初始版本

This commit is contained in:
2026-04-23 13:49:53 +08:00
parent c1d6ebd38c
commit ac718a463a
257 changed files with 265681 additions and 0 deletions
+170
View File
@@ -0,0 +1,170 @@
/**
*******************************************************************************
* @file hc32_ll.c
* @brief This file provides firmware functions to low-level drivers (LL).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_Global Global
* @{
*/
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup LL_Global_Functions LL Global Functions
* @{
*/
void LL_PERIPH_WE(uint32_t u32Peripheral)
{
#if (LL_EFM_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_EFM) != 0UL) {
/* Unlock all EFM registers */
EFM_REG_Unlock();
}
#endif
#if (LL_FCG_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_FCG) != 0UL) {
/* Unlock FCG register */
PWC_FCG0_REG_Unlock();
}
#endif
#if (LL_GPIO_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_GPIO) != 0UL) {
/* Unlock GPIO register: PSPCR, PCCR, PINAER, PCRxy, PFSRxy */
GPIO_REG_Unlock();
}
#endif
#if (LL_MPU_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_MPU) != 0UL) {
/* Unlock all MPU registers */
MPU_REG_Unlock();
}
#endif
#if (LL_PWC_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_LVD) != 0UL) {
/* Unlock LVD registers, @ref PWC_REG_Write_Unlock_Code for details */
PWC_REG_Unlock(PWC_UNLOCK_CODE2);
}
#endif
#if (LL_PWC_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_PWC_CLK_RMU) != 0UL) {
/* Unlock PWC, CLK, RMU registers, @ref PWC_REG_Write_Unlock_Code for details */
PWC_REG_Unlock(PWC_UNLOCK_CODE0 | PWC_UNLOCK_CODE1);
}
#endif
#if (LL_SRAM_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_SRAM) != 0UL) {
/* Unlock SRAM register: WTCR, CKCR */
SRAM_REG_Unlock();
}
#endif
}
void LL_PERIPH_WP(uint32_t u32Peripheral)
{
#if (LL_EFM_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_EFM) != 0UL) {
/* Lock all EFM registers */
EFM_REG_Lock();
}
#endif
#if (LL_FCG_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_FCG) != 0UL) {
/* Lock FCG register */
PWC_FCG0_REG_Lock();
}
#endif
#if (LL_GPIO_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_GPIO) != 0UL) {
/* Unlock GPIO register: PSPCR, PCCR, PINAER, PCRxy, PFSRxy */
GPIO_REG_Lock();
}
#endif
#if (LL_MPU_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_MPU) != 0UL) {
/* Lock all MPU registers */
MPU_REG_Lock();
}
#endif
#if (LL_PWC_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_LVD) != 0UL) {
/* Lock LVD registers, @ref PWC_REG_Write_Unlock_Code for details */
PWC_REG_Lock(PWC_UNLOCK_CODE2);
}
#endif
#if (LL_PWC_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_PWC_CLK_RMU) != 0UL) {
/* Lock PWC, CLK, RMU registers, @ref PWC_REG_Write_Unlock_Code for details */
PWC_REG_Lock(PWC_UNLOCK_CODE0 | PWC_UNLOCK_CODE1);
}
#endif
#if (LL_SRAM_ENABLE == DDL_ON)
if ((u32Peripheral & LL_PERIPH_SRAM) != 0UL) {
/* Lock SRAM register: WTCR, CKCR */
SRAM_REG_Lock();
}
#endif
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
File diff suppressed because it is too large Load Diff
+307
View File
@@ -0,0 +1,307 @@
/**
*******************************************************************************
* @file hc32_ll_aes.c
* @brief This file provides firmware functions to manage the Advanced Encryption
* Standard(AES).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2023-06-30 CDT Add API AES_DeInit()
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_aes.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_AES AES
* @brief AES Driver Library
* @{
*/
#if (LL_AES_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup AES_Local_Macros AES Local Macros
* @{
*/
/* Delay count for timeout */
#define AES_TIMEOUT (30000UL)
/* AES block size */
#define AES_BLOCK_SIZE (16U)
/**
* @defgroup AES_Check_Parameters_Validity AES Check Parameters Validity
* @{
*/
#define IS_AES_KEY_SIZE(x) ((x) == AES_KEY_SIZE_16BYTE)
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup AES_Local_Functions AES Local Functions
* @{
*/
/**
* @brief Write the input buffer in data register.
* @param [in] pu8SrcData Point to the source data buffer.
* @retval None
*/
static void AES_WriteData(const uint8_t *pu8SrcData)
{
uint8_t i;
__IO uint32_t *regDR = &CM_AES->DR0;
const uint32_t *pu32Data = (const uint32_t *)((uint32_t)pu8SrcData);
for (i = 0U; i < 4U; i++) {
regDR[i] = pu32Data[i];
}
}
/**
* @brief Read the from data register.
* @param [out] pu8Result Point to the result buffer.
* @retval None
*/
static void AES_ReadData(uint8_t *pu8Result)
{
uint8_t i;
__IO uint32_t *regDR = &CM_AES->DR0;
uint32_t *pu32Result = (uint32_t *)((uint32_t)pu8Result);
for (i = 0U; i < 4U; i++) {
pu32Result[i] = regDR[i];
}
}
/**
* @brief Write the input buffer in key register.
* @param [in] pu8Key Pointer to the key buffer.
* @param [in] u8KeySize AES key size. This parameter can be a value of @ref AES_Key_Size
* @retval None
*/
static void AES_WriteKey(const uint8_t *pu8Key, uint8_t u8KeySize)
{
uint8_t i;
uint8_t u8KeyWordSize = u8KeySize / 4U;
__IO uint32_t *regKR = &CM_AES->KR0;
const uint32_t *pu32Key = (const uint32_t *)((uint32_t)pu8Key);
for (i = 0U; i < u8KeyWordSize; i++) {
regKR[i] = pu32Key[i];
}
}
/**
* @brief Wait AES operation done.
* @param None
* @retval None
*/
static int32_t AES_WaitDone(void)
{
__IO uint32_t u32TimeCount = 0UL;
int32_t i32Ret = LL_OK;
while (bCM_AES->CR_b.START != 0UL) {
if (u32TimeCount++ >= AES_TIMEOUT) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
}
return i32Ret;
}
/**
* @}
*/
/**
* @defgroup AES_Global_Functions AES Global Functions
* @{
*/
/**
* @brief AES encryption.
* @param [in] pu8Plaintext Buffer of the plaintext(the source data which will be encrypted).
* @param [in] u32PlaintextSize Length of plaintext in bytes.
* @param [in] pu8Key Pointer to the AES key.
* @param [in] u8KeySize AES key size. This parameter can be a value of @ref AES_Key_Size
* @param [out] pu8Ciphertext Buffer of the ciphertext.
* @retval int32_t:
* - LL_OK: Encrypt successfully.
* - LL_ERR_INVD_PARAM: Invalid parameter.
* - LL_TIMEOUT: Encrypt timeout.
*/
int32_t AES_Encrypt(const uint8_t *pu8Plaintext, uint32_t u32PlaintextSize,
const uint8_t *pu8Key, uint8_t u8KeySize,
uint8_t *pu8Ciphertext)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
uint32_t u32Index = 0UL;
DDL_ASSERT(IS_AES_KEY_SIZE(u8KeySize));
DDL_ASSERT((u32PlaintextSize % AES_BLOCK_SIZE) == 0U);
if ((pu8Plaintext != NULL) && (u32PlaintextSize > 0UL) && \
(pu8Key != NULL) && (pu8Ciphertext != NULL)) {
AES_WriteKey(pu8Key, u8KeySize);
/* Set AES encrypt. */
WRITE_REG32(bCM_AES->CR_b.MODE, 0UL);
while (u32Index < u32PlaintextSize) {
AES_WriteData(&pu8Plaintext[u32Index]);
/* Start AES calculating. */
WRITE_REG32(bCM_AES->CR_b.START, 1UL);
/* Wait for AES to stop */
i32Ret = AES_WaitDone();
if (i32Ret != LL_OK) {
break;
}
AES_ReadData(&pu8Ciphertext[u32Index]);
u32Index += AES_BLOCK_SIZE;
}
}
return i32Ret;
}
/**
* @brief AES decryption.
* @param [in] pu8Ciphertext Buffer of the Ciphertext(the source data which will be decrypted).
* @param [in] u32CiphertextSize Length of ciphertext in bytes.
* @param [in] pu8Key Pointer to the AES key.
* @param [in] u8KeySize AES key size. This parameter can be a value of @ref AES_Key_Size
* @param [out] pu8Plaintext Buffer of the plaintext.
* @retval int32_t:
* - LL_OK: Decrypt successfully.
* - LL_ERR_INVD_PARAM: Invalid parameter.
* - LL_TIMEOUT: Decrypt timeout.
*/
int32_t AES_Decrypt(const uint8_t *pu8Ciphertext, uint32_t u32CiphertextSize,
const uint8_t *pu8Key, uint8_t u8KeySize,
uint8_t *pu8Plaintext)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
uint32_t u32Index = 0UL;
DDL_ASSERT(IS_AES_KEY_SIZE(u8KeySize));
DDL_ASSERT((u32CiphertextSize % AES_BLOCK_SIZE) == 0U);
if ((pu8Plaintext != NULL) && (u32CiphertextSize > 0UL) && \
(pu8Key != NULL) && (pu8Ciphertext != NULL)) {
AES_WriteKey(pu8Key, u8KeySize);
/* Set AES decrypt. */
WRITE_REG32(bCM_AES->CR_b.MODE, 1UL);
while (u32Index < u32CiphertextSize) {
AES_WriteData(&pu8Ciphertext[u32Index]);
/* Start AES calculating. */
WRITE_REG32(bCM_AES->CR_b.START, 1UL);
/* Wait for AES to stop */
i32Ret = AES_WaitDone();
if (i32Ret != LL_OK) {
break;
}
AES_ReadData(&pu8Plaintext[u32Index]);
u32Index += AES_BLOCK_SIZE;
}
}
return i32Ret;
}
/**
* @brief De-Initialize AES function.
* @param None
* @retval int32_t:
* - LL_OK: De-Initialize success.
* - LL_ERR_TIMEOUT: Timeout.
*/
int32_t AES_DeInit(void)
{
int32_t i32Ret = LL_OK;
__IO uint32_t u32TimeOut = 0U;
uint8_t i;
__IO uint32_t *regDR = &CM_AES->DR0;
__IO uint32_t *regKR = &CM_AES->KR0;
/* Wait generating done */
while (0UL != READ_REG32(bCM_AES->CR_b.START)) {
u32TimeOut++;
if (u32TimeOut > AES_TIMEOUT) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
}
if (LL_OK == i32Ret) {
/* Configures the registers to reset value. */
WRITE_REG32(CM_AES->CR, 0x00000000UL);
for (i = 0U; i < 4U; i++) {
regDR[i] = 0x00000000UL;
}
for (i = 0U; i < 8U; i++) {
regKR[i] = 0x00000000UL;
}
}
return i32Ret;
}
/**
* @}
*/
#endif /* LL_AES_ENABLE */
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/
+179
View File
@@ -0,0 +1,179 @@
/**
*******************************************************************************
* @file hc32_ll_aos.c
* @brief This file provides firmware functions to manage the AOS.
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2023-01-15 CDT Macro name modified: from IS_AOS_TRIG_SEL to IS_AOS_TARGET
Modified parameters name and comments of AOS_CommonTriggerCmd() and AOS_SetTriggerEventSrc()
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_aos.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_AOS AOS
* @brief AOS Driver Library
* @{
*/
#if (LL_AOS_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup AOS_Local_Macros AOS Local Macros
* @{
*/
/**
* @defgroup AOS_Common_Trigger_ID_Validity AOS Common Trigger ID Validity
* @{
*/
#define IS_AOS_COMM_TRIG(x) \
( ((x) != 0UL) && \
((x) | AOS_COMM_TRIG_MASK) == AOS_COMM_TRIG_MASK)
/**
* @}
*/
/**
* @defgroup AOS_Target_Select_Validity AOS Target Select Validity
* @{
*/
#define IS_AOS_TARGET(x) \
( ((x) == AOS_DCU1) || \
((x) == AOS_DCU2) || \
((x) == AOS_DCU3) || \
((x) == AOS_DCU4) || \
((x) == AOS_DMA1_0) || \
((x) == AOS_DMA1_1) || \
((x) == AOS_DMA1_2) || \
((x) == AOS_DMA1_3) || \
((x) == AOS_DMA2_0) || \
((x) == AOS_DMA2_1) || \
((x) == AOS_DMA2_2) || \
((x) == AOS_DMA2_3) || \
((x) == AOS_DMA_RC) || \
((x) == AOS_TMR6_0) || \
((x) == AOS_TMR6_1) || \
((x) == AOS_TMR0) || \
((x) == AOS_EVTPORT12) || \
((x) == AOS_EVTPORT34) || \
((x) == AOS_TMRA_0) || \
((x) == AOS_TMRA_1) || \
((x) == AOS_OTS) || \
((x) == AOS_ADC1_0) || \
((x) == AOS_ADC1_1) || \
((x) == AOS_ADC2_0) || \
((x) == AOS_ADC2_1) || \
((x) == AOS_COMM_1) || \
((x) == AOS_COMM_2))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup AOS_Global_Functions AOS Global Functions
* @{
*/
/**
* @brief Common trigger function command
* @param [in] u32Target AOS target that need to be triggered by common trigger @ref AOS_Target_Select in details
* @param [in] u32CommonTrigger Common trigger ID
* This parameter can be one of the following values:
* @arg AOS_COMM_TRIG1: Common trigger 1.
* @arg AOS_COMM_TRIG2: Common trigger 2.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void AOS_CommonTriggerCmd(uint32_t u32Target, uint32_t u32CommonTrigger, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_AOS_TARGET(u32Target));
DDL_ASSERT(IS_AOS_COMM_TRIG(u32CommonTrigger));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(*(__IO uint32_t *)u32Target, u32CommonTrigger);
} else {
CLR_REG32_BIT(*(__IO uint32_t *)u32Target, u32CommonTrigger);
}
}
/**
* @brief Set trigger event source
* @param [in] u32Target AOS target that need to be triggered by AOS source @ref AOS_Target_Select in details
* @param [in] enSource AOS source that trigger the AOS target @ref en_event_src_t in details
* @retval None
*/
void AOS_SetTriggerEventSrc(uint32_t u32Target, en_event_src_t enSource)
{
DDL_ASSERT(IS_AOS_TARGET(u32Target));
MODIFY_REG32(*(__IO uint32_t *)u32Target, AOS_TRIG_SEL_MASK, enSource);
}
/**
* @}
*/
#endif /* LL_AOS_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+703
View File
@@ -0,0 +1,703 @@
/**
*******************************************************************************
* @file hc32_ll_cmp.c
* @brief This file provides firmware functions to manage the Comparator(CMP).
*
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2022-06-30 CDT Modify macro define for API
2023-01-15 CDT Code refine for scan function
2023-06-30 CDT Modify typo
2023-09-30 CDT Add assert for IEN bit in GetCmpFuncStatusAndDisFunc function
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_cmp.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_CMP CMP
* @brief CMP Driver Library
* @{
*/
#if (LL_CMP_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup CMP_Local_Macros CMP Local Macros
* @{
*/
/**
* @defgroup CMP_Check_Parameters_Validity CMP Check Parameters Validity
* @{
*/
#define IS_CMP_UNIT(x) \
( ((x) == CM_CMP1) || \
((x) == CM_CMP2) || \
((x) == CM_CMP3))
#define CMP1_INP4_MASK (CMP1_POSITIVE_PGAO | \
CMP1_POSITIVE_PGAO_BP | \
CMP1_POSITIVE_CMP1_INP4)
#define CMP1_POSITIVE_MASK (CMP_POSITIVE_NONE | \
CMP1_POSITIVE_CMP1_INP1 | \
CMP1_POSITIVE_CMP1_INP2 | \
CMP1_POSITIVE_CMP1_INP3 | \
CMP1_INP4_MASK)
#define CMP2_INP4_MASK (CMP2_POSITIVE_PGAO | \
CMP2_POSITIVE_PGAO_BP)
#define CMP2_POSITIVE_MASK (CMP_POSITIVE_NONE | \
CMP2_POSITIVE_CMP2_INP1 | \
CMP2_POSITIVE_CMP2_INP2 | \
CMP2_POSITIVE_CMP2_INP3 | \
CMP2_INP4_MASK)
#define CMP3_POSITIVE_MASK (CMP_POSITIVE_NONE | \
CMP3_POSITIVE_CMP3_INP1 | \
CMP3_POSITIVE_CMP3_INP2 | \
CMP3_POSITIVE_CMP3_INP3 | \
CMP3_POSITIVE_CMP3_INP4)
#define IS_CMP1_POSITIVE_IN(x) \
( (((x) & (~CMP1_POSITIVE_MASK)) == 0U) && \
((((x) & CMP1_INP4_MASK) == 0U) || \
(((x) & CMP1_INP4_MASK) == CMP1_POSITIVE_PGAO) || \
(((x) & CMP1_INP4_MASK) == CMP1_POSITIVE_PGAO_BP) || \
(((x) & CMP1_INP4_MASK) == CMP1_POSITIVE_CMP1_INP4)))
#define IS_CMP2_POSITIVE_IN(x) \
( (((x) & (~CMP2_POSITIVE_MASK)) == 0U) && \
((((x) & CMP2_INP4_MASK) == 0U) || \
(((x) & CMP2_INP4_MASK) == CMP2_POSITIVE_PGAO) || \
(((x) & CMP2_INP4_MASK) == CMP2_POSITIVE_PGAO_BP)))
#define IS_CMP3_POSITIVE_IN(x) \
( ((x) & (~CMP3_POSITIVE_MASK)) == 0U)
#define IS_CMP_NEGATIVE_IN(x) \
( ((x) == CMP_NEGATIVE_NONE) || \
((x) == CMP_NEGATIVE_INM1) || \
((x) == CMP_NEGATIVE_INM2) || \
((x) == CMP_NEGATIVE_INM3) || \
((x) == CMP_NEGATIVE_INM4))
#define IS_CMP_SCAN_STABLE(x) \
( (x) <= 0x0FU)
#define IS_CMP_SCAN_PERIOD(x) \
( ((x) >= 0x0FU) && \
((x) <= 0xFFU))
#define IS_CMP_8_BIT_DAC_CH(x) \
( ((x) == CMP_8BITDAC_CH1) || \
((x) == CMP_8BITDAC_CH2))
#define IS_CMP_8_BIT_DAC_DATA(x) \
( (x) <= 0xFFU)
#define IS_CMP_8_BIT_DAC_SW(x) \
( ((x) == CMP_ADC_REF_VREF) || \
((x) == CMP_ADC_REF_DA2) || \
((x) == CMP_ADC_REF_DA1))
#define IS_CMP_OUT_POLARITY(x) \
( ((x) == CMP_OUT_INVT_OFF) || \
((x) == CMP_OUT_INVT_ON))
#define IS_CMP_OUT_FILTER(x) \
( ((x) == CMP_OUT_FILTER_NONE) || \
((x) == CMP_OUT_FILTER_CLK) || \
((x) == CMP_OUT_FILTER_CLK_DIV2) || \
((x) == CMP_OUT_FILTER_CLK_DIV4) || \
((x) == CMP_OUT_FILTER_CLK_DIV8) || \
((x) == CMP_OUT_FILTER_CLK_DIV16) || \
((x) == CMP_OUT_FILTER_CLK_DIV32) || \
((x) == CMP_OUT_FILTER_CLK_DIV64))
#define IS_CMP_OUT_DETECT_EDGE(x) \
( ((x) == CMP_DETECT_EDGS_NONE) || \
((x) == CMP_DETECT_EDGS_RISING) || \
((x) == CMP_DETECT_EDGS_FALLING) || \
((x) == CMP_DETECT_EDGS_BOTH))
/**
* @}
*/
#define CMP_DADC_RVADC_REG_UNLOCK (0x5500U)
#define CMP_SCAN_PERIOD_IMME (0x05U)
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup CMP_Local_Functions CMP Local Functions
* @{
*/
/**
* @brief Delay function, delay us approximately
* @param [in] u32Count us
* @retval None
*/
static void CMP_DelayUS(uint32_t u32Count)
{
__IO uint32_t i;
const uint32_t u32Cyc = HCLK_VALUE / 10000000UL;
while (u32Count-- > 0UL) {
i = u32Cyc;
while (i-- > 0UL) {
;
}
}
}
/**
* @brief Get CMP function status and disable CMP
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @retval uint16_t The register value
*/
static uint16_t GetCmpFuncStatusAndDisFunc(CM_CMP_TypeDef *CMPx)
{
uint16_t u16temp;
/* It is possible that the interrupt may occurs after CMP status switch. */
DDL_ASSERT(READ_REG8_BIT(CMPx->CTRL, CMP_CTRL_IEN) == 0U);
/* Read CMP status */
u16temp = READ_REG16_BIT(CMPx->CTRL, CMP_CTRL_CMPON);
/* Stop CMP function */
CLR_REG16_BIT(CMPx->CTRL, CMP_CTRL_CMPON);
return u16temp;
}
/**
* @brief Recover CMP function status
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] u16CmpFuncStatus CMP function status backup value
* @retval None
*/
static void RecoverCmpFuncStatus(CM_CMP_TypeDef *CMPx, uint16_t u16CmpFuncStatus)
{
if (u16CmpFuncStatus != 0U) {
/* Recover CMP status */
MODIFY_REG16(CMPx->CTRL, CMP_CTRL_CMPON, u16CmpFuncStatus);
/* Delay 1us */
CMP_DelayUS(1U);
}
}
/**
* @}
*/
/**
* @defgroup CMP_Global_Functions CMP Global Functions
* @{
*/
/**
* @brief Initialize structure stc_cmp_init_t variable with default value.
* @param [in] pstcCmpInit Pointer to a structure variable which will be initialized. @ref stc_cmp_init_t
* @retval int32_t
* - LL_OK: Success
* - LL_ERR_INVD_PARAM: Parameter error
*/
int32_t CMP_StructInit(stc_cmp_init_t *pstcCmpInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (pstcCmpInit != NULL) {
pstcCmpInit->u16PositiveInput = CMP_POSITIVE_NONE;
pstcCmpInit->u16NegativeInput = CMP_NEGATIVE_NONE;
pstcCmpInit->u16OutPolarity = CMP_OUT_INVT_OFF;
pstcCmpInit->u16OutDetectEdge = CMP_DETECT_EDGS_NONE;
pstcCmpInit->u16OutFilter = CMP_OUT_FILTER_NONE;
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief De-initialize CMP unit
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @retval None
*/
void CMP_DeInit(CM_CMP_TypeDef *CMPx)
{
DDL_ASSERT(IS_CMP_UNIT(CMPx));
CLR_REG16(CMPx->CTRL);
CLR_REG16(CMPx->VLTSEL);
WRITE_REG16(CMPx->CVSSTB, 0x0005U);
WRITE_REG16(CMPx->CVSPRD, 0x000FU);
CLR_REG16(CM_CMPCR->DADR1);
CLR_REG16(CM_CMPCR->DADR2);
CLR_REG16(CM_CMPCR->DACR);
CLR_REG16(CM_CMPCR->RVADC);
}
/**
* @brief CMP normal mode initialize
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] pstcCmpInit CMP function base parameter structure
* @arg pstcCmpInit->u16PositiveInput: @ref CMP_Positive_Input_Select
* @arg pstcCmpInit->u16NegativeInput: @ref CMP_Negative_Input_Select
* @arg pstcCmpInit->u16OutPolarity: @ref CMP_Out_Polarity_Select
* @arg pstcCmpInit->u16OutDetectEdge: @ref CMP_Out_Detect_Edge_Select
* @arg pstcCmpInit->u16OutFilter: @ref CMP_Out_Filter
* @retval int32_t
* - LL_OK: Success
* - LL_ERR_INVD_PARAM: Parameter error
*/
int32_t CMP_NormalModeInit(CM_CMP_TypeDef *CMPx, const stc_cmp_init_t *pstcCmpInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
/* Check CMPx instance and configuration structure*/
if (NULL != pstcCmpInit) {
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
DDL_ASSERT(IS_CMP_OUT_POLARITY(pstcCmpInit->u16OutPolarity));
DDL_ASSERT(IS_CMP_OUT_DETECT_EDGE(pstcCmpInit->u16OutDetectEdge));
DDL_ASSERT(IS_CMP_OUT_FILTER(pstcCmpInit->u16OutFilter));
if (CM_CMP1 == CMPx) {
DDL_ASSERT(IS_CMP1_POSITIVE_IN(pstcCmpInit->u16PositiveInput));
} else if (CM_CMP2 == CMPx) {
DDL_ASSERT(IS_CMP2_POSITIVE_IN(pstcCmpInit->u16PositiveInput));
} else {
DDL_ASSERT(IS_CMP3_POSITIVE_IN(pstcCmpInit->u16PositiveInput));
}
DDL_ASSERT(IS_CMP_NEGATIVE_IN(pstcCmpInit->u16NegativeInput));
/* Stop CMP compare */
CLR_REG16_BIT(CMPx->CTRL, CMP_CTRL_CMPON);
/* Set voltage in */
WRITE_REG16(CMPx->VLTSEL, pstcCmpInit->u16PositiveInput | pstcCmpInit->u16NegativeInput);
/* Delay 1us*/
CMP_DelayUS(1U);
/* Start CMP compare */
SET_REG16_BIT(CMPx->CTRL, CMP_CTRL_CMPON);
/* Delay 1us*/
CMP_DelayUS(1U);
/* Set output filter and output detect edge and output polarity */
MODIFY_REG16(CMPx->CTRL, CMP_CTRL_FLTSL | CMP_CTRL_EDGSL | CMP_CTRL_INV, (pstcCmpInit->u16OutFilter | pstcCmpInit->u16OutDetectEdge | pstcCmpInit->u16OutPolarity));
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief Voltage compare function command
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void CMP_FuncCmd(CM_CMP_TypeDef *CMPx, en_functional_state_t enNewState)
{
/* Check CMPx instance */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG16_BIT(CMPx->CTRL, CMP_CTRL_CMPON);
/* Delay 1us*/
CMP_DelayUS(1U);
} else {
CLR_REG16_BIT(CMPx->CTRL, CMP_CTRL_CMPON);
}
}
/**
* @brief Voltage compare interrupt function command
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void CMP_IntCmd(CM_CMP_TypeDef *CMPx, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG16_BIT(CMPx->CTRL, CMP_CTRL_IEN);
} else {
CLR_REG16_BIT(CMPx->CTRL, CMP_CTRL_IEN);
}
}
/**
* @brief Voltage compare output command
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void CMP_CompareOutCmd(CM_CMP_TypeDef *CMPx, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG16_BIT(CMPx->CTRL, CMP_CTRL_CMPOE);
} else {
CLR_REG16_BIT(CMPx->CTRL, CMP_CTRL_CMPOE);
}
}
/**
* @brief Voltage compare output port VCOUT function command
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void CMP_PinVcoutCmd(CM_CMP_TypeDef *CMPx, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG16_BIT(CMPx->CTRL, CMP_CTRL_OUTEN);
} else {
CLR_REG16_BIT(CMPx->CTRL, CMP_CTRL_OUTEN);
}
}
/**
* @brief Voltage compare result flag read
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @retval An @ref en_flag_status_t enumeration type value.
* In normal mode
* - RESET: compare voltage < reference voltage
* - SET: compare voltage > reference voltage
* In Window mode
* - RESET: compare voltage < reference low voltage or compare voltage > reference high voltage
* - SET: reference low voltage < compare voltage < reference high voltage
*/
en_flag_status_t CMP_GetStatus(const CM_CMP_TypeDef *CMPx)
{
en_flag_status_t enRet;
/* Check CMPx instance */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
enRet = (READ_REG16_BIT(CMPx->OUTMON, CMP_OUTMON_OMON) != 0U) ? SET : RESET;
return enRet;
}
/**
* @brief Set output detect edge
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] u8CmpEdges CMP output detect edge selection. @ref CMP_Out_Detect_Edge_Select
* @retval None
*/
void CMP_SetOutDetectEdge(CM_CMP_TypeDef *CMPx, uint8_t u8CmpEdges)
{
uint16_t u16temp;
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
DDL_ASSERT(IS_CMP_OUT_DETECT_EDGE(u8CmpEdges));
/* Read CMP status */
u16temp = GetCmpFuncStatusAndDisFunc(CMPx);
/* CMP output detect edge selection */
MODIFY_REG16(CMPx->CTRL, CMP_CTRL_EDGSL, u8CmpEdges);
/* Recover CMP function */
RecoverCmpFuncStatus(CMPx, u16temp);
}
/**
* @brief Set output filter
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] u8CmpFilter CMP output filter selection. @ref CMP_Out_Filter
* @retval None
*/
void CMP_SetOutFilter(CM_CMP_TypeDef *CMPx, uint8_t u8CmpFilter)
{
uint16_t u16temp;
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
DDL_ASSERT(IS_CMP_OUT_FILTER(u8CmpFilter));
/* Read CMP status */
u16temp = GetCmpFuncStatusAndDisFunc(CMPx);
/* CMP output filter selection */
MODIFY_REG16(CMPx->CTRL, CMP_CTRL_FLTSL, u8CmpFilter);
/* Recover CMP function */
RecoverCmpFuncStatus(CMPx, u16temp);
}
/**
* @brief Set output polarity
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] u16CmpPolarity CMP output polarity selection. @ref CMP_Out_Polarity_Select
* @retval None
*/
void CMP_SetOutPolarity(CM_CMP_TypeDef *CMPx, uint16_t u16CmpPolarity)
{
uint16_t u16temp;
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
DDL_ASSERT(IS_CMP_OUT_POLARITY(u16CmpPolarity));
/* Read CMP status */
u16temp = GetCmpFuncStatusAndDisFunc(CMPx);
/* CMP output polarity selection */
MODIFY_REG16(CMPx->CTRL, CMP_CTRL_INV, u16CmpPolarity);
/* Recover CMP function */
RecoverCmpFuncStatus(CMPx, u16temp);
}
/**
* @brief Set positive in(compare voltage)
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] u16PositiveInput @ref CMP_Positive_Input_Select
* @retval None
*/
void CMP_SetPositiveInput(CM_CMP_TypeDef *CMPx, uint16_t u16PositiveInput)
{
uint16_t u16temp;
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
if (CM_CMP1 == CMPx) {
DDL_ASSERT(IS_CMP1_POSITIVE_IN(u16PositiveInput));
} else if (CM_CMP2 == CMPx) {
DDL_ASSERT(IS_CMP2_POSITIVE_IN(u16PositiveInput));
} else {
DDL_ASSERT(IS_CMP3_POSITIVE_IN(u16PositiveInput));
}
/* Read CMP status */
u16temp = GetCmpFuncStatusAndDisFunc(CMPx);
/* Set voltage in */
MODIFY_REG16(CMPx->VLTSEL, (CMP_VLTSEL_CVSL | CMP_VLTSEL_C4SL), u16PositiveInput);
/* Recover CMP function */
RecoverCmpFuncStatus(CMPx, u16temp);
}
/**
* @brief Set negative in(reference voltage)
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] u16NegativeInput @ref CMP_Negative_Input_Select
* @retval None
*/
void CMP_SetNegativeInput(CM_CMP_TypeDef *CMPx, uint16_t u16NegativeInput)
{
uint16_t u16temp;
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
DDL_ASSERT(IS_CMP_NEGATIVE_IN(u16NegativeInput));
/* Read CMP status */
u16temp = GetCmpFuncStatusAndDisFunc(CMPx);
/* Set voltage in */
MODIFY_REG16(CMPx->VLTSEL, CMP_VLTSEL_RVSL, u16NegativeInput);
/* Recover CMP function */
RecoverCmpFuncStatus(CMPx, u16temp);
}
/**
* @brief Get CMP scan INP source
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @retval An uint32_t value @ref CMP_Scan_Inp_Status
*/
uint32_t CMP_GetScanInpSrc(CM_CMP_TypeDef *CMPx)
{
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
return (uint32_t)READ_REG16_BIT(CMPx->OUTMON, CMP_OUTMON_CVST);
}
/**
* @brief Get CMP scan function stable time and period configuration
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] u16Stable The CMP stable time = T(CMP clock) x u16Stable, The stable time is recommended
* greater than 100nS
* @arg range from 0x00U to 0x0FU
* @param [in] u16Period CMP scan period = T(CMP clock) x u16Period
* @arg range from 0x0F to 0xFF
* @retval int32_t
* - LL_OK: Success
* - LL_ERR_INVD_PARAM: Parameter error
* @note 1. u16Period > (u16Stable + u16OutFilter * 4 + CMP_SCAN_PERIOD_IMME)
* u16OutFilter is configured in CMP_NormalModeInit() function.
*/
int32_t CMP_ScanTimeConfig(CM_CMP_TypeDef *CMPx, uint16_t u16Stable, uint16_t u16Period)
{
uint16_t u16Fltsl;
uint16_t u16FltslDiv;
int32_t i32Ret = LL_OK;
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
DDL_ASSERT(IS_CMP_SCAN_STABLE(u16Stable));
DDL_ASSERT(IS_CMP_SCAN_PERIOD(u16Period));
u16Fltsl = READ_REG16_BIT(CMPx->CTRL, CMP_CTRL_FLTSL);
if (0U != u16Fltsl) {
u16FltslDiv = ((uint16_t)1U << (u16Fltsl - 1U));
} else {
u16FltslDiv = 0U;
}
if (u16Period <= (u16Stable + u16FltslDiv * 4U + CMP_SCAN_PERIOD_IMME)) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
WRITE_REG16(CMPx->CVSSTB, u16Stable);
WRITE_REG16(CMPx->CVSPRD, u16Period);
}
return i32Ret;
}
/**
* @brief CMP scan function command
* @param [in] CMPx Pointer to CMP instance register base
* @arg CM_CMPx
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void CMP_ScanCmd(CM_CMP_TypeDef *CMPx, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_CMP_UNIT(CMPx));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
MODIFY_REG16(CMPx->CTRL, CMP_CTRL_CVSEN, (uint16_t)enNewState << CMP_CTRL_CVSEN_POS);
}
/**
* @brief CMP 8 bit DAC reference voltage command
* @param [in] u8Ch The DAC channel @ref CMP_8Bit_Dac_Ch
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void CMP_8BitDAC_Cmd(uint8_t u8Ch, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_CMP_8_BIT_DAC_CH(u8Ch));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG16_BIT(CM_CMPCR->DACR, u8Ch);
} else {
CLR_REG16_BIT(CM_CMPCR->DACR, u8Ch);
}
}
/**
* @brief CMP 8 bit DAC connect to ADC reference voltage command
* @param [in] u16AdcRefSw @ref CMP_8BitDAC_Adc_Ref_Switch
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void CMP_8BitDAC_AdcRefCmd(uint16_t u16AdcRefSw, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_CMP_8_BIT_DAC_SW(u16AdcRefSw));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
uint16_t WrTmp;
if (ENABLE == enNewState) {
WrTmp = u16AdcRefSw;
} else {
WrTmp = 0U;
}
WRITE_REG16(CM_CMPCR->RVADC, CMP_DADC_RVADC_REG_UNLOCK);
WRITE_REG16(CM_CMPCR->RVADC, WrTmp);
}
/**
* @brief Write raw data to DAC
* @param [in] u8Ch DAC channel @ref CMP_8Bit_Dac_Ch
* @param [in] u16DACData DAC voltage data
* @retval None
*/
void CMP_8BitDAC_WriteData(uint8_t u8Ch, uint16_t u16DACData)
{
DDL_ASSERT(IS_CMP_8_BIT_DAC_CH(u8Ch));
DDL_ASSERT(IS_CMP_8_BIT_DAC_DATA(u16DACData));
if (CMP_8BITDAC_CH1 == u8Ch) {
WRITE_REG16(CM_CMPCR->DADR1, u16DACData);
} else {
WRITE_REG16(CM_CMPCR->DADR2, u16DACData);
}
}
/**
* @}
*/
#endif /* LL_CMP_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+639
View File
@@ -0,0 +1,639 @@
/**
*******************************************************************************
* @file hc32_ll_crc.c
* @brief This file provides firmware functions to manage the Cyclic Redundancy
* Check(CRC).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2022-06-30 CDT Add waiting time after write CRC data
2023-06-30 CDT Reconstruct interface function relate to calculate CRC
Optimize CRC_DeInit function
2023-09-30 CDT Delete and modify some of group/function relate to calculate CRC
Modify typo
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_crc.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_CRC CRC
* @brief Cyclic Redundancy Check Driver Library
* @{
*/
#if (LL_CRC_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup CRC_Local_Macros CRC Local Macros
* @{
*/
/**
* @defgroup CRC_Check_Parameters_Validity CRC Check Parameters Validity
* @{
*/
/*! Parameter validity check for CRC protocol. */
#define IS_CRC_PROTOCOL(x) \
( ((x) == CRC_CRC16) || \
((x) == CRC_CRC32))
/*! Parameter validity check for CRC data width. */
#define IS_CRC_DATA_WIDTH(x) \
( ((x) == CRC_DATA_WIDTH_8BIT) || \
((x) == CRC_DATA_WIDTH_16BIT) || \
((x) == CRC_DATA_WIDTH_32BIT))
/*! Parameter validity check for REFIN. */
#define IS_CRC_REFIN(x) \
( ((x) == CRC_REFIN_ENABLE) || \
((x) == CRC_REFIN_DISABLE))
/*! Parameter validity check for REFOUT. */
#define IS_CRC_REFOUT(x) \
( ((x) == CRC_REFOUT_ENABLE) || \
((x) == CRC_REFOUT_DISABLE))
/*! Parameter validity check for XOROUT. */
#define IS_CRC_XOROUT(x) \
( ((x) == CRC_XOROUT_ENABLE) || \
((x) == CRC_XOROUT_DISABLE))
/**
* @}
*/
/**
* @defgroup CRC_Registers_Reset_Value_definition CRC Registers Reset Value
* @{
*/
#define CRC_CR_RST_VALUE (0x001CUL)
/**
* @}
*/
/**
* @defgroup CRC_DATA_Register_Address CRC Data Register Address
* @{
*/
#define CRC_DATA_ADDR ((uint32_t)(&CM_CRC->DAT0))
/**
* @}
*/
/**
* @defgroup CRC_Calculate_Clock_Count CRC Calculate Clock Count
* @{
*/
#define CRC_CALC_CLK_COUNT (10UL)
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup CRC_Local_Functions CRC Local Functions
* @{
*/
/**
* @brief Convert CRC value.
* @param [in] u32CrcValue The CRC value of CRC16 or CRC32.
* @retval the converted CRC value
*/
static uint32_t CRC_ConvertCrcValue(uint32_t u32CrcValue)
{
uint8_t i;
uint8_t u8Size;
uint8_t u8Offset;
uint32_t u32Temp;
uint32_t u32Config;
uint32_t u32FinalCrcValue = u32CrcValue;
const uint32_t u32ConvertFlag = (CRC_REFIN_ENABLE | CRC_REFOUT_ENABLE | CRC_XOROUT_ENABLE);
u32Config = READ_REG32(CM_CRC->CR);
if ((u32Config & u32ConvertFlag) != u32ConvertFlag) {
if ((u32Config & CRC_CR_CR) == CRC_CRC32) {
u8Size = 32U;
} else {
u8Size = 16U;
}
if ((u32Config & CRC_CR_REFOUT) == CRC_REFOUT_DISABLE) {
u32FinalCrcValue = __RBIT(u32FinalCrcValue); /* Bits reversing. */
if (u8Size == 16U) {
u32FinalCrcValue >>= 16U;
u32FinalCrcValue &= 0xFFFFUL;
}
}
if ((u32Config & CRC_CR_XOROUT) == CRC_XOROUT_DISABLE) {
u32FinalCrcValue = ~u32FinalCrcValue; /* Bits NOT. */
}
if ((u32Config & CRC_CR_REFIN) == CRC_REFIN_DISABLE) {
u8Size /= 8U;
/* Bits reversing in bytes. */
for (i = 0U; i < u8Size; i++) {
u8Offset = i * 8U;
u32Temp = (u32FinalCrcValue >> u8Offset) & 0xFFUL;
u32Temp = __RBIT(u32Temp); /* Bits reversing. */
u32Temp = u32Temp >> (24U - u8Offset);
u32FinalCrcValue &= ~((uint32_t)0xFFUL << u8Offset);
u32FinalCrcValue |= u32Temp;
}
}
}
return u32FinalCrcValue;
}
/**
* @brief Calculate the CRC value of a 8-bit data buffer.
* @param [in] au8Data Pointer to the input data buffer.
* @param [in] u32Len The length(counted in byte) of the data to be calculated.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_INVD_PARAM: The au8Data value is NULL or u32Len value is 0.
*/
static int32_t CRC_WriteData8(const uint8_t au8Data[], uint32_t u32Len)
{
uint32_t i;
int32_t i32Ret = LL_ERR_INVD_PARAM;
const uint32_t u32DataAddr = CRC_DATA_ADDR;
if ((au8Data != NULL) && (u32Len != 0UL)) {
for (i = 0UL; i < u32Len; i++) {
RW_MEM8(u32DataAddr) = au8Data[i];
}
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief Calculate the CRC value of a 16-bit data buffer.
* @param [in] au16Data Pointer to the input data buffer.
* @param [in] u32Len The length(counted in half-word) of the data to be calculated.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_INVD_PARAM: The au16Data value is NULL or u32Len value is 0.
*/
static int32_t CRC_WriteData16(const uint16_t au16Data[], uint32_t u32Len)
{
uint32_t i;
int32_t i32Ret = LL_ERR_INVD_PARAM;
const uint32_t u32DataAddr = CRC_DATA_ADDR;
if ((au16Data != NULL) && (u32Len != 0UL)) {
for (i = 0UL; i < u32Len; i++) {
RW_MEM16(u32DataAddr) = au16Data[i];
}
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief Calculate the CRC value of a 32-bit data buffer.
* @param [in] au32Data Pointer to the input data buffer.
* @param [in] u32Len The length(counted in word) of the data to be calculated.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_INVD_PARAM: The au32Data value is NULL or u32Len value is 0.
*/
static int32_t CRC_WriteData32(const uint32_t au32Data[], uint32_t u32Len)
{
uint32_t i;
int32_t i32Ret = LL_ERR_INVD_PARAM;
const uint32_t u32DataAddr = CRC_DATA_ADDR;
if ((au32Data != NULL) && (u32Len != 0UL)) {
for (i = 0UL; i < u32Len; i++) {
RW_MEM32(u32DataAddr) = au32Data[i];
}
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @}
*/
/**
* @defgroup CRC_Global_Functions CRC Global Functions
* @{
*/
/**
* @brief Set the fields of structure stc_crc_init_t to default values.
* @param [out] pstcCrcInit Pointer to a @ref stc_crc_init_t structure.
* @retval int32_t:
* - LL_OK: Initialize successfully.
* - LL_ERR_INVD_PARAM: The pointer pstcCrcInit value is NULL.
*/
int32_t CRC_StructInit(stc_crc_init_t *pstcCrcInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (NULL != pstcCrcInit) {
pstcCrcInit->u32Protocol = CRC_CRC16;
pstcCrcInit->u32InitValue = CRC_INIT_VALUE_DEFAULT;
pstcCrcInit->u32RefIn = CRC_REFIN_ENABLE;
pstcCrcInit->u32RefOut = CRC_REFOUT_ENABLE;
pstcCrcInit->u32XorOut = CRC_XOROUT_ENABLE;
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief Initialize the CRC.
* @param [in] pstcCrcInit Pointer to a @ref stc_crc_init_t structure.
* @retval int32_t:
* - LL_OK: Initialize successfully.
* - LL_ERR_INVD_PARAM: The pointer pstcCrcInit value is NULL.
*/
int32_t CRC_Init(const stc_crc_init_t *pstcCrcInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (NULL != pstcCrcInit) {
DDL_ASSERT(IS_CRC_PROTOCOL(pstcCrcInit->u32Protocol));
DDL_ASSERT(IS_CRC_REFIN(pstcCrcInit->u32RefIn));
DDL_ASSERT(IS_CRC_REFOUT(pstcCrcInit->u32RefOut));
DDL_ASSERT(IS_CRC_XOROUT(pstcCrcInit->u32XorOut));
WRITE_REG32(CM_CRC->CR, (pstcCrcInit->u32RefIn | pstcCrcInit->u32RefOut | pstcCrcInit->u32XorOut));
MODIFY_REG32(CM_CRC->CR, CRC_CRC32, pstcCrcInit->u32Protocol);
/* Set initial value */
if (CRC_CRC16 == (pstcCrcInit->u32Protocol & CRC_CRC32)) {
WRITE_REG16(CM_CRC->RESLT, (uint16_t)pstcCrcInit->u32InitValue);
} else {
WRITE_REG32(CM_CRC->RESLT, pstcCrcInit->u32InitValue);
}
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief De-initialize the CRC.
* @param None
* @retval int32_t:
* - LL_OK: Reset success.
*/
int32_t CRC_DeInit(void)
{
int32_t i32Ret = LL_OK;
WRITE_REG32(CM_CRC->CR, CRC_CR_RST_VALUE);
return i32Ret;
}
/**
* @brief Get status of the CRC operation result.
* @param None
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t CRC_GetResultStatus(void)
{
uint32_t u32Status;
if (READ_REG32_BIT(CM_CRC->CR, CRC_CR_CR) == CRC_CRC32) {
u32Status = READ_REG32_BIT(CM_CRC->FLG, CRC_FLG_CRCFLAG_32);
} else {
u32Status = READ_REG32_BIT(CM_CRC->RESLT, CRC_RESLT_CRCFLAG_16);
}
return (u32Status > 0UL) ? SET : RESET;
}
/**
* @brief Calculate the CRC16 value and start with the previously calculated CRC as initial value.
* @param [in] u8DataWidth Bit width of the data.
* This parameter can be one of the macros group @ref CRC_DATA_Bit_Width
* @arg CRC_DATA_WIDTH_8BIT: 8 Bit
* @arg CRC_DATA_WIDTH_16BIT: 16 Bit
* @arg CRC_DATA_WIDTH_32BIT: 32 Bit
* @param [in] pvData Pointer to the buffer containing the data to be calculated.
* @param [in] u32Len The length(counted in bytes or half word or word, depending on
* the bit width) of the data to be calculated.
* @retval The CRC16 value.
* @note The function fetch data in byte or half word or word depending on the data bit width(the parameter u8DataWidth).
*/
uint16_t CRC_CRC16_AccumulateData(uint8_t u8DataWidth, const void *pvData, uint32_t u32Len)
{
uint16_t u16CrcValue = 0U;
if ((pvData != NULL) && (u32Len != 0UL)) {
DDL_ASSERT(IS_CRC_DATA_WIDTH(u8DataWidth));
/* Write data */
if (CRC_DATA_WIDTH_32BIT == u8DataWidth) {
(void)CRC_WriteData32((const uint32_t *)pvData, u32Len);
} else if (CRC_DATA_WIDTH_16BIT == u8DataWidth) {
(void)CRC_WriteData16((const uint16_t *)pvData, u32Len);
} else {
(void)CRC_WriteData8((const uint8_t *)pvData, u32Len);
}
/* Get checksum */
u16CrcValue = (uint16_t)READ_REG16(CM_CRC->RESLT);
}
return u16CrcValue;
}
/**
* @brief Calculate the CRC32 value and start with the previously calculated CRC as initial value.
* @param [in] u8DataWidth Bit width of the data.
* This parameter can be one of the macros group @ref CRC_DATA_Bit_Width
* @arg CRC_DATA_WIDTH_8BIT: 8 Bit
* @arg CRC_DATA_WIDTH_16BIT: 16 Bit
* @arg CRC_DATA_WIDTH_32BIT: 32 Bit
* @param [in] pvData Pointer to the buffer containing the data to be calculated.
* @param [in] u32Len The length(counted in bytes or half word or word, depending on
* the bit width) of the data to be calculated.
* @retval The CRC32 value.
* @note The function fetch data in byte or half word or word depending on the data bit width(the parameter u8DataWidth).
*/
uint32_t CRC_CRC32_AccumulateData(uint8_t u8DataWidth, const void *pvData, uint32_t u32Len)
{
uint32_t u32CrcValue = 0UL;
if ((pvData != NULL) && (u32Len != 0UL)) {
DDL_ASSERT(IS_CRC_DATA_WIDTH(u8DataWidth));
/* Write data */
if (CRC_DATA_WIDTH_32BIT == u8DataWidth) {
(void)CRC_WriteData32((const uint32_t *)pvData, u32Len);
} else if (CRC_DATA_WIDTH_16BIT == u8DataWidth) {
(void)CRC_WriteData16((const uint16_t *)pvData, u32Len);
} else {
(void)CRC_WriteData8((const uint8_t *)pvData, u32Len);
}
/* Get checksum */
u32CrcValue = READ_REG32(CM_CRC->RESLT);
}
return u32CrcValue;
}
/**
* @brief Calculate the CRC16 value and start with the specified initial value.
* @param [in] u16InitValue The CRC initialization value which is the valid bits same as
* the bits of CRC Protocol.
* @param [in] u8DataWidth Bit width of the data.
* This parameter can be one of the macros group @ref CRC_DATA_Bit_Width
* @arg CRC_DATA_WIDTH_8BIT: 8 Bit
* @arg CRC_DATA_WIDTH_16BIT: 16 Bit
* @arg CRC_DATA_WIDTH_32BIT: 32 Bit
* @param [in] pvData Pointer to the buffer containing the data to be computed.
* @param [in] u32Len The length(counted in bytes or half word or word, depending on
* the bit width) of the data to be computed.
* @retval The CRC16 value.
* @note The function fetch data in byte or half word or word depending on the data bit width(the parameter u8DataWidth).
*/
uint16_t CRC_CRC16_Calculate(uint16_t u16InitValue, uint8_t u8DataWidth, const void *pvData, uint32_t u32Len)
{
uint16_t u16CrcValue = 0U;
if ((pvData != NULL) && (u32Len != 0UL)) {
/* Set initial value */
WRITE_REG16(CM_CRC->RESLT, u16InitValue);
u16CrcValue = CRC_CRC16_AccumulateData(u8DataWidth, pvData, u32Len);
}
return u16CrcValue;
}
/**
* @brief Calculate the CRC32 value and start with the specified initial value.
* @param [in] u32InitValue The CRC initialization value which is the valid bits same as
* the bits of CRC Protocol.
* @param [in] u8DataWidth Bit width of the data.
* This parameter can be one of the macros group @ref CRC_DATA_Bit_Width
* @arg CRC_DATA_WIDTH_8BIT: 8 Bit
* @arg CRC_DATA_WIDTH_16BIT: 16 Bit
* @arg CRC_DATA_WIDTH_32BIT: 32 Bit
* @param [in] pvData Pointer to the buffer containing the data to be computed.
* @param [in] u32Len The length(counted in bytes or half word or word, depending on
* the bit width) of the data to be computed.
* @retval The CRC32 value.
* @note The function fetch data in byte or half word or word depending on the data bit width(the parameter u8DataWidth).
*/
uint32_t CRC_CRC32_Calculate(uint32_t u32InitValue, uint8_t u8DataWidth, const void *pvData, uint32_t u32Len)
{
uint32_t u32CrcValue = 0UL;
if ((pvData != NULL) && (u32Len != 0UL)) {
/* Set initial value */
WRITE_REG32(CM_CRC->RESLT, u32InitValue);
u32CrcValue = CRC_CRC32_AccumulateData(u8DataWidth, pvData, u32Len);
}
return u32CrcValue;
}
/**
* @brief Check the CRC16 calculating result with the expected value.
* @param [in] u16InitValue The CRC initialization value which is the valid bits same as
* the bits of CRC Protocol.
* @param [in] u8DataWidth Bit width of the data.
* This parameter can be one of the following values:
* @arg CRC_DATA_WIDTH_8BIT: 8 Bit
* @arg CRC_DATA_WIDTH_16BIT: 16 Bit
* @arg CRC_DATA_WIDTH_32BIT: 32 Bit
* @param [in] pvData Pointer to the buffer containing the data to be computed.
* @param [in] u32Len The length(counted in byte) of the data to be calculated.
* @param [in] u16ExpectValue The expected CRC value to be checked.
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t CRC_CRC16_CheckData(uint16_t u16InitValue, uint8_t u8DataWidth, const void *pvData, uint32_t u32Len, uint16_t u16ExpectValue)
{
__IO uint32_t u32Count = CRC_CALC_CLK_COUNT;
en_flag_status_t enStatus = RESET;
uint32_t u32Expect_Value = u16ExpectValue;
if ((pvData != NULL) && (u32Len != 0UL)) {
(void)CRC_CRC16_Calculate(u16InitValue, u8DataWidth, pvData, u32Len);
u32Expect_Value = CRC_ConvertCrcValue(u32Expect_Value);
/* Writes the expected CRC value to be checked */
(void)CRC_WriteData16((uint16_t *)((void *)&u32Expect_Value), 1UL);
/* Delay for waiting CRC result flag */
while (u32Count-- != 0UL) {
__NOP();
}
enStatus = CRC_GetResultStatus();
}
return enStatus;
}
/**
* @brief Check the CRC32 calculating result with the expected value.
* @param [in] u32InitValue The CRC initialization value which is the valid bits same as
* the bits of CRC Protocol.
* @param [in] u8DataWidth Bit width of the data.
* This parameter can be one of the following values:
* @arg CRC_DATA_WIDTH_8BIT: 8 Bit
* @arg CRC_DATA_WIDTH_16BIT: 16 Bit
* @arg CRC_DATA_WIDTH_32BIT: 32 Bit
* @param [in] pvData Pointer to the buffer containing the data to be computed.
* @param [in] u32Len The length(counted in byte) of the data to be calculated.
* @param [in] u32ExpectValue The expected CRC value to be checked.
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t CRC_CRC32_CheckData(uint32_t u32InitValue, uint8_t u8DataWidth, const void *pvData, uint32_t u32Len, uint32_t u32ExpectValue)
{
__IO uint32_t u32Count = CRC_CALC_CLK_COUNT;
en_flag_status_t enStatus = RESET;
uint32_t u32Expect_Value = u32ExpectValue;
if ((pvData != NULL) && (u32Len != 0UL)) {
(void)CRC_CRC32_Calculate(u32InitValue, u8DataWidth, pvData, u32Len);
u32Expect_Value = CRC_ConvertCrcValue(u32Expect_Value);
/* Writes the expected CRC value to be checked */
(void)CRC_WriteData32(&u32Expect_Value, 1UL);
/* Delay for waiting CRC result flag */
while (u32Count-- != 0UL) {
__NOP();
}
enStatus = CRC_GetResultStatus();
}
return enStatus;
}
/**
* @brief Get the CRC16 check result with the expected value.
* @param [in] u16ExpectValue The expected CRC value to be checked.
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t CRC_CRC16_GetCheckResult(uint16_t u16ExpectValue)
{
__IO uint32_t u32Count = CRC_CALC_CLK_COUNT;
en_flag_status_t enStatus;
uint32_t u32Expect_Value = u16ExpectValue;
u32Expect_Value = CRC_ConvertCrcValue(u32Expect_Value);
/* Writes the expected CRC value to be checked */
(void)CRC_WriteData16((uint16_t *)((void *)&u32Expect_Value), 1UL);
/* Delay for waiting CRC result flag */
while (u32Count-- != 0UL) {
__NOP();
}
enStatus = CRC_GetResultStatus();
return enStatus;
}
/**
* @brief Get the CRC32 check result with the expected value.
* @param [in] u32ExpectValue The expected CRC value to be checked.
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t CRC_CRC32_GetCheckResult(uint32_t u32ExpectValue)
{
__IO uint32_t u32Count = CRC_CALC_CLK_COUNT;
en_flag_status_t enStatus;
uint32_t u32Expect_Value = u32ExpectValue;
u32Expect_Value = CRC_ConvertCrcValue(u32Expect_Value);
/* Writes the expected CRC value to be checked */
(void)CRC_WriteData32(&u32Expect_Value, 1UL);
/* Delay for waiting CRC result flag */
while (u32Count-- != 0UL) {
__NOP();
}
enStatus = CRC_GetResultStatus();
return enStatus;
}
/**
* @}
*/
#endif /* LL_CRC_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+209
View File
@@ -0,0 +1,209 @@
/**
*******************************************************************************
* @file hc32_ll_dbgc.c
* @brief This file provides firmware functions to manage the DBGC.
@verbatim
Change Logs:
Date Author Notes
2023-09-30 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_dbgc.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_DBGC DBGC
* @brief DBGC Driver Library
* @{
*/
#if (LL_DBGC_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup DBGC_Local_Macros DBGC Local Macros
* @{
*/
/**
* @defgroup DBGC_Check_Parameters_Validity DBGC Check Parameters Validity
* @{
*/
#define IS_SECURITY_FLAG(x) \
( ((x) != 0U) && \
(((x) | DBGC_SECURITY_ALL) == DBGC_SECURITY_ALL))
/* Parameter valid check for debug trace mode */
#define IS_DGBC_TRACE_MD(x) \
( ((x) == DBGC_TRACE_ASYNC) || \
((x) == DBGC_TRACE_SYNC_1BIT) || \
((x) == DBGC_TRACE_SYNC_2BIT) || \
((x) == DBGC_TRACE_SYNC_4BIT))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup DBGC_Global_Functions DBGC Global Functions
* @{
*/
/**
* @brief Get MCU security status.
* @param [in] u32Flag Specify the flags to get, This parameter can be any combination of the member from
* @ref DBGC_MCU_Security_Flag
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t DBGC_GetSecurityStatus(uint32_t u32Flag)
{
DDL_ASSERT(IS_SECURITY_FLAG(u32Flag));
return ((0UL != READ_REG32_BIT(CM_DBGC->MCUSTAT, u32Flag)) ? SET : RESET);
}
/**
* @brief erase the chip.
* @param [in] u32Timeout Maximum count of trying to wait flash erase
* @retval int32_t:
* - LL_OK: erase successfully
* - LL_ERR: erase error
* - LL_ERR_TIMEOUT: erase timeout
*/
int32_t DBGC_FlashErase(uint32_t u32Timeout)
{
__IO uint32_t u32TimeCnt = 0UL;
int32_t i32Ret = LL_ERR_TIMEOUT;
SET_REG32_BIT(CM_DBGC->FERSCTL, DBGC_FERSCTL_ERASEREQ);
/* Wait erase finish */
while (u32TimeCnt <= u32Timeout) {
if (DBGC_FERSCTL_ERASEACK == READ_REG32_BIT(CM_DBGC->FERSCTL, DBGC_FERSCTL_ERASEACK)) {
i32Ret = LL_OK;
break;
}
u32TimeCnt++;
}
if (DBGC_FERSCTL_ERASEERR == READ_REG32_BIT(CM_DBGC->FERSCTL, DBGC_FERSCTL_ERASEERR)) {
i32Ret = LL_ERR;
}
return i32Ret;
}
/**
* @brief Get authenticate ID.
* @param [out] pstcAuthID Authenticate ID struct
* @retval the value of the authenticate ID
*/
void DBGC_GetAuthID(stc_dbgc_auth_id_t *pstcAuthID)
{
if (NULL != pstcAuthID) {
pstcAuthID->u32AuthID0 = READ_REG32(CM_DBGC->AUTHID0);
pstcAuthID->u32AuthID1 = READ_REG32(CM_DBGC->AUTHID1);
pstcAuthID->u32AuthID2 = READ_REG32(CM_DBGC->AUTHID2);
}
}
/**
* @brief Whether to stop the peripheral while mcu core stop.
* @param [in] u32Periph Specifies the peripheral. @ref DBGC_Periph_Sel
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void DBGC_PeriphCmd(uint32_t u32Periph, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
CLR_REG32_BIT(CM_DBGC->MCUSTPCTL, u32Periph);
} else {
SET_REG32_BIT(CM_DBGC->MCUSTPCTL, u32Periph);
}
}
/**
* @brief Enable or disable the trace pin output.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void DBGC_TraceIoCmd(en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(CM_DBGC->MCUTRACECTL, DBGC_MCUTRACECTL_TRACEIOEN);
} else {
CLR_REG32_BIT(CM_DBGC->MCUTRACECTL, DBGC_MCUTRACECTL_TRACEIOEN);
}
}
/**
* @brief Config trace mode.
* @param [in] u32TraceMode An @ref en_functional_state_t enumeration value.
* @retval None
*/
void DBGC_TraceModeConfig(uint32_t u32TraceMode)
{
DDL_ASSERT(IS_DGBC_TRACE_MD(u32TraceMode));
MODIFY_REG32(CM_DBGC->MCUTRACECTL, DBGC_MCUTRACECTL_TRACEMODE, u32TraceMode);
}
/**
* @}
*/
#endif /* LL_DBGC_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+539
View File
@@ -0,0 +1,539 @@
/**
*******************************************************************************
* @file hc32_ll_dcu.c
* @brief This file provides firmware functions to manage the DCU(Data Computing
* Unit).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2022-06-30 CDT Synchronize register: DCU_INTSEL -> DCU_INTEVTSEL
Modify function comments: DCU_IntCmd
2023-06-30 CDT Modify typo
Modify API DCU_DeInit()
Add CM_DCU4
Modify function DCU_IntCmd() for misra
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_dcu.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_DCU DCU
* @brief DCU Driver Library
* @{
*/
#if (LL_DCU_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup DCU_Local_Macros DCU Local Macros
* @{
*/
/**
* @defgroup DCU_Check_Parameters_Validity DCU Check Parameters Validity
* @{
*/
#define IS_DCU_BASE_FUNC_UNIT(x) \
( ((x) == CM_DCU1) || \
((x) == CM_DCU2) || \
((x) == CM_DCU3) || \
((x) == CM_DCU4))
#define IS_DCU_UNIT(x) (IS_DCU_BASE_FUNC_UNIT(x))
#define IS_DCU_BASE_FUNC_UNIT_MD(x) \
( ((x) == DCU_MD_CMP) || \
((x) == DCU_MD_ADD) || \
((x) == DCU_MD_SUB) || \
((x) == DCU_MD_HW_ADD) || \
((x) == DCU_MD_HW_SUB) || \
((x) == DCU_MD_INVD))
#define IS_DCU_BASE_FUNC_UNIT_FLAG(x) \
( (0UL != (x)) && \
(0UL == ((x) & (~DCU_BASE_FUNC_UNIT_FLAG_MASK))))
#define IS_DCU_CMP_COND(x) \
( ((x) == DCU_CMP_TRIG_DATA0) || \
((x) == DCU_CMP_TRIG_DATA0_DATA1_DATA2))
#define IS_DCU_DATA_WIDTH(x) \
( ((x) == DCU_DATA_WIDTH_8BIT) || \
((x) == DCU_DATA_WIDTH_16BIT) || \
((x) == DCU_DATA_WIDTH_32BIT))
#define IS_DCU_INT_CATEGORY(x) \
( ((x) == DCU_CATEGORY_OP) || \
((x) == DCU_CATEGORY_CMP_WIN) || \
((x) == DCU_CATEGORY_CMP_NON_WIN))
#define IS_DCU_INT_OP(x) ((x) == DCU_INT_OP_CARRY)
#define IS_DCU_INT_CMP_WIN(x) \
( ((x) == DCU_INT_CMP_WIN_INSIDE) || \
((x) == DCU_INT_CMP_WIN_OUTSIDE))
#define IS_DCU_INT_CMP_NON_WIN(x) \
( ((x) != 0UL) || \
(((x) | DCU_INT_CMP_NON_WIN_ALL) == DCU_INT_CMP_NON_WIN_ALL))
#define IS_DCU_INT_WAVE_MD(x) \
( ((x) != 0UL) && \
(((x) | DCU_INT_WAVE_MD_ALL) == DCU_INT_WAVE_MD_ALL))
#define IS_DCU_DATA_REG(x) \
( ((x) == DCU_DATA0_IDX) || \
((x) == DCU_DATA1_IDX) || \
((x) == DCU_DATA2_IDX))
#define IS_DCU_WAVE_UPPER_LIMIT(x) ((x) <= 0xFFFUL)
#define IS_DCU_WAVE_LOWER_LIMIT(x) ((x) <= 0xFFFUL)
#define IS_DCU_WAVE_STEP(x) ((x) <= 0xFFFUL)
/**
* @}
*/
/**
* @defgroup DCU_Flag_Mask DCU Flag Mask
* @{
*/
#define DCU_BASE_FUNC_UNIT_FLAG_MASK (0x0E7FUL)
/**
* @}
*/
/**
* @defgroup DCU_Register_Address DCU Register Address
* @{
*/
#define DCU_REG_ADDR(_REG_) ((uint32_t)(&(_REG_)))
#define DCU_DATA_REG_ADDR(_UNITx_, _IDX_) (DCU_REG_ADDR((_UNITx_)->DATA0) + ((_IDX_) << 2UL))
#define DCU_DATA_REG8(_UNITx_, _IDX_) (*(__IO uint8_t *)DCU_DATA_REG_ADDR(_UNITx_, _IDX_))
#define DCU_DATA_REG16(_UNITx_, _IDX_) (*(__IO uint16_t *)DCU_DATA_REG_ADDR(_UNITx_, _IDX_))
#define DCU_DATA_REG32(_UNITx_, _IDX_) (*(__IO uint32_t *)DCU_DATA_REG_ADDR(_UNITx_, _IDX_))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup DCU_Global_Functions DCU Global Functions
* @{
*/
/**
* @brief Set the fields of structure stc_dcu_init_t to default values.
* @param [out] pstcDcuInit Pointer to a @ref stc_dcu_init_t structure.
* @retval int32_t:
* - LL_OK: Initialize successfully.
* - LL_ERR_INVD_PARAM: The pointer pstcDcuInit value is NULL.
*/
int32_t DCU_StructInit(stc_dcu_init_t *pstcDcuInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (NULL != pstcDcuInit) {
pstcDcuInit->u32Mode = DCU_MD_INVD;
pstcDcuInit->u32DataWidth = DCU_DATA_WIDTH_8BIT;
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief Initialize DCU function.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] pstcDcuInit Pointer to a @ref stc_dcu_init_t structure.
* @retval int32_t:
* - LL_OK: Initialize successfully.
* - LL_ERR_INVD_PARAM: The pointer pstcDcuInit value is NULL.
*/
int32_t DCU_Init(CM_DCU_TypeDef *DCUx, const stc_dcu_init_t *pstcDcuInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (NULL != pstcDcuInit) {
DDL_ASSERT(IS_DCU_UNIT(DCUx) && IS_DCU_BASE_FUNC_UNIT_MD(pstcDcuInit->u32Mode));
DDL_ASSERT(IS_DCU_DATA_WIDTH(pstcDcuInit->u32DataWidth));
/* Set register: CTL */
WRITE_REG32(DCUx->CTL, (pstcDcuInit->u32Mode | pstcDcuInit->u32DataWidth));
/* Disable interrupt */
WRITE_REG32(DCUx->INTEVTSEL, 0x00000000UL);
/* Clear Flag */
WRITE_REG32(DCUx->FLAGCLR, 0x0000007FUL);
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief De-Initialize DCU function.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @retval int32_t:
* - LL_OK: De-Initialize success.
*/
int32_t DCU_DeInit(CM_DCU_TypeDef *DCUx)
{
DDL_ASSERT(IS_DCU_UNIT(DCUx));
/* Configures the registers to reset value. */
WRITE_REG32(DCUx->CTL, 0x00000000UL);
WRITE_REG32(DCUx->INTEVTSEL, 0x00000000UL);
/* Clear Flag */
WRITE_REG32(DCUx->FLAGCLR, 0x0000007FUL);
return LL_OK;
}
/**
* @brief Set DCU operation mode.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32Mode DCU mode
* This parameter can be one of the macros group @ref DCU_Mode.
* @retval None
*/
void DCU_SetMode(CM_DCU_TypeDef *DCUx, uint32_t u32Mode)
{
DDL_ASSERT(IS_DCU_UNIT(DCUx) && IS_DCU_BASE_FUNC_UNIT_MD(u32Mode));
MODIFY_REG32(DCUx->CTL, DCU_CTL_MODE, u32Mode);
}
/**
* @brief Set DCU data size.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32DataWidth DCU data width
* This parameter can be one of the macros group @ref DCU_Data_Width
* @arg DCU_DATA_WIDTH_8BIT: DCU data size 8 bit
* @arg DCU_DATA_WIDTH_16BIT: DCU data size 16 bit
* @arg DCU_DATA_WIDTH_32BIT: DCU data size 32 bit
* @retval None
*/
void DCU_SetDataWidth(CM_DCU_TypeDef *DCUx, uint32_t u32DataWidth)
{
DDL_ASSERT(IS_DCU_UNIT(DCUx));
DDL_ASSERT(IS_DCU_DATA_WIDTH(u32DataWidth));
MODIFY_REG32(DCUx->CTL, DCU_CTL_DATASIZE, u32DataWidth);
}
/**
* @brief Set DCU compare trigger condition.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32Cond DCU compare trigger condition
* This parameter can be one of the macros group @ref DCU_Compare_Trigger_Condition
* @arg DCU_CMP_TRIG_DATA0: DCU compare triggered by DATA0.
* @arg DCU_CMP_TRIG_DATA0_DATA1_DATA2: DCU compare triggered by DATA0 or DATA1 or DATA2.
* @retval None
*/
void DCU_SetCompareCond(CM_DCU_TypeDef *DCUx, uint32_t u32Cond)
{
DDL_ASSERT(IS_DCU_UNIT(DCUx));
DDL_ASSERT(IS_DCU_CMP_COND(u32Cond));
MODIFY_REG32(DCUx->CTL, DCU_CTL_COMPTRG, u32Cond);
}
/**
* @brief Get DCU flag.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32Flag The specified DCU flag
* This parameter can be any composed value of the macros group @ref DCU_Flag.
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t DCU_GetStatus(const CM_DCU_TypeDef *DCUx, uint32_t u32Flag)
{
DDL_ASSERT(IS_DCU_UNIT(DCUx) && IS_DCU_BASE_FUNC_UNIT_FLAG(u32Flag));
return (0UL == READ_REG32_BIT(DCUx->FLAG, u32Flag)) ? RESET : SET;
}
/**
* @brief Clear DCU flag.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32Flag The specified DCU flag
* This parameter can be any composed value of the macros group @ref DCU_Mode.
* @retval None
*/
void DCU_ClearStatus(CM_DCU_TypeDef *DCUx, uint32_t u32Flag)
{
DDL_ASSERT(IS_DCU_UNIT(DCUx) && IS_DCU_BASE_FUNC_UNIT_FLAG(u32Flag));
WRITE_REG32(DCUx->FLAGCLR, u32Flag);
}
/**
* @brief Enable or disable DCU interrupt function.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void DCU_GlobalIntCmd(CM_DCU_TypeDef *DCUx, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_DCU_UNIT(DCUx));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(DCUx->CTL, DCU_CTL_INTEN);
} else {
CLR_REG32_BIT(DCUx->CTL, DCU_CTL_INTEN);
}
}
/**
* @brief Enable/disable DCU the specified interrupt source.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32IntCategory DCU interrupt category
* This parameter can be one of the macros group @ref DCU_Category.
* @param [in] u32IntType DCU interrupt type
* This parameter can be one of the macros group @ref DCU_Interrupt_Type.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void DCU_IntCmd(CM_DCU_TypeDef *DCUx, uint32_t u32IntCategory, uint32_t u32IntType, en_functional_state_t enNewState)
{
uint32_t u32Type;
DDL_ASSERT(IS_DCU_UNIT(DCUx));
DDL_ASSERT(IS_DCU_INT_CATEGORY(u32IntCategory));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (DCU_CATEGORY_OP == u32IntCategory) {
DDL_ASSERT(IS_DCU_INT_OP(u32IntType));
u32Type = (u32IntType & DCU_INT_OP_CARRY);
} else if (DCU_CATEGORY_CMP_WIN == u32IntCategory) {
DDL_ASSERT(IS_DCU_INT_CMP_WIN(u32IntType));
u32Type = (u32IntType & DCU_INT_CMP_WIN_ALL);
} else {
DDL_ASSERT(IS_DCU_INT_CMP_NON_WIN(u32IntType));
u32Type = (u32IntType & DCU_INT_CMP_NON_WIN_ALL);
}
if (ENABLE == enNewState) {
SET_REG32_BIT(DCUx->INTEVTSEL, u32Type);
} else {
CLR_REG32_BIT(DCUx->INTEVTSEL, u32Type);
}
}
/**
* @brief Read DCU register DATA for byte.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32DataIndex DCU data register index
* This parameter can be one of the macros group @ref DCU_Data_Register_Index
* @arg DCU_DATA0_IDX: DCU DATA0
* @arg DCU_DATA1_IDX: DCU DATA1
* @arg DCU_DATA2_IDX: DCU DATA2
* @retval DCU register DATA value for byte
*/
uint8_t DCU_ReadData8(const CM_DCU_TypeDef *DCUx, uint32_t u32DataIndex)
{
DDL_ASSERT(IS_DCU_UNIT(DCUx));
DDL_ASSERT(IS_DCU_DATA_REG(u32DataIndex));
return READ_REG8(DCU_DATA_REG8(DCUx, u32DataIndex));
}
/**
* @brief Write DCU register DATA for byte.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32DataIndex DCU data register index
* This parameter can be one of the macros group @ref DCU_Data_Register_Index
* @arg DCU_DATA0_IDX: DCU DATA0
* @arg DCU_DATA1_IDX: DCU DATA1
* @arg DCU_DATA2_IDX: DCU DATA2
* @param [in] u8Data The data to write.
* @retval None
*/
void DCU_WriteData8(CM_DCU_TypeDef *DCUx, uint32_t u32DataIndex, uint8_t u8Data)
{
__IO uint8_t *DATA;
DDL_ASSERT(IS_DCU_UNIT(DCUx));
DDL_ASSERT(IS_DCU_DATA_REG(u32DataIndex));
DATA = &DCU_DATA_REG8(DCUx, u32DataIndex);
WRITE_REG8(*DATA, u8Data);
}
/**
* @brief Read DCU register DATA for half-word.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32DataIndex DCU data register index
* This parameter can be one of the macros group @ref DCU_Data_Register_Index
* @arg DCU_DATA0_IDX: DCU DATA0
* @arg DCU_DATA1_IDX: DCU DATA1
* @arg DCU_DATA2_IDX: DCU DATA2
* @retval DCU register DATA value for half-word
*/
uint16_t DCU_ReadData16(const CM_DCU_TypeDef *DCUx, uint32_t u32DataIndex)
{
DDL_ASSERT(IS_DCU_UNIT(DCUx));
DDL_ASSERT(IS_DCU_DATA_REG(u32DataIndex));
return READ_REG16(DCU_DATA_REG16(DCUx, u32DataIndex));
}
/**
* @brief Write DCU register DATA for half-word.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32DataIndex DCU data register index
* This parameter can be one of the macros group @ref DCU_Data_Register_Index
* @arg DCU_DATA0_IDX: DCU DATA0
* @arg DCU_DATA1_IDX: DCU DATA1
* @arg DCU_DATA2_IDX: DCU DATA2
* @param [in] u16Data The data to write.
* @retval None
*/
void DCU_WriteData16(CM_DCU_TypeDef *DCUx, uint32_t u32DataIndex, uint16_t u16Data)
{
__IO uint16_t *DATA;
DDL_ASSERT(IS_DCU_UNIT(DCUx));
DDL_ASSERT(IS_DCU_DATA_REG(u32DataIndex));
DATA = &DCU_DATA_REG16(DCUx, u32DataIndex);
WRITE_REG16(*DATA, u16Data);
}
/**
* @brief Read DCU register DATA for word.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32DataIndex DCU data register index
* This parameter can be one of the macros group @ref DCU_Data_Register_Index
* @arg DCU_DATA0_IDX: DCU DATA0
* @arg DCU_DATA1_IDX: DCU DATA1
* @arg DCU_DATA2_IDX: DCU DATA2
* @retval DCU register DATA value for word
*/
uint32_t DCU_ReadData32(const CM_DCU_TypeDef *DCUx, uint32_t u32DataIndex)
{
DDL_ASSERT(IS_DCU_UNIT(DCUx));
DDL_ASSERT(IS_DCU_DATA_REG(u32DataIndex));
return READ_REG32(DCU_DATA_REG32(DCUx, u32DataIndex));
}
/**
* @brief Write DCU register DATA0 for word.
* @param [in] DCUx Pointer to DCU instance register base
* This parameter can be one of the following values:
* @arg CM_DCU or CM_DCUx: DCU instance register base
* @param [in] u32DataIndex DCU data register index
* This parameter can be one of the macros group @ref DCU_Data_Register_Index
* @arg DCU_DATA0_IDX: DCU DATA0
* @arg DCU_DATA1_IDX: DCU DATA1
* @arg DCU_DATA2_IDX: DCU DATA2
* @param [in] u32Data The data to write.
* @retval None
*/
void DCU_WriteData32(CM_DCU_TypeDef *DCUx, uint32_t u32DataIndex, uint32_t u32Data)
{
__IO uint32_t *DATA;
DDL_ASSERT(IS_DCU_UNIT(DCUx));
DDL_ASSERT(IS_DCU_DATA_REG(u32DataIndex));
DATA = &DCU_DATA_REG32(DCUx, u32DataIndex);
WRITE_REG32(*DATA, u32Data);
}
/**
* @}
*/
#endif /* LL_DCU_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+493
View File
@@ -0,0 +1,493 @@
/**
*******************************************************************************
* @file hc32_ll_emb.c
* @brief This file provides firmware functions to manage the EMB
* (Emergency Brake).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2022-06-30 CDT Optimize function: EMB_TMR4_Init
Optimize function: EMB_TMR6_Init
2023-06-30 CDT Function EMB_TMR4_Init don't call EMB_DeInit
Function EMB_TMR6_Init don't call EMB_DeInit
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_emb.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_EMB EMB
* @brief Emergency Brake Driver Library
* @{
*/
#if (LL_EMB_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup EMB_Local_Macros EMB Local Macros
* @{
*/
/**
* @defgroup EMB_Check_Parameters_Validity EMB Check Parameters Validity
* @{
*/
#define IS_EMB_GROUP(x) \
( ((x) == CM_EMB0) || \
((x) == CM_EMB1) || \
((x) == CM_EMB2) || \
((x) == CM_EMB3))
#define IS_EMB_TMR4_GROUP(x) \
( ((x) == CM_EMB1) || \
((x) == CM_EMB2) || \
((x) == CM_EMB3))
#define IS_EMB_TMR6_GROUP(x) ((x) == CM_EMB0)
#define IS_EMB_OSC_STAT(x) \
( ((x) == EMB_OSC_ENABLE) || \
((x) == EMB_OSC_DISABLE))
#define IS_EMB_TMR4_PWM_W_STAT(x) \
( ((x) == EMB_TMR4_PWM_W_ENABLE) || \
((x) == EMB_TMR4_PWM_W_DISABLE))
#define IS_EMB_DETECT_TMR4_PWM_W_LVL(x) \
( ((x) == EMB_DETECT_TMR4_PWM_W_BOTH_LOW) || \
((x) == EMB_DETECT_TMR4_PWM_W_BOTH_HIGH))
#define IS_EMB_TMR4_PWM_V_STAT(x) \
( ((x) == EMB_TMR4_PWM_V_ENABLE) || \
((x) == EMB_TMR4_PWM_V_DISABLE))
#define IS_EMB_DETECT_TMR4_PWM_V_LVL(x) \
( ((x) == EMB_DETECT_TMR4_PWM_V_BOTH_LOW) || \
((x) == EMB_DETECT_TMR4_PWM_V_BOTH_HIGH))
#define IS_EMB_TMR4_PWM_U_STAT(x) \
( ((x) == EMB_TMR4_PWM_U_ENABLE) || \
((x) == EMB_TMR4_PWM_U_DISABLE))
#define IS_EMB_DETECT_TMR4_PWM_U_LVL(x) \
( ((x) == EMB_DETECT_TMR4_PWM_U_BOTH_LOW) || \
((x) == EMB_DETECT_TMR4_PWM_U_BOTH_HIGH))
#define IS_EMB_CMP1_STAT(x) \
( ((x) == EMB_CMP1_ENABLE) || \
((x) == EMB_CMP1_DISABLE))
#define IS_EMB_CMP2_STAT(x) \
( ((x) == EMB_CMP2_ENABLE) || \
((x) == EMB_CMP2_DISABLE))
#define IS_EMB_CMP3_STAT(x) \
( ((x) == EMB_CMP3_ENABLE) || \
((x) == EMB_CMP3_DISABLE))
#define IS_EMB_PORT1_STAT(x) \
( ((x) == EMB_PORT1_ENABLE) || \
((x) == EMB_PORT1_DISABLE))
#define IS_EMB_PORT1_DETECT_LVL(x) \
( ((x) == EMB_PORT1_DETECT_LVL_LOW) || \
((x) == EMB_PORT1_DETECT_LVL_HIGH))
#define IS_EMB_PORT1_FILTER_STAT(x) \
( ((x) == EMB_PORT1_FILTER_ENABLE) || \
((x) == EMB_PORT1_FILTER_DISABLE))
#define IS_EMB_PORT1_FILTER_DIV(x) (((x) & (~EMB_PORT1_FILTER_CLK_DIV_MASK)) == 0UL)
#define IS_EMB_TMR6_1_PWM_STAT(x) \
( ((x) == EMB_TMR6_1_PWM_ENABLE) || \
((x) == EMB_TMR6_1_PWM_DISABLE))
#define IS_EMB_DETECT_TMR6_1_PWM_LVL(x) \
( ((x) == EMB_DETECT_TMR6_1_PWM_BOTH_LOW) || \
((x) == EMB_DETECT_TMR6_1_PWM_BOTH_HIGH))
#define IS_EMB_TMR6_2_PWM_STAT(x) \
( ((x) == EMB_TMR6_2_PWM_ENABLE) || \
((x) == EMB_TMR6_2_PWM_DISABLE))
#define IS_EMB_DETECT_TMR6_2_PWM_LVL(x) \
( ((x) == EMB_DETECT_TMR6_2_PWM_BOTH_LOW) || \
((x) == EMB_DETECT_TMR6_2_PWM_BOTH_HIGH))
#define IS_EMB_TMR6_3_PWM_STAT(x) \
( ((x) == EMB_TMR6_3_PWM_ENABLE) || \
((x) == EMB_TMR6_3_PWM_DISABLE))
#define IS_EMB_DETECT_TMR6_3_PWM_LVL(x) \
( ((x) == EMB_DETECT_TMR6_3_PWM_BOTH_LOW) || \
((x) == EMB_DETECT_TMR6_3_PWM_BOTH_HIGH))
#define IS_VALID_EMB_INT(x) \
( ((x) != 0UL) && \
(((x) | EMB_INT_ALL) == EMB_INT_ALL))
#define IS_EMB_FLAG(x) \
( ((x) != 0UL) && \
(((x) | EMB_FLAG_ALL) == EMB_FLAG_ALL))
/**
* @}
*/
#define EMB_PORT1_FILTER_CLK_DIV_MASK EMB_PORT1_FILTER_CLK_DIV128
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup EMB_Global_Functions EMB Global Functions
* @{
*/
/**
* @brief Set the fields of structure stc_emb_tmr4_init_t to default values
* @param [out] pstcEmbInit Pointer to a @ref stc_emb_tmr4_init_t structure
* @retval int32_t:
* - LL_OK: Initialize successfully.
* - LL_ERR_INVD_PARAM: The pointer pstcEmbInit value is NULL.
*/
int32_t EMB_TMR4_StructInit(stc_emb_tmr4_init_t *pstcEmbInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (NULL != pstcEmbInit) {
/* OSC */
pstcEmbInit->stcOsc.u32OscState = EMB_OSC_DISABLE;
/* CMP */
pstcEmbInit->stcCmp.u32Cmp1State = EMB_CMP1_DISABLE;
pstcEmbInit->stcCmp.u32Cmp2State = EMB_CMP2_DISABLE;
pstcEmbInit->stcCmp.u32Cmp3State = EMB_CMP3_DISABLE;
/* Port */
pstcEmbInit->stcPort.stcPort1.u32PortState = EMB_PORT1_DISABLE;
pstcEmbInit->stcPort.stcPort1.u32PortLevel = EMB_PORT1_DETECT_LVL_HIGH;
pstcEmbInit->stcPort.stcPort1.u32PortFilterDiv = EMB_PORT1_FILTER_CLK_DIV1;
pstcEmbInit->stcPort.stcPort1.u32PortFilterState = EMB_PORT1_FILTER_DISABLE;
/* PWM */
pstcEmbInit->stcTmr4.stcTmr4PwmU.u32PwmState = EMB_TMR4_PWM_U_DISABLE;
pstcEmbInit->stcTmr4.stcTmr4PwmU.u32PwmLevel = EMB_DETECT_TMR4_PWM_U_BOTH_LOW;
pstcEmbInit->stcTmr4.stcTmr4PwmV.u32PwmState = EMB_TMR4_PWM_V_DISABLE;
pstcEmbInit->stcTmr4.stcTmr4PwmV.u32PwmLevel = EMB_DETECT_TMR4_PWM_V_BOTH_LOW;
pstcEmbInit->stcTmr4.stcTmr4PwmW.u32PwmState = EMB_TMR4_PWM_W_DISABLE;
pstcEmbInit->stcTmr4.stcTmr4PwmW.u32PwmLevel = EMB_DETECT_TMR4_PWM_W_BOTH_LOW;
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief Initialize EMB for TMR4.
* @param [in] EMBx Pointer to EMB instance register base
* This parameter can be one of the following values:
* @arg CM_EMBx: EMB group instance register base
* @param [in] pstcEmbInit Pointer to a @ref stc_emb_tmr4_init_t structure
* @retval int32_t:
* - LL_OK: Initialize successfully.
* - LL_ERR_INVD_PARAM: The pointer pstcEmbInit value is NULL.
*/
int32_t EMB_TMR4_Init(CM_EMB_TypeDef *EMBx, const stc_emb_tmr4_init_t *pstcEmbInit)
{
uint32_t u32Reg1Value;
uint32_t u32Reg2Value;
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (NULL != pstcEmbInit) {
DDL_ASSERT(IS_EMB_TMR4_GROUP(EMBx));
DDL_ASSERT(IS_EMB_OSC_STAT(pstcEmbInit->stcOsc.u32OscState));
DDL_ASSERT(IS_EMB_CMP1_STAT(pstcEmbInit->stcCmp.u32Cmp1State));
DDL_ASSERT(IS_EMB_CMP2_STAT(pstcEmbInit->stcCmp.u32Cmp2State));
DDL_ASSERT(IS_EMB_CMP3_STAT(pstcEmbInit->stcCmp.u32Cmp3State));
DDL_ASSERT(IS_EMB_PORT1_STAT(pstcEmbInit->stcPort.stcPort1.u32PortState));
DDL_ASSERT(IS_EMB_PORT1_DETECT_LVL(pstcEmbInit->stcPort.stcPort1.u32PortLevel));
DDL_ASSERT(IS_EMB_PORT1_FILTER_DIV(pstcEmbInit->stcPort.stcPort1.u32PortFilterDiv));
DDL_ASSERT(IS_EMB_PORT1_FILTER_STAT(pstcEmbInit->stcPort.stcPort1.u32PortFilterState));
DDL_ASSERT(IS_EMB_TMR4_PWM_U_STAT(pstcEmbInit->stcTmr4.stcTmr4PwmU.u32PwmState));
DDL_ASSERT(IS_EMB_DETECT_TMR4_PWM_U_LVL(pstcEmbInit->stcTmr4.stcTmr4PwmU.u32PwmLevel));
DDL_ASSERT(IS_EMB_TMR4_PWM_V_STAT(pstcEmbInit->stcTmr4.stcTmr4PwmV.u32PwmState));
DDL_ASSERT(IS_EMB_DETECT_TMR4_PWM_V_LVL(pstcEmbInit->stcTmr4.stcTmr4PwmV.u32PwmLevel));
DDL_ASSERT(IS_EMB_TMR4_PWM_W_STAT(pstcEmbInit->stcTmr4.stcTmr4PwmW.u32PwmState));
DDL_ASSERT(IS_EMB_DETECT_TMR4_PWM_W_LVL(pstcEmbInit->stcTmr4.stcTmr4PwmW.u32PwmLevel));
/* OSC */
u32Reg1Value = pstcEmbInit->stcOsc.u32OscState;
u32Reg2Value = 0UL;
/* PWM */
u32Reg1Value |= (pstcEmbInit->stcTmr4.stcTmr4PwmU.u32PwmState | pstcEmbInit->stcTmr4.stcTmr4PwmV.u32PwmState | \
pstcEmbInit->stcTmr4.stcTmr4PwmW.u32PwmState);
u32Reg2Value |= (pstcEmbInit->stcTmr4.stcTmr4PwmU.u32PwmLevel | pstcEmbInit->stcTmr4.stcTmr4PwmV.u32PwmLevel | \
pstcEmbInit->stcTmr4.stcTmr4PwmW.u32PwmLevel);
/* CMP */
u32Reg1Value |= (pstcEmbInit->stcCmp.u32Cmp1State | pstcEmbInit->stcCmp.u32Cmp2State | \
pstcEmbInit->stcCmp.u32Cmp3State);
/* PORT */
u32Reg1Value |= (pstcEmbInit->stcPort.stcPort1.u32PortState | pstcEmbInit->stcPort.stcPort1.u32PortLevel | \
pstcEmbInit->stcPort.stcPort1.u32PortFilterDiv | pstcEmbInit->stcPort.stcPort1.u32PortFilterState);
WRITE_REG32(EMBx->PWMLV, u32Reg2Value);
WRITE_REG32(EMBx->CTL, u32Reg1Value);
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief Set the fields of structure stc_emb_tmr6_init_t to default values
* @param [out] pstcEmbInit Pointer to a @ref stc_emb_tmr6_init_t structure
* @retval int32_t:
* - LL_OK: Initialize successfully.
* - LL_ERR_INVD_PARAM: The pointer pstcEmbInit value is NULL.
*/
int32_t EMB_TMR6_StructInit(stc_emb_tmr6_init_t *pstcEmbInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (NULL != pstcEmbInit) {
/* OSC */
pstcEmbInit->stcOsc.u32OscState = EMB_OSC_DISABLE;
/* CMP */
pstcEmbInit->stcCmp.u32Cmp1State = EMB_CMP1_DISABLE;
pstcEmbInit->stcCmp.u32Cmp2State = EMB_CMP2_DISABLE;
pstcEmbInit->stcCmp.u32Cmp3State = EMB_CMP3_DISABLE;
/* Port */
pstcEmbInit->stcPort.stcPort1.u32PortState = EMB_PORT1_DISABLE;
pstcEmbInit->stcPort.stcPort1.u32PortLevel = EMB_PORT1_DETECT_LVL_HIGH;
pstcEmbInit->stcPort.stcPort1.u32PortFilterDiv = EMB_PORT1_FILTER_CLK_DIV1;
pstcEmbInit->stcPort.stcPort1.u32PortFilterState = EMB_PORT1_FILTER_DISABLE;
/* PWM */
pstcEmbInit->stcTmr6.stcTmr6_1.u32PwmLevel = EMB_DETECT_TMR6_1_PWM_BOTH_LOW;
pstcEmbInit->stcTmr6.stcTmr6_1.u32PwmState = EMB_TMR6_1_PWM_DISABLE;
pstcEmbInit->stcTmr6.stcTmr6_2.u32PwmLevel = EMB_DETECT_TMR6_2_PWM_BOTH_LOW;
pstcEmbInit->stcTmr6.stcTmr6_2.u32PwmState = EMB_TMR6_2_PWM_DISABLE;
pstcEmbInit->stcTmr6.stcTmr6_3.u32PwmLevel = EMB_DETECT_TMR6_3_PWM_BOTH_LOW;
pstcEmbInit->stcTmr6.stcTmr6_3.u32PwmState = EMB_TMR6_3_PWM_DISABLE;
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief Initialize EMB for TMR6.
* @param [in] EMBx Pointer to EMB instance register base
* This parameter can be one of the following values:
* @arg CM_EMBx: EMB group instance register base
* @param [in] pstcEmbInit Pointer to a @ref stc_emb_tmr6_init_t structure
* @retval int32_t:
* - LL_OK: Initialize successfully.
* - LL_ERR_INVD_PARAM: The pointer pstcEmbInit value is NULL.
*/
int32_t EMB_TMR6_Init(CM_EMB_TypeDef *EMBx, const stc_emb_tmr6_init_t *pstcEmbInit)
{
uint32_t u32Reg1Value;
uint32_t u32Reg2Value;
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (NULL != pstcEmbInit) {
DDL_ASSERT(IS_EMB_TMR6_GROUP(EMBx));
DDL_ASSERT(IS_EMB_OSC_STAT(pstcEmbInit->stcOsc.u32OscState));
DDL_ASSERT(IS_EMB_CMP1_STAT(pstcEmbInit->stcCmp.u32Cmp1State));
DDL_ASSERT(IS_EMB_CMP2_STAT(pstcEmbInit->stcCmp.u32Cmp2State));
DDL_ASSERT(IS_EMB_CMP3_STAT(pstcEmbInit->stcCmp.u32Cmp3State));
DDL_ASSERT(IS_EMB_PORT1_STAT(pstcEmbInit->stcPort.stcPort1.u32PortState));
DDL_ASSERT(IS_EMB_PORT1_DETECT_LVL(pstcEmbInit->stcPort.stcPort1.u32PortLevel));
DDL_ASSERT(IS_EMB_PORT1_FILTER_DIV(pstcEmbInit->stcPort.stcPort1.u32PortFilterDiv));
DDL_ASSERT(IS_EMB_PORT1_FILTER_STAT(pstcEmbInit->stcPort.stcPort1.u32PortFilterState));
DDL_ASSERT(IS_EMB_TMR6_1_PWM_STAT(pstcEmbInit->stcTmr6.stcTmr6_1.u32PwmState));
DDL_ASSERT(IS_EMB_DETECT_TMR6_1_PWM_LVL(pstcEmbInit->stcTmr6.stcTmr6_1.u32PwmLevel));
DDL_ASSERT(IS_EMB_TMR6_2_PWM_STAT(pstcEmbInit->stcTmr6.stcTmr6_2.u32PwmState));
DDL_ASSERT(IS_EMB_DETECT_TMR6_2_PWM_LVL(pstcEmbInit->stcTmr6.stcTmr6_2.u32PwmLevel));
DDL_ASSERT(IS_EMB_TMR6_3_PWM_STAT(pstcEmbInit->stcTmr6.stcTmr6_3.u32PwmState));
DDL_ASSERT(IS_EMB_DETECT_TMR6_3_PWM_LVL(pstcEmbInit->stcTmr6.stcTmr6_3.u32PwmLevel));
/* OSC */
u32Reg2Value = 0UL;
u32Reg1Value = pstcEmbInit->stcOsc.u32OscState;
/* PWM */
u32Reg1Value |= (pstcEmbInit->stcTmr6.stcTmr6_1.u32PwmState | pstcEmbInit->stcTmr6.stcTmr6_2.u32PwmState | \
pstcEmbInit->stcTmr6.stcTmr6_3.u32PwmState);
u32Reg2Value |= (pstcEmbInit->stcTmr6.stcTmr6_1.u32PwmLevel | pstcEmbInit->stcTmr6.stcTmr6_2.u32PwmLevel | \
pstcEmbInit->stcTmr6.stcTmr6_3.u32PwmLevel);
/* CMP */
u32Reg1Value |= (pstcEmbInit->stcCmp.u32Cmp1State | pstcEmbInit->stcCmp.u32Cmp2State | \
pstcEmbInit->stcCmp.u32Cmp3State);
/* PORT */
u32Reg1Value |= (pstcEmbInit->stcPort.stcPort1.u32PortState | pstcEmbInit->stcPort.stcPort1.u32PortFilterDiv | \
pstcEmbInit->stcPort.stcPort1.u32PortLevel | pstcEmbInit->stcPort.stcPort1.u32PortFilterState);
WRITE_REG32(EMBx->PWMLV, u32Reg2Value);
WRITE_REG32(EMBx->CTL, u32Reg1Value);
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief De-Initialize EMB function
* @param [in] EMBx Pointer to EMB instance register base
* This parameter can be one of the following values:
* @arg CM_EMBx: EMB group instance register base
* @retval None
*/
void EMB_DeInit(CM_EMB_TypeDef *EMBx)
{
DDL_ASSERT(IS_EMB_GROUP(EMBx));
WRITE_REG32(EMBx->SOE, 0x00UL);
WRITE_REG32(EMBx->INTEN, 0x00UL);
}
/**
* @brief Set the EMB interrupt function
* @param [in] EMBx Pointer to EMB instance register base
* This parameter can be one of the following values:
* @arg CM_EMBx: EMB group instance register base
* @param [in] u32IntType EMB interrupt source
* This parameter can be any composed value of the macros group @ref EMB_Interrupt.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void EMB_IntCmd(CM_EMB_TypeDef *EMBx, uint32_t u32IntType, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_EMB_GROUP(EMBx));
DDL_ASSERT(IS_VALID_EMB_INT(u32IntType));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(EMBx->INTEN, u32IntType);
} else {
CLR_REG32_BIT(EMBx->INTEN, u32IntType);
}
}
/**
* @brief Get EMB flag status.
* @param [in] EMBx Pointer to EMB instance register base
* This parameter can be one of the following values:
* @arg CM_EMBx: EMB group instance register base
* @param [in] u32Flag EMB flag
* This parameter can be any composed value(prefix with EMB_FLAG) of the macros group @ref EMB_Flag_State.
* @retval None
* @note This parameter u32Flag prefix with EMB_FLAG(eg EMB_FLAG_CMP) of the macros group @ref EMB_Flag_State.
*/
void EMB_ClearStatus(CM_EMB_TypeDef *EMBx, uint32_t u32Flag)
{
/* Check parameters */
DDL_ASSERT(IS_EMB_GROUP(EMBx));
DDL_ASSERT(IS_EMB_FLAG(u32Flag));
SET_REG32_BIT(EMBx->STATCLR, u32Flag);
}
/**
* @brief Clear EMB flag status.
* @param [in] EMBx Pointer to EMB instance register base
* This parameter can be one of the following values:
* @arg CM_EMBx: EMB group instance register base
* @param [in] u32Flag EMB flag
* This parameter can be any composed value of the macros group @ref EMB_Flag_State.
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t EMB_GetStatus(const CM_EMB_TypeDef *EMBx, uint32_t u32Flag)
{
DDL_ASSERT(IS_EMB_GROUP(EMBx));
DDL_ASSERT(IS_EMB_FLAG(u32Flag));
return (READ_REG32_BIT(EMBx->STAT, u32Flag) == 0UL) ? RESET : SET;
}
/**
* @brief Start/stop EMB brake by software control
* @param [in] EMBx Pointer to EMB instance register base
* This parameter can be one of the following values:
* @arg CM_EMBx: EMB group instance register base
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void EMB_SWBrake(CM_EMB_TypeDef *EMBx, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_EMB_GROUP(EMBx));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
WRITE_REG32(EMBx->SOE, enNewState);
}
/**
* @}
*/
#endif /* LL_EMB_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+444
View File
@@ -0,0 +1,444 @@
/**
*******************************************************************************
* @file hc32_ll_event_port.c
* @brief This file provides firmware functions to manage the Event Port (EP).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2023-09-30 CDT Modify typo
Modify for new head file
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_event_port.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_EVENT_PORT EVENT_PORT
* @brief Event Port Driver Library
* @{
*/
#if (LL_EVENT_PORT_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup EP_Local_Macros Event Port Local Macros
* @{
*/
#define EP_OFFSET (0x1CUL)
#define PEVNTDIR_REG(x) (*(__IO uint32_t *)((uint32_t)(&CM_AOS->PEVNTDIRR1) + (EP_OFFSET * (x))))
#define PEVNTIDR_REG(x) (*(__IO uint32_t *)((uint32_t)(&CM_AOS->PEVNTIDR1) + (EP_OFFSET * (x))))
#define PEVNTODR_REG(x) (*(__IO uint32_t *)((uint32_t)(&CM_AOS->PEVNTODR1) + (EP_OFFSET * (x))))
#define PEVNTORR_REG(x) (*(__IO uint32_t *)((uint32_t)(&CM_AOS->PEVNTORR1) + (EP_OFFSET * (x))))
#define PEVNTOSR_REG(x) (*(__IO uint32_t *)((uint32_t)(&CM_AOS->PEVNTOSR1) + (EP_OFFSET * (x))))
#define PEVNTRIS_REG(x) (*(__IO uint32_t *)((uint32_t)(&CM_AOS->PEVNTRISR1) + (EP_OFFSET * (x))))
#define PEVNTFAL_REG(x) (*(__IO uint32_t *)((uint32_t)(&CM_AOS->PEVNTFALR1) + (EP_OFFSET * (x))))
#define PEVNTTRGSR_RST_VALUE (0x1FFUL)
#define EP_PIN_MAX (16U)
/**
* @defgroup EP_Check_Parameters_Validity Event Port Check Parameters Validity
* @{
*/
/*! Parameter validity check for port group. */
#define IS_EVENT_PORT(port) \
( ((port) == EVT_PORT_1) || \
((port) == EVT_PORT_2) || \
((port) == EVT_PORT_3) || \
((port) == EVT_PORT_4))
/*! Parameter valid check for event port trigger edge. */
#define IS_EP_TRIG_EDGE(edge) \
( ((edge) == EP_TRIG_NONE) || \
((edge) == EP_TRIG_FALLING) || \
((edge) == EP_TRIG_RISING) || \
((edge) == EP_TRIG_BOTH))
/*! Parameter valid check for event port initial output state. */
#define IS_EP_STATE(state) \
( ((state) == EVT_PIN_RESET) || \
((state) == EVT_PIN_SET))
/*! Parameter valid check for event port filter function. */
#define IS_EP_FILTER(filter) \
( ((filter) == EP_FILTER_OFF) || \
((filter) == EP_FILTER_ON))
/*! Parameter validity check for pin. */
#define IS_EVENT_PIN(pin) (((pin) & EVT_PIN_MASK ) != 0x0000U)
/*! Parameter valid check for event port operation after triggered. */
#define IS_EP_OPS(ops) \
( ((ops) == EP_OPS_NONE) || \
((ops) == EP_OPS_LOW) || \
((ops) == EP_OPS_HIGH) || \
((ops) == EP_OPS_TOGGLE))
/*! Parameter valid check for event port direction. */
#define IS_EP_DIR(dir) \
( ((dir) == EP_DIR_IN) || \
((dir) == EP_DIR_OUT))
/*! Parameter valid check for event port filter clock div. */
#define IS_EP_FILTER_CLK(clk) \
( ((clk) == EP_FCLK_DIV1) || \
((clk) == EP_FCLK_DIV8) || \
((clk) == EP_FCLK_DIV32) || \
((clk) == EP_FCLK_DIV64))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup EP_Global_Functions Event Port Global Functions
* @{
*/
/**
* @brief Initialize Event Port.
* @param [in] u8EventPort: EVENT_PORT_x, x can be (1~4) to select the EP port peripheral
* @param [in] u16EventPin: EVENT_PIN_x, x can be (00~15) to select the EP pin index
* @param [in] pstcEventPortInit Pointer to a stc_ep_init_t structure that
* contains configuration information.
* @retval int32_t:
* - LL_OK: Event Port initialize successful
* - LL_ERR_INVD_PARAM: NULL pointer
*/
int32_t EP_Init(uint8_t u8EventPort, uint16_t u16EventPin, const stc_ep_init_t *pstcEventPortInit)
{
uint16_t u16PinPos;
int32_t i32Ret = LL_OK;
if (NULL == pstcEventPortInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
DDL_ASSERT(IS_EVENT_PORT(u8EventPort));
DDL_ASSERT(IS_EVENT_PIN(u16EventPin));
DDL_ASSERT(IS_EP_OPS(pstcEventPortInit->u32PinTriggerOps));
DDL_ASSERT(IS_EP_DIR(pstcEventPortInit->u32PinDir));
DDL_ASSERT(IS_EP_STATE(pstcEventPortInit->enPinState));
DDL_ASSERT(IS_EP_TRIG_EDGE(pstcEventPortInit->u32Edge));
DDL_ASSERT(IS_EP_FILTER(pstcEventPortInit->u32Filter));
DDL_ASSERT(IS_EP_FILTER_CLK(pstcEventPortInit->u32FilterClock));
for (u16PinPos = 0U; u16PinPos < EP_PIN_MAX; u16PinPos++) {
if ((u16EventPin & (1UL << u16PinPos)) != 0U) {
/* Direction config */
if (EP_DIR_OUT == pstcEventPortInit->u32PinDir) {
SET_REG32_BIT(PEVNTDIR_REG(u8EventPort), u16EventPin);
} else {
CLR_REG32_BIT(PEVNTDIR_REG(u8EventPort), u16EventPin);
}
/* Set pin initial output value */
if (EVT_PIN_SET == pstcEventPortInit->enPinState) {
SET_REG32_BIT(PEVNTODR_REG(u8EventPort), u16EventPin);
} else {
CLR_REG32_BIT(PEVNTODR_REG(u8EventPort), u16EventPin);
}
/* Set Pin operation after triggered */
(void)EP_SetTriggerOps(u8EventPort, u16EventPin, pstcEventPortInit->u32PinTriggerOps);
/* Set trigger edge */
(void)EP_SetTriggerEdge(u8EventPort, u16EventPin, pstcEventPortInit->u32Edge);
}
MODIFY_REG32(CM_AOS->PEVNTNFCR, \
((AOS_PEVNTNFCR_NFEN1 | AOS_PEVNTNFCR_DIVS1) << (u8EventPort * 8UL)), \
((pstcEventPortInit->u32Filter | pstcEventPortInit->u32FilterClock) << (u8EventPort * 8UL)));
}
}
return i32Ret;
}
/**
* @brief De-init Event Port register to default value
* @param None
* @retval None
*/
void EP_DeInit(void)
{
uint8_t u8EventPort;
/* Restore all registers to default value */
WRITE_REG32(CM_AOS->PEVNT_TRGSEL12, PEVNTTRGSR_RST_VALUE);
WRITE_REG32(CM_AOS->PEVNT_TRGSEL34, PEVNTTRGSR_RST_VALUE);
WRITE_REG32(CM_AOS->PEVNTNFCR, 0UL);
for (u8EventPort = EVT_PORT_1; u8EventPort < EVT_PORT_4; u8EventPort++) {
WRITE_REG32(PEVNTDIR_REG(u8EventPort), 0UL);
WRITE_REG32(PEVNTODR_REG(u8EventPort), 0UL);
WRITE_REG32(PEVNTORR_REG(u8EventPort), 0UL);
WRITE_REG32(PEVNTOSR_REG(u8EventPort), 0UL);
WRITE_REG32(PEVNTRIS_REG(u8EventPort), 0UL);
WRITE_REG32(PEVNTFAL_REG(u8EventPort), 0UL);
}
}
/**
* @brief Initialize Event Port config structure. Fill each pstcEventPortInit with default value
* @param [in] pstcEventPortInit: Pointer to a stc_ep_init_t structure that
* contains configuration information.
* @retval int32_t:
* - LL_OK: Event Port structure initialize successful
* - LL_ERR_INVD_PARAM: NULL pointer
*/
int32_t EP_StructInit(stc_ep_init_t *pstcEventPortInit)
{
int32_t i32Ret = LL_OK;
/* Check if pointer is NULL */
if (NULL == pstcEventPortInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Reset Event Port init structure parameters values */
pstcEventPortInit->u32PinDir = EP_DIR_IN;
pstcEventPortInit->enPinState = EVT_PIN_RESET;
pstcEventPortInit->u32PinTriggerOps = EP_OPS_NONE;
pstcEventPortInit->u32Edge = EP_TRIG_NONE;
pstcEventPortInit->u32Filter = EP_FILTER_OFF;
pstcEventPortInit->u32FilterClock = EP_FCLK_DIV1;
}
return i32Ret;
}
/**
* @brief Set event port trigger edge.
* @param [in] u8EventPort: EVENT_PORT_x, x can be (1~4) to select the EP port peripheral
* @param [in] u16EventPin: EVENT_PIN_x, x can be (00~15) to select the EP pin index
* @param [in] u32Edge: Trigger edge, @ref EP_Trigger_Sel for details
* @retval int32_t:
* - LL_OK: Trigger edge set successful
* - LL_ERR_INVD_PARAM: Undefined edge
*/
int32_t EP_SetTriggerEdge(uint8_t u8EventPort, uint16_t u16EventPin, uint32_t u32Edge)
{
int32_t i32Ret = LL_OK;
DDL_ASSERT(IS_EVENT_PORT(u8EventPort));
DDL_ASSERT(IS_EVENT_PIN(u16EventPin));
DDL_ASSERT(IS_EP_TRIG_EDGE(u32Edge));
/* Set trigger edge */
switch (u32Edge) {
case EP_TRIG_NONE:
CLR_REG32_BIT(PEVNTFAL_REG(u8EventPort), u16EventPin);
CLR_REG32_BIT(PEVNTRIS_REG(u8EventPort), u16EventPin);
break;
case EP_TRIG_FALLING:
SET_REG32_BIT(PEVNTFAL_REG(u8EventPort), u16EventPin);
CLR_REG32_BIT(PEVNTRIS_REG(u8EventPort), u16EventPin);
break;
case EP_TRIG_RISING:
CLR_REG32_BIT(PEVNTFAL_REG(u8EventPort), u16EventPin);
SET_REG32_BIT(PEVNTRIS_REG(u8EventPort), u16EventPin);
break;
case EP_TRIG_BOTH:
SET_REG32_BIT(PEVNTFAL_REG(u8EventPort), u16EventPin);
SET_REG32_BIT(PEVNTRIS_REG(u8EventPort), u16EventPin);
break;
default:
i32Ret = LL_ERR_INVD_PARAM;
break;
}
return i32Ret;
}
/**
* @brief Set event port operation after triggered
* @param [in] u8EventPort: EVENT_PORT_x, x can be (1~4) to select the EP peripheral
* @param [in] u16EventPin: EVENT_PIN_x, x can be (00~15) to select the EP pin index
* @param [in] u32Ops: The operation after triggered, @ref EP_TriggerOps_Sel for details
* @retval Specified Event port pin input value
*/
int32_t EP_SetTriggerOps(uint8_t u8EventPort, uint16_t u16EventPin, uint32_t u32Ops)
{
int32_t i32Ret = LL_OK;
DDL_ASSERT(IS_EVENT_PORT(u8EventPort));
DDL_ASSERT(IS_EVENT_PIN(u16EventPin));
DDL_ASSERT(IS_EP_OPS(u32Ops));
switch (u32Ops) {
case EP_OPS_NONE:
CLR_REG32_BIT(PEVNTORR_REG(u8EventPort), u16EventPin);
CLR_REG32_BIT(PEVNTOSR_REG(u8EventPort), u16EventPin);
break;
case EP_OPS_LOW:
SET_REG32_BIT(PEVNTORR_REG(u8EventPort), u16EventPin);
CLR_REG32_BIT(PEVNTOSR_REG(u8EventPort), u16EventPin);
break;
case EP_OPS_HIGH:
CLR_REG32_BIT(PEVNTORR_REG(u8EventPort), u16EventPin);
SET_REG32_BIT(PEVNTOSR_REG(u8EventPort), u16EventPin);
break;
case EP_OPS_TOGGLE:
SET_REG32_BIT(PEVNTORR_REG(u8EventPort), u16EventPin);
SET_REG32_BIT(PEVNTOSR_REG(u8EventPort), u16EventPin);
break;
default:
i32Ret = LL_ERR_INVD_PARAM;
break;
}
return i32Ret;
}
/**
* @brief Read specified Event port input data port pins
* @param [in] u8EventPort: EVENT_PORT_x, x can be (1~4) to select the EP peripheral
* @param [in] u16EventPin: EVENT_PIN_x, x can be (00~15) to select the EP pin index
* @retval Specified Event port pin input value
*/
en_ep_state_t EP_ReadInputPins(uint8_t u8EventPort, uint16_t u16EventPin)
{
DDL_ASSERT(IS_EVENT_PORT(u8EventPort));
DDL_ASSERT(IS_EVENT_PIN(u16EventPin));
return ((READ_REG32(PEVNTIDR_REG(u8EventPort)) & (u16EventPin)) != 0UL) ? EVT_PIN_SET : EVT_PIN_RESET;
}
/**
* @brief Read specified Event port input data port
* @param [in] u8EventPort: EVENT_PORT_x, x can be (1~4) to select the Event Port peripheral
* @retval Specified Event Port input value
*/
uint16_t EP_ReadInputPort(uint8_t u8EventPort)
{
DDL_ASSERT(IS_EVENT_PORT(u8EventPort));
return (uint16_t)(READ_REG32(PEVNTIDR_REG(u8EventPort)) & 0xFFFFUL);
}
/**
* @brief Read specified Event port output data port pins
* @param [in] u8EventPort: EVENT_PORT_x, x can be (1~4) to select the EP peripheral
* @param [in] u16EventPin: EVENT_PIN_x, x can be (00~15) to select the EP pin index
* @retval Specified Event port pin output value
*/
en_ep_state_t EP_ReadOutputPins(uint8_t u8EventPort, uint16_t u16EventPin)
{
DDL_ASSERT(IS_EVENT_PORT(u8EventPort));
DDL_ASSERT(IS_EVENT_PIN(u16EventPin));
return ((READ_REG32(PEVNTODR_REG(u8EventPort)) & (u16EventPin)) != 0UL) ? EVT_PIN_SET : EVT_PIN_RESET;
}
/**
* @brief Read specified Event port output data port
* @param [in] u8EventPort: EVENT_PORT_x, x can be (1~4) to select the Event Port peripheral
* @retval Specified Event Port output value
*/
uint16_t EP_ReadOutputPort(uint8_t u8EventPort)
{
DDL_ASSERT(IS_EVENT_PORT(u8EventPort));
return (uint16_t)(READ_REG32(PEVNTODR_REG(u8EventPort)) & 0xFFFFUL);
}
/**
* @brief Set specified Event port output data port pins
* @param [in] u8EventPort: EVENT_PORT_x, x can be (1~4) to select the EP peripheral
* @param [in] u16EventPin: EVENT_PIN_x, x can be (00~15) to select the EP pin index
* @retval None
*/
void EP_SetPins(uint8_t u8EventPort, uint16_t u16EventPin)
{
DDL_ASSERT(IS_EVENT_PORT(u8EventPort));
DDL_ASSERT(IS_EVENT_PIN(u16EventPin));
SET_REG32_BIT(PEVNTODR_REG(u8EventPort), u16EventPin);
}
/**
* @brief Reset specified Event port output data port pins
* @param [in] u8EventPort: EVENT_PORT_x, x can be (1~4) to select the EP peripheral
* @param [in] u16EventPin: EVENT_PIN_x, x can be (00~15) to select the EP pin index
* @retval None
*/
void EP_ResetPins(uint8_t u8EventPort, uint16_t u16EventPin)
{
DDL_ASSERT(IS_EVENT_PORT(u8EventPort));
DDL_ASSERT(IS_EVENT_PIN(u16EventPin));
CLR_REG32_BIT(PEVNTODR_REG(u8EventPort), u16EventPin);
}
/**
* @brief Set specified Event port pins direction
* @param [in] u8EventPort: EVENT_PORT_x, x can be (1~4) to select the EP peripheral
* @param [in] u16EventPin: EVENT_PIN_x, x can be (00~15) to select the EP pin index
* @param [in] u32Dir: Pin direction
* @arg EP_DIR_IN
* @arg EP_DIR_OUT
* @retval None
*/
void EP_SetDir(uint8_t u8EventPort, uint16_t u16EventPin, uint32_t u32Dir)
{
DDL_ASSERT(IS_EVENT_PORT(u8EventPort));
DDL_ASSERT(IS_EVENT_PIN(u16EventPin));
DDL_ASSERT(IS_EP_DIR(u32Dir));
if (EP_DIR_OUT == u32Dir) {
SET_REG32_BIT(PEVNTDIR_REG(u8EventPort), u16EventPin);
} else {
CLR_REG32_BIT(PEVNTDIR_REG(u8EventPort), u16EventPin);
}
}
/**
* @}
*/
#endif /* LL_EVENT_PORT_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+194
View File
@@ -0,0 +1,194 @@
/**
*******************************************************************************
* @file hc32_ll_fcg.c
* @brief This file provides firmware functions to manage the Function Clock
* Gate (FCG).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_fcg.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_FCG FCG
* @brief FCG Driver Library
* @{
*/
#if (LL_FCG_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup FCG_Local_Macros FCG Local Macros
* @{
*/
#define IS_FCG0_UNLOCKED() ((CM_PWC->FCG0PC & PWC_FCG0PC_PRT0) == PWC_FCG0PC_PRT0)
/**
* @defgroup FCG_Check_Parameters_Validity FCG Check Parameters Validity
* @{
*/
/* Parameter validity check for peripheral in fcg0. */
#define IS_FCG0_PERIPH(per) \
( ((per) != 0x00UL) && \
(((per) | FCG_FCG0_PERIPH_MASK) == FCG_FCG0_PERIPH_MASK))
/* Parameter validity check for peripheral in fcg1. */
#define IS_FCG1_PERIPH(per) \
( ((per) != 0x00UL) && \
(((per) | FCG_FCG1_PERIPH_MASK) == FCG_FCG1_PERIPH_MASK))
/* Parameter validity check for peripheral in fcg2. */
#define IS_FCG2_PERIPH(per) \
( ((per) != 0x00UL) && \
(((per) | FCG_FCG2_PERIPH_MASK) == FCG_FCG2_PERIPH_MASK))
/* Parameter validity check for peripheral in fcg3. */
#define IS_FCG3_PERIPH(per) \
( ((per) != 0x00UL) && \
(((per) | FCG_FCG3_PERIPH_MASK) == FCG_FCG3_PERIPH_MASK))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup FCG_Global_Functions FCG Global Functions
* @{
*/
/**
* @brief Enable or disable the FCG0 peripheral clock.
* @param [in] u32Fcg0Periph The peripheral in FCG0 @ref FCG_FCG0_Peripheral.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void FCG_Fcg0PeriphClockCmd(uint32_t u32Fcg0Periph, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FCG0_PERIPH(u32Fcg0Periph));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
DDL_ASSERT(IS_FCG0_UNLOCKED());
if (ENABLE == enNewState) {
CLR_REG32_BIT(CM_PWC->FCG0, u32Fcg0Periph);
} else {
SET_REG32_BIT(CM_PWC->FCG0, u32Fcg0Periph);
}
}
/**
* @brief Enable or disable the FCG1 peripheral clock.
* @param [in] u32Fcg1Periph The peripheral in FCG1 @ref FCG_FCG1_Peripheral.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void FCG_Fcg1PeriphClockCmd(uint32_t u32Fcg1Periph, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FCG1_PERIPH(u32Fcg1Periph));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
CLR_REG32_BIT(CM_PWC->FCG1, u32Fcg1Periph);
} else {
SET_REG32_BIT(CM_PWC->FCG1, u32Fcg1Periph);
}
}
/**
* @brief Enable or disable the FCG2 peripheral clock.
* @param [in] u32Fcg2Periph The peripheral in FCG2 @ref FCG_FCG2_Peripheral.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void FCG_Fcg2PeriphClockCmd(uint32_t u32Fcg2Periph, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FCG2_PERIPH(u32Fcg2Periph));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
CLR_REG32_BIT(CM_PWC->FCG2, u32Fcg2Periph);
} else {
SET_REG32_BIT(CM_PWC->FCG2, u32Fcg2Periph);
}
}
/**
* @brief Enable or disable the FCG3 peripheral clock.
* @param [in] u32Fcg3Periph The peripheral in FCG3 @ref FCG_FCG3_Peripheral.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void FCG_Fcg3PeriphClockCmd(uint32_t u32Fcg3Periph, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FCG3_PERIPH(u32Fcg3Periph));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
CLR_REG32_BIT(CM_PWC->FCG3, u32Fcg3Periph);
} else {
SET_REG32_BIT(CM_PWC->FCG3, u32Fcg3Periph);
}
}
#endif /* LL_FCG_ENABLE */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+388
View File
@@ -0,0 +1,388 @@
/**
*******************************************************************************
* @file hc32_ll_fcm.c
* @brief This file provides firmware functions to manage the Frequency Clock
* Measurement (FCM).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2022-10-31 CDT Modify parameter check for reference clock source
2023-06-30 CDT Modify API FCM_DeInit()
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_fcm.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_FCM FCM
* @brief FCM Driver Library
* @{
*/
#if (LL_FCM_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup FCM_Local_Macros FCM Local Macros
* @{
*/
/* FCM Registers RESET Value */
#define FCM_REG_RST_VALUE (0x00000000UL)
/* FCM interrupt mask */
#define FCM_INT_MASK (FCM_INT_OVF | FCM_INT_END | FCM_INT_ERR)
/* FCM status flag mask */
#define FCM_FLAG_MASK (FCM_SR_ERRF | FCM_SR_MENDF | FCM_SR_OVF)
/**
* @defgroup FCM_Check_Parameters_Validity FCM Check Parameters Validity
* @{
*/
/* Parameter validity check for FCM target and reference clock source. */
#define IS_FCM_TARGET_SRC(x) \
( ((x) == FCM_TARGET_CLK_XTAL) || \
((x) == FCM_TARGET_CLK_XTAL32) || \
((x) == FCM_TARGET_CLK_HRC) || \
((x) == FCM_TARGET_CLK_LRC) || \
((x) == FCM_TARGET_CLK_SWDTLRC) || \
((x) == FCM_TARGET_CLK_PCLK1) || \
((x) == FCM_TARGET_CLK_UPLLP) || \
((x) == FCM_TARGET_CLK_MRC) || \
((x) == FCM_TARGET_CLK_MPLLP))
#define IS_FCM_REF_SRC(x) \
( ((x) == FCM_REF_CLK_EXTCLK) || \
((x) == FCM_REF_CLK_XTAL) || \
((x) == FCM_REF_CLK_XTAL32) || \
((x) == FCM_REF_CLK_HRC) || \
((x) == FCM_REF_CLK_LRC) || \
((x) == FCM_REF_CLK_SWDTLRC) || \
((x) == FCM_REF_CLK_PCLK1) || \
((x) == FCM_REF_CLK_UPLLP) || \
((x) == FCM_REF_CLK_MRC) || \
((x) == FCM_REF_CLK_MPLLP))
/* Parameter validity check for FCM target clock division. */
#define IS_FCM_TARGET_DIV(x) \
( ((x) == FCM_TARGET_CLK_DIV1) || \
((x) == FCM_TARGET_CLK_DIV4) || \
((x) == FCM_TARGET_CLK_DIV8) || \
((x) == FCM_TARGET_CLK_DIV32))
/* Parameter validity check for FCM external reference input function. */
#define IS_FCM_EXT_REF_FUNC(x) \
( ((x) == FCM_EXT_REF_OFF) || \
((x) == FCM_EXT_REF_ON))
/* Parameter validity check for FCM reference clock edge. */
#define IS_FCM_REF_EDGE(x) \
( ((x) == FCM_REF_CLK_RISING) || \
((x) == FCM_REF_CLK_FALLING) || \
((x) == FCM_REF_CLK_BOTH))
/* Parameter validity check for FCM digital filter function. */
#define IS_FCM_DIG_FILTER(x) \
( ((x) == FCM_DIG_FILTER_OFF) || \
((x) == FCM_DIG_FILTER_DIV1) || \
((x) == FCM_DIG_FILTER_DIV4) || \
((x) == FCM_DIG_FILTER_DIV16))
/* Parameter validity check for FCM reference clock division. */
#define IS_FCM_REF_DIV(x) \
( ((x) == FCM_REF_CLK_DIV32) || \
((x) == FCM_REF_CLK_DIV128) || \
((x) == FCM_REF_CLK_DIV1024) || \
((x) == FCM_REF_CLK_DIV8192))
/* Parameter validity check for FCM exception type function. */
#define IS_FCM_EXP_TYPE(x) \
( ((x) == FCM_EXP_TYPE_INT) || \
((x) == FCM_EXP_TYPE_RST))
/* Parameter validity check for FCM interrupt. */
#define IS_FCM_INT(x) (((x) | FCM_INT_MASK) == FCM_INT_MASK)
/* Parameter validity check for FCM flag state. */
#define IS_FCM_FLAG(x) \
( ((x) != 0x00UL) && \
(((x) | FCM_FLAG_MASK) == FCM_FLAG_MASK))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup FCM_Global_Functions FCM Global Functions
* @{
*/
/**
* @brief Initialize FCM.
* @param [in] pstcFcmInit Pointer to a @ref stc_fcm_init_t structure
* that contains configuration information.
* @retval int32_t:
* - LL_OK: FCM initialize successful
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t FCM_Init(const stc_fcm_init_t *pstcFcmInit)
{
int32_t i32Ret = LL_OK;
/* Check if pointer is NULL */
if (NULL == pstcFcmInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Parameter validity checking */
DDL_ASSERT(IS_FCM_TARGET_SRC(pstcFcmInit->u32TargetClock));
DDL_ASSERT(IS_FCM_TARGET_DIV(pstcFcmInit->u32TargetClockDiv));
DDL_ASSERT(IS_FCM_EXT_REF_FUNC(pstcFcmInit->u32ExtRefClockEnable));
DDL_ASSERT(IS_FCM_REF_EDGE(pstcFcmInit->u32RefClockEdge));
DDL_ASSERT(IS_FCM_DIG_FILTER(pstcFcmInit->u32DigitalFilter));
DDL_ASSERT(IS_FCM_REF_SRC(pstcFcmInit->u32RefClock));
DDL_ASSERT(IS_FCM_REF_DIV(pstcFcmInit->u32RefClockDiv));
DDL_ASSERT(IS_FCM_EXP_TYPE(pstcFcmInit->u32ExceptionType));
WRITE_REG32(CM_FCM->LVR, pstcFcmInit->u16LowerLimit);
WRITE_REG32(CM_FCM->UVR, pstcFcmInit->u16UpperLimit);
WRITE_REG32(CM_FCM->MCCR, (pstcFcmInit->u32TargetClock | pstcFcmInit->u32TargetClockDiv));
WRITE_REG32(CM_FCM->RCCR, (pstcFcmInit->u32ExtRefClockEnable | pstcFcmInit->u32RefClockEdge |
pstcFcmInit->u32DigitalFilter | pstcFcmInit->u32RefClock |
pstcFcmInit->u32RefClockDiv));
MODIFY_REG32(CM_FCM->RIER, FCM_RIER_ERRINTRS, pstcFcmInit->u32ExceptionType);
}
return i32Ret;
}
/**
* @brief Initialize FCM structure. Fill each pstcFcmInit with default value.
* @param [in] pstcFcmInit Pointer to a @ref stc_fcm_init_t structure
* that contains configuration information.
* @retval int32_t:
* - LL_OK: FCM structure initialize successful
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t FCM_StructInit(stc_fcm_init_t *pstcFcmInit)
{
int32_t i32Ret = LL_OK;
/* Check if pointer is NULL */
if (NULL == pstcFcmInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* RESET FCM init structure parameters values */
pstcFcmInit->u16LowerLimit = 0U;
pstcFcmInit->u16UpperLimit = 0U;
pstcFcmInit->u32TargetClock = FCM_TARGET_CLK_XTAL;
pstcFcmInit->u32TargetClockDiv = FCM_TARGET_CLK_DIV1;
pstcFcmInit->u32ExtRefClockEnable = FCM_EXT_REF_OFF;
pstcFcmInit->u32RefClockEdge = FCM_REF_CLK_RISING;
pstcFcmInit->u32DigitalFilter = FCM_DIG_FILTER_OFF;
pstcFcmInit->u32RefClock = FCM_REF_CLK_XTAL;
pstcFcmInit->u32RefClockDiv = FCM_REF_CLK_DIV32;
pstcFcmInit->u32ExceptionType = FCM_EXP_TYPE_INT;
}
return i32Ret;
}
/**
* @brief De-Initialize FCM.
* @param None
* @retval int32_t:
* - LL_OK: De-Initialize success.
*/
int32_t FCM_DeInit(void)
{
WRITE_REG32(CM_FCM->STR, FCM_REG_RST_VALUE);
WRITE_REG32(CM_FCM->CLR, FCM_FLAG_MASK);
WRITE_REG32(CM_FCM->LVR, FCM_REG_RST_VALUE);
WRITE_REG32(CM_FCM->UVR, FCM_REG_RST_VALUE);
WRITE_REG32(CM_FCM->MCCR, FCM_REG_RST_VALUE);
WRITE_REG32(CM_FCM->RCCR, FCM_REG_RST_VALUE);
WRITE_REG32(CM_FCM->RIER, FCM_REG_RST_VALUE);
return LL_OK;
}
/**
* @brief Get FCM state, get FCM overflow, complete, error flag.
* @param [in] u32Flag FCM flags.This parameter can be one or any
* combination of the following values: @ref FCM_Flag_Sel
* @arg FCM_FLAG_ERR: FCM error.
* @arg FCM_FLAG_END: FCM measure end.
* @arg FCM_FLAG_OVF: FCM overflow.
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t FCM_GetStatus(uint32_t u32Flag)
{
DDL_ASSERT(IS_FCM_FLAG(u32Flag));
return ((READ_REG32_BIT(CM_FCM->SR, u32Flag) != 0UL) ? SET : RESET);
}
/**
* @brief Clear FCM state, Clear FCM overflow, complete, error flag.
* @param [in] u32Flag FCM flags.This parameter can be one or any
* combination of the following values: @ref FCM_Flag_Sel
* @arg FCM_FLAG_ERR: FCM error.
* @arg FCM_FLAG_END: FCM measure end.
* @arg FCM_FLAG_OVF: FCM overflow.
* @retval None.
*/
void FCM_ClearStatus(uint32_t u32Flag)
{
DDL_ASSERT(IS_FCM_FLAG(u32Flag));
SET_REG32_BIT(CM_FCM->CLR, u32Flag);
}
/**
* @brief Get FCM counter value.
* @param None
* @retval FCM counter value.
*/
uint16_t FCM_GetCountValue(void)
{
return (uint16_t)(READ_REG32(CM_FCM->CNTR) & 0xFFFFU);
}
/**
* @brief FCM target clock type and division config.
* @param [in] u32ClockSrc Target clock type. @ref FCM_Target_Clock_Src
* @param [in] u32Div Target clock division. @ref FCM_Target_Clock_Div
* @arg FCM_TARGET_CLK_DIV1
* @arg FCM_TARGET_CLK_DIV4
* @arg FCM_TARGET_CLK_DIV8
* @arg FCM_TARGET_CLK_DIV32
* @retval None.
*/
void FCM_SetTargetClock(uint32_t u32ClockSrc, uint32_t u32Div)
{
DDL_ASSERT(IS_FCM_TARGET_SRC(u32ClockSrc));
DDL_ASSERT(IS_FCM_TARGET_DIV(u32Div));
WRITE_REG32(CM_FCM->MCCR, (u32ClockSrc | u32Div));
}
/**
* @brief FCM reference clock type and division config.
* @param [in] u32ClockSrc Reference clock type. @ref FCM_Ref_Clock_Src
* @param [in] u32Div Reference clock division. @ref FCM_Ref_Clock_Div
* @arg FCM_REF_CLK_DIV32
* @arg FCM_REF_CLK_DIV128
* @arg FCM_REF_CLK_DIV1024
* @arg FCM_REF_CLK_DIV8192
* @retval None.
*/
void FCM_SetRefClock(uint32_t u32ClockSrc, uint32_t u32Div)
{
DDL_ASSERT(IS_FCM_REF_SRC(u32ClockSrc));
DDL_ASSERT(IS_FCM_REF_DIV(u32Div));
MODIFY_REG32(CM_FCM->RCCR, (FCM_RCCR_INEXS | FCM_RCCR_RCKS | FCM_RCCR_RDIVS), (u32ClockSrc | u32Div));
}
/**
* @brief Enable or disable the FCM reset
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void FCM_ResetCmd(en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
WRITE_REG32(bCM_FCM->RIER_b.ERRE, enNewState);
}
/**
* @brief Enable or disable the FCM interrupt
* @param [in] u32IntType The FCM interrupt type. This parameter can be
* one or any combination @ref FCM_Int_Type
* @arg FCM_INT_OVF: FCM overflow interrupt
* @arg FCM_INT_END: FCM calculate end interrupt
* @arg FCM_INT_ERR: FCM frequency abnormal interrupt
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void FCM_IntCmd(uint32_t u32IntType, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FCM_INT(u32IntType));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(CM_FCM->RIER, u32IntType);
} else {
CLR_REG32_BIT(CM_FCM->RIER, u32IntType);
}
}
/**
* @brief FCM function config.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None.
*/
void FCM_Cmd(en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
WRITE_REG32(bCM_FCM->STR_b.START, enNewState);
}
/**
* @}
*/
#endif /* LL_FCM_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+706
View File
@@ -0,0 +1,706 @@
/**
*******************************************************************************
* @file hc32_ll_gpio.c
* @brief This file provides firmware functions to manage the General Purpose
* Input/Output(GPIO).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2022-06-30 CDT Add API GPIO_AnalogCmd() and GPIO_ExIntCmd()
2023-06-30 CDT Modify GPIO_SetFunc()
Rename GPIO_ExIntCmd() as GPIO_ExtIntCmd
Optimize API: GPIO_Init(), GPIO_SetFunc(), GPIO_SubFuncCmd(), GPIO_InputMOSCmd(), GPIO_AnalogCmd(), GPIO_ExtIntCmd()
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_gpio.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_GPIO GPIO
* @brief GPIO Driver Library
* @{
*/
#if (LL_GPIO_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/**
* @defgroup GPIO_Local_Types GPIO Local Typedefs
* @{
*/
/**
* @brief GPIO port pin table definition
*/
typedef struct {
uint8_t u8Port; /*!< GPIO Port Source, @ref GPIO_Port_Source for details */
uint16_t u16PinMask; /*!< Pin active or inactive, @ref GPIO_All_Pins_Define for details */
} stc_gpio_port_pin_tbl_t;
/**
* @}
*/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup GPIO_Local_Macros GPIO Local Macros
* @{
*/
/**
* @defgroup GPIO_Registers_Setting_definition GPIO Registers setting definition
* @{
*/
#define GPIO_PSPCR_RST_VALUE (0x001FU)
#define GPIO_PCCR_RST_VALUE (0x4000U)
#define GPIO_PINAER_RST_VALUE (0x0000U)
#define GPIO_PIN_NUM_MAX (16U)
#define GPIO_PORT_OFFSET (0x40UL)
#define GPIO_PIN_OFFSET (0x04UL)
#define GPIO_REG_OFFSET (0x10UL)
#define GPIO_REG_TYPE uint16_t
#define GPIO_PIDR_BASE ((uint32_t)(&CM_GPIO->PIDRA))
#define GPIO_PODR_BASE ((uint32_t)(&CM_GPIO->PODRA))
#define GPIO_POSR_BASE ((uint32_t)(&CM_GPIO->POSRA))
#define GPIO_PORR_BASE ((uint32_t)(&CM_GPIO->PORRA))
#define GPIO_POTR_BASE ((uint32_t)(&CM_GPIO->POTRA))
#define GPIO_POER_BASE ((uint32_t)(&CM_GPIO->POERA))
#define GPIO_PCR_BASE ((uint32_t)(&CM_GPIO->PCRA0))
#define GPIO_PFSR_BASE ((uint32_t)(&CM_GPIO->PFSRA0))
#define PIDR_REG(x) (*(__IO GPIO_REG_TYPE *)(GPIO_PIDR_BASE + GPIO_REG_OFFSET * (x)))
#define PODR_REG(x) (*(__IO GPIO_REG_TYPE *)(GPIO_PODR_BASE + GPIO_REG_OFFSET * (x)))
#define POSR_REG(x) (*(__IO GPIO_REG_TYPE *)(GPIO_POSR_BASE + GPIO_REG_OFFSET * (x)))
#define PORR_REG(x) (*(__IO GPIO_REG_TYPE *)(GPIO_PORR_BASE + GPIO_REG_OFFSET * (x)))
#define POTR_REG(x) (*(__IO GPIO_REG_TYPE *)(GPIO_POTR_BASE + GPIO_REG_OFFSET * (x)))
#define POER_REG(x) (*(__IO GPIO_REG_TYPE *)(GPIO_POER_BASE + GPIO_REG_OFFSET * (x)))
#define PCR_REG(x, y) (*(__IO uint16_t *)(GPIO_PCR_BASE + (uint32_t)((x) * GPIO_PORT_OFFSET) + (y) * GPIO_PIN_OFFSET))
#define PFSR_REG(x, y) (*(__IO uint16_t *)(GPIO_PFSR_BASE + (uint32_t)((x) * GPIO_PORT_OFFSET) + (y) * GPIO_PIN_OFFSET))
/**
* @}
*/
/**
* @defgroup GPIO_Check_Parameters_Validity GPIO Check Parameters Validity
* @{
*/
/*! Parameter validity check for pin state. */
#define IS_GPIO_PIN_STATE(state) \
( ((state) == PIN_STAT_RST) || \
((state) == PIN_STAT_SET))
/*! Parameter validity check for pin direction. */
#define IS_GPIO_DIR(dir) \
( ((dir) == PIN_DIR_IN) || \
((dir) == PIN_DIR_OUT))
/*! Parameter validity check for pin output type. */
#define IS_GPIO_OUT_TYPE(type) \
( ((type) == PIN_OUT_TYPE_CMOS) || \
((type) == PIN_OUT_TYPE_NMOS))
/*! Parameter validity check for pin driver capacity. */
#define IS_GPIO_PIN_DRV(drv) \
( ((drv) == PIN_LOW_DRV) || \
((drv) == PIN_MID_DRV) || \
((drv) == PIN_HIGH_DRV))
/*! Parameter validity check for pin attribute. */
#define IS_GPIO_ATTR(attr) \
( ((attr) == PIN_ATTR_DIGITAL) || \
((attr) == PIN_ATTR_ANALOG))
/*! Parameter validity check for pin latch function. */
#define IS_GPIO_LATCH(latch) \
( ((latch) == PIN_LATCH_OFF) || \
((latch) == PIN_LATCH_ON))
/*! Parameter validity check for internal pull-up resistor. */
#define IS_GPIO_PIN_PU(pu) \
( ((pu) == PIN_PU_OFF) || \
((pu) == PIN_PU_ON))
/*! Parameter validity check for pin state invert. */
#define IS_GPIO_PIN_INVERT(invert) \
( ((invert) == PIN_INVT_OFF) || \
((invert) == PIN_INVT_ON))
/*! Parameter validity check for external interrupt function. */
#define IS_GPIO_EXTINT(extint) \
( ((extint) == PIN_EXTINT_OFF) || \
((extint) == PIN_EXTINT_ON))
/*! Parameter validity check for pin number. */
#define IS_GPIO_PIN(pin) \
( ((pin) != 0U) && \
(((pin) & GPIO_PIN_ALL) != 0U))
/*! Parameter validity check for port source. */
#define IS_GPIO_PORT(port) \
( ((port) == GPIO_PORT_A) || \
((port) == GPIO_PORT_B) || \
((port) == GPIO_PORT_C) || \
((port) == GPIO_PORT_D) || \
((port) == GPIO_PORT_E) || \
((port) == GPIO_PORT_H))
/*! Parameter validity check for pin function. */
#define IS_GPIO_FUNC(func) \
( ((func) <= GPIO_FUNC_15) || \
(((func) >= GPIO_FUNC_32) && ((func) <= GPIO_FUNC_59)))
/*! Parameter validity check for debug pin definition. */
#define IS_GPIO_DEBUG_PORT(port) \
( ((port) != 0U) && \
(((port) | GPIO_PIN_DEBUG) == GPIO_PIN_DEBUG))
/*! Parameter validity check for pin read wait cycle. */
#define IS_GPIO_READ_WAIT(wait) \
( ((wait) == GPIO_RD_WAIT0) || \
((wait) == GPIO_RD_WAIT1) || \
((wait) == GPIO_RD_WAIT2) || \
((wait) == GPIO_RD_WAIT3))
/* Check GPIO register lock status. */
#define IS_GPIO_UNLOCK() (GPIO_PWPR_WE == (CM_GPIO->PWPR & GPIO_PWPR_WE))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/**
* @defgroup GPIO_Local_Variables GPIO Local Variables
* @{
*/
static const stc_gpio_port_pin_tbl_t m_astcGpioPortPinTbl[] = {
{GPIO_PORT_A, GPIO_PIN_A_ALL},
{GPIO_PORT_B, GPIO_PIN_B_ALL},
{GPIO_PORT_C, GPIO_PIN_C_ALL},
{GPIO_PORT_D, GPIO_PIN_D_ALL},
{GPIO_PORT_E, GPIO_PIN_E_ALL},
{GPIO_PORT_H, GPIO_PIN_H_ALL},
};
/**
* @}
*/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup GPIO_Global_Functions GPIO Global Functions
* @{
*/
/**
* @brief Initialize GPIO.
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16Pin: GPIO_PIN_x, x can be the suffix in @ref GPIO_Pins_Define for each product
* @param [in] pstcGpioInit: Pointer to a stc_gpio_init_t structure that
* contains configuration information.
* @retval int32_t:
* - LL_OK: GPIO initialize successful
* - LL_ERR_INVD_PARAM: NULL pointer
*/
int32_t GPIO_Init(uint8_t u8Port, uint16_t u16Pin, const stc_gpio_init_t *pstcGpioInit)
{
uint8_t u8PinPos;
uint16_t u16PCRVal;
uint16_t u16PCRMask;
int32_t i32Ret = LL_OK;
__IO uint16_t *PCRx;
/* Check if pointer is NULL */
if (NULL == pstcGpioInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_UNLOCK());
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_GPIO_PIN(u16Pin));
DDL_ASSERT(IS_GPIO_PIN_STATE(pstcGpioInit->u16PinState));
DDL_ASSERT(IS_GPIO_DIR(pstcGpioInit->u16PinDir));
DDL_ASSERT(IS_GPIO_OUT_TYPE(pstcGpioInit->u16PinOutputType));
DDL_ASSERT(IS_GPIO_PIN_DRV(pstcGpioInit->u16PinDrv));
DDL_ASSERT(IS_GPIO_LATCH(pstcGpioInit->u16Latch));
DDL_ASSERT(IS_GPIO_PIN_PU(pstcGpioInit->u16PullUp));
DDL_ASSERT(IS_GPIO_PIN_INVERT(pstcGpioInit->u16Invert));
DDL_ASSERT(IS_GPIO_EXTINT(pstcGpioInit->u16ExtInt));
DDL_ASSERT(IS_GPIO_ATTR(pstcGpioInit->u16PinAttr));
for (u8PinPos = 0U; u8PinPos < GPIO_PIN_NUM_MAX; u8PinPos++) {
if ((u16Pin & 1U) != 0U) {
u16PCRVal = pstcGpioInit->u16PinState | pstcGpioInit->u16PinDir | pstcGpioInit->u16PinOutputType | \
pstcGpioInit->u16PinDrv | pstcGpioInit->u16PullUp | pstcGpioInit->u16Invert | \
pstcGpioInit->u16ExtInt | pstcGpioInit->u16Latch;
u16PCRMask = GPIO_PCR_POUT | GPIO_PCR_POUTE | GPIO_PCR_NOD | \
GPIO_PCR_DRV | GPIO_PCR_PUU | GPIO_PCR_INVE | \
GPIO_PCR_INTE | GPIO_PCR_LTE ;
u16PCRVal |= pstcGpioInit->u16PinAttr;
u16PCRMask |= GPIO_PCR_DDIS;
PCRx = &PCR_REG(u8Port, u8PinPos);
MODIFY_REG16(*PCRx, u16PCRMask, u16PCRVal);
}
u16Pin >>= 1U;
if (0U == u16Pin) {
break;
}
}
}
return i32Ret;
}
/**
* @brief De-init GPIO register to default value
* @param None
* @retval None
*/
void GPIO_DeInit(void)
{
stc_gpio_init_t stcGpioInit;
uint8_t i;
DDL_ASSERT(IS_GPIO_UNLOCK());
(void)GPIO_StructInit(&stcGpioInit);
for (i = 0U; i < ARRAY_SZ(m_astcGpioPortPinTbl); i++) {
(void)GPIO_Init(m_astcGpioPortPinTbl[i].u8Port, m_astcGpioPortPinTbl[i].u16PinMask, &stcGpioInit);
}
/* GPIO global register reset */
WRITE_REG16(CM_GPIO->PSPCR, GPIO_PSPCR_RST_VALUE);
WRITE_REG16(CM_GPIO->PCCR, GPIO_PCCR_RST_VALUE);
WRITE_REG16(CM_GPIO->PINAER, GPIO_PINAER_RST_VALUE);
}
/**
* @brief Initialize GPIO config structure. Fill each pstcGpioInit with default value
* @param [in] pstcGpioInit: Pointer to a stc_gpio_init_t structure that
* contains configuration information.
* @retval int32_t:
* - LL_OK: GPIO structure initialize successful
* - LL_ERR_INVD_PARAM: NULL pointer
*/
int32_t GPIO_StructInit(stc_gpio_init_t *pstcGpioInit)
{
int32_t i32Ret = LL_OK;
/* Check if pointer is NULL */
if (NULL == pstcGpioInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Reset GPIO init structure parameters values */
pstcGpioInit->u16PinState = PIN_STAT_RST;
pstcGpioInit->u16PinDir = PIN_DIR_IN;
pstcGpioInit->u16PinDrv = PIN_LOW_DRV;
pstcGpioInit->u16PinAttr = PIN_ATTR_DIGITAL;
pstcGpioInit->u16Latch = PIN_LATCH_OFF;
pstcGpioInit->u16PullUp = PIN_PU_OFF;
pstcGpioInit->u16Invert = PIN_INVT_OFF;
pstcGpioInit->u16ExtInt = PIN_EXTINT_OFF;
pstcGpioInit->u16PinOutputType = PIN_OUT_TYPE_CMOS;
}
return i32Ret;
}
/**
* @brief GPIO debug port configure. Set debug pins to GPIO
* @param [in] u8DebugPort: @ref GPIO_DebugPin_Sel for each product
* @param [in] enNewState: An @ref en_functional_state_t enumeration value.
* @arg ENABLE: set to debug port (SWD/JTAG)
* @arg DISABLE: set to GPIO
* @retval None
*/
void GPIO_SetDebugPort(uint8_t u8DebugPort, en_functional_state_t enNewState)
{
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_DEBUG_PORT(u8DebugPort));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
DDL_ASSERT(IS_GPIO_UNLOCK());
if (ENABLE == enNewState) {
SET_REG16_BIT(CM_GPIO->PSPCR, ((uint16_t)u8DebugPort & GPIO_PSPCR_SPFE));
} else {
CLR_REG16_BIT(CM_GPIO->PSPCR, ((uint16_t)u8DebugPort & GPIO_PSPCR_SPFE));
}
}
/**
* @brief Set specified Port Pin function
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16Pin: GPIO_PIN_x, x can be the suffix in @ref GPIO_Pins_Define for each product
* @param [in] u16Func: GPIO_FUNC_x, x can be the suffix in @ref GPIO_Function_Sel for each product
* @retval None
*/
void GPIO_SetFunc(uint8_t u8Port, uint16_t u16Pin, uint16_t u16Func)
{
uint8_t u8PinPos;
__IO uint16_t *PFSRx;
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_GPIO_PIN(u16Pin));
DDL_ASSERT(IS_GPIO_FUNC(u16Func));
DDL_ASSERT(IS_GPIO_UNLOCK());
for (u8PinPos = 0U; u8PinPos < GPIO_PIN_NUM_MAX; u8PinPos++) {
if ((u16Pin & 1U) != 0U) {
PFSRx = &PFSR_REG(u8Port, u8PinPos);
MODIFY_REG16(*PFSRx, GPIO_PFSR_FSEL, u16Func);
}
u16Pin >>= 1U;
if (0U == u16Pin) {
break;
}
}
}
/**
* @brief GPIO pin sub-function ENABLE.
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16Pin: GPIO_PIN_x, x can be the suffix in @ref GPIO_Pins_Define for each product
* @param [in] enNewState: An @ref en_functional_state_t enumeration value.
* @retval None
*/
void GPIO_SubFuncCmd(uint8_t u8Port, uint16_t u16Pin, en_functional_state_t enNewState)
{
uint8_t u8PinPos;
__IO uint16_t *PFSRx;
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_GPIO_PIN(u16Pin));
DDL_ASSERT(IS_GPIO_UNLOCK());
for (u8PinPos = 0U; u8PinPos < GPIO_PIN_NUM_MAX; u8PinPos++) {
if ((u16Pin & 1U) != 0U) {
PFSRx = &PFSR_REG(u8Port, u8PinPos);
if (ENABLE == enNewState) {
SET_REG16_BIT(*PFSRx, PIN_SUBFUNC_ENABLE);
} else {
CLR_REG16_BIT(*PFSRx, PIN_SUBFUNC_ENABLE);
}
}
u16Pin >>= 1U;
if (0U == u16Pin) {
break;
}
}
}
/**
* @brief Set the sub-function, it's a global configuration
* @param [in] u8Func: GPIO_FUNC_x, x can be the suffix in @ref GPIO_Function_Sel for each product
* @retval None
*/
void GPIO_SetSubFunc(uint8_t u8Func)
{
DDL_ASSERT(IS_GPIO_FUNC(u8Func));
DDL_ASSERT(IS_GPIO_UNLOCK());
MODIFY_REG16(CM_GPIO->PCCR, GPIO_PCCR_BFSEL, u8Func);
}
/**
* @brief GPIO output ENABLE.
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16Pin: GPIO_PIN_x, x can be the suffix in @ref GPIO_Pins_Define for each product
* @param [in] enNewState: An @ref en_functional_state_t enumeration value.
* @retval None
*/
void GPIO_OutputCmd(uint8_t u8Port, uint16_t u16Pin, en_functional_state_t enNewState)
{
__IO GPIO_REG_TYPE *POERx;
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_GPIO_PIN(u16Pin));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
POERx = &POER_REG(u8Port);
if (ENABLE == enNewState) {
SET_REG_BIT(*POERx, (GPIO_REG_TYPE)u16Pin);
} else {
CLR_REG_BIT(*POERx, (GPIO_REG_TYPE)u16Pin);
}
}
/**
* @brief GPIO read wait cycle configure.
* @param [in] u16ReadWait: @ref GPIO_ReadCycle_Sel for each product
* @retval None
*/
void GPIO_SetReadWaitCycle(uint16_t u16ReadWait)
{
DDL_ASSERT(IS_GPIO_READ_WAIT(u16ReadWait));
DDL_ASSERT(IS_GPIO_UNLOCK());
MODIFY_REG16(CM_GPIO->PCCR, GPIO_PCCR_RDWT, u16ReadWait);
}
/**
* @brief GPIO input MOS always ON configure.
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] enNewState: An @ref en_functional_state_t enumeration value.
* @arg ENABLE: set input MOS always ON
* @arg DISABLE: set input MOS turns on while read operation
* @retval None
*/
void GPIO_InputMOSCmd(uint8_t u8Port, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
DDL_ASSERT(IS_GPIO_UNLOCK());
if (ENABLE == enNewState) {
SET_REG16_BIT(CM_GPIO->PINAER, (1UL << u8Port));
} else {
CLR_REG16_BIT(CM_GPIO->PINAER, (1UL << u8Port));
}
}
/**
* @brief Read specified GPIO input data port pins
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16Pin: GPIO_PIN_x, x can be the suffix in @ref GPIO_Pins_Define for each product
* @retval Specified GPIO port pin input value
*/
en_pin_state_t GPIO_ReadInputPins(uint8_t u8Port, uint16_t u16Pin)
{
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_GPIO_PIN(u16Pin));
return ((READ_REG(PIDR_REG(u8Port)) & (u16Pin)) != 0U) ? PIN_SET : PIN_RESET;
}
/**
* @brief Read specified GPIO input data port
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @retval Specified GPIO port input value
*/
uint16_t GPIO_ReadInputPort(uint8_t u8Port)
{
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
return READ_REG(PIDR_REG(u8Port));
}
/**
* @brief Read specified GPIO output data port pins
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16Pin: GPIO_PIN_x, x can be the suffix in @ref GPIO_Pins_Define for each product
* @retval Specified GPIO port pin output value
*/
en_pin_state_t GPIO_ReadOutputPins(uint8_t u8Port, uint16_t u16Pin)
{
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_GPIO_PIN(u16Pin));
return ((READ_REG(PODR_REG(u8Port)) & (u16Pin)) != 0U) ? PIN_SET : PIN_RESET;
}
/**
* @brief Read specified GPIO output data port
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @retval Specified GPIO port output value
*/
uint16_t GPIO_ReadOutputPort(uint8_t u8Port)
{
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
return READ_REG(PODR_REG(u8Port));
}
/**
* @brief Set specified GPIO output data port pins
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16Pin: GPIO_PIN_x, x can be the suffix in @ref GPIO_Pins_Define for each product
* @retval None
*/
void GPIO_SetPins(uint8_t u8Port, uint16_t u16Pin)
{
__IO GPIO_REG_TYPE *POSRx;
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_GPIO_PIN(u16Pin));
POSRx = &POSR_REG(u8Port);
SET_REG_BIT(*POSRx, (GPIO_REG_TYPE)u16Pin);
}
/**
* @brief Reset specified GPIO output data port pins
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16Pin: GPIO_PIN_x, x can be the suffix in @ref GPIO_Pins_Define for each product
* @retval None
*/
void GPIO_ResetPins(uint8_t u8Port, uint16_t u16Pin)
{
__IO GPIO_REG_TYPE *PORRx;
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_GPIO_PIN(u16Pin));
PORRx = &PORR_REG(u8Port);
SET_REG_BIT(*PORRx, (GPIO_REG_TYPE)u16Pin);
}
/**
* @brief Write specified GPIO data port
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16PortVal: Pin output value
* @retval None
*/
void GPIO_WritePort(uint8_t u8Port, uint16_t u16PortVal)
{
__IO GPIO_REG_TYPE *PODRx;
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
PODRx = &PODR_REG(u8Port);
WRITE_REG(*PODRx, (GPIO_REG_TYPE)u16PortVal);
}
/**
* @brief Toggle specified GPIO output data port pin
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16Pin: GPIO_PIN_x, x can be the suffix in @ref GPIO_Pins_Define for each product
* @retval None
*/
void GPIO_TogglePins(uint8_t u8Port, uint16_t u16Pin)
{
__IO GPIO_REG_TYPE *POTRx;
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_GPIO_PIN(u16Pin));
POTRx = &POTR_REG(u8Port);
SET_REG_BIT(*POTRx, (GPIO_REG_TYPE)u16Pin);
}
/**
* @brief GPIO Analog command.
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16Pin: GPIO_PIN_x, x can be the suffix in @ref GPIO_Pins_Define for each product
* @param [in] enNewState: An @ref en_functional_state_t enumeration value.
* @retval None
*/
void GPIO_AnalogCmd(uint8_t u8Port, uint16_t u16Pin, en_functional_state_t enNewState)
{
__IO uint16_t *PCRx;
uint8_t u8PinPos;
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_GPIO_PIN(u16Pin));
for (u8PinPos = 0U; u8PinPos < GPIO_PIN_NUM_MAX; u8PinPos++) {
if ((u16Pin & 1U) != 0U) {
PCRx = &PCR_REG(u8Port, u8PinPos);
if (ENABLE == enNewState) {
SET_REG16_BIT(*PCRx, GPIO_PCR_DDIS);
} else {
CLR_REG16_BIT(*PCRx, GPIO_PCR_DDIS);
}
}
u16Pin >>= 1U;
if (0U == u16Pin) {
break;
}
}
}
/**
* @brief GPIO external interrupt command.
* @param [in] u8Port: GPIO_PORT_x, x can be the suffix in @ref GPIO_Port_Source for each product
* @param [in] u16Pin: GPIO_PIN_x, x can be the suffix in @ref GPIO_Pins_Define for each product
* @param [in] enNewState: An @ref en_functional_state_t enumeration value.
* @retval None
*/
void GPIO_ExtIntCmd(uint8_t u8Port, uint16_t u16Pin, en_functional_state_t enNewState)
{
__IO uint16_t *PCRx;
uint8_t u8PinPos;
/* Parameter validity checking */
DDL_ASSERT(IS_GPIO_PORT(u8Port));
DDL_ASSERT(IS_GPIO_PIN(u16Pin));
for (u8PinPos = 0U; u8PinPos < GPIO_PIN_NUM_MAX; u8PinPos++) {
if ((u16Pin & 1U) != 0U) {
PCRx = &PCR_REG(u8Port, u8PinPos);
if (ENABLE == enNewState) {
SET_REG16_BIT(*PCRx, GPIO_PCR_INTE);
} else {
CLR_REG16_BIT(*PCRx, GPIO_PCR_INTE);
}
}
u16Pin >>= 1U;
if (0U == u16Pin) {
break;
}
}
}
/**
* @}
*/
#endif /* LL_GPIO_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+336
View File
@@ -0,0 +1,336 @@
/**
*******************************************************************************
* @file hc32_ll_hash.c
* @brief This file provides firmware functions to manage the HASH.
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2023-06-30 CDT Add HASH_DeInit function
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_hash.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_HASH HASH
* @brief HASH Driver Library
* @{
*/
#if (LL_HASH_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup HASH_Local_Macros HASH Local Macros
* @{
*/
/**
* @defgroup HASH_Miscellaneous_Macros HASH Miscellaneous Macros
* @{
*/
#define HASH_GROUP_SIZE (64U)
#define HASH_GROUP_SIZE_WORD (HASH_GROUP_SIZE / 4U)
#define HASH_LAST_GROUP_SIZE_MAX (56U)
#define HASH_TIMEOUT (6000U)
#define HASH_MSG_DIGEST_SIZE_WORD (8U)
/**
* @}
*/
/**
* @defgroup HASH_Action HASH Action
* @{
*/
#define HASH_ACTION_START (HASH_CR_START)
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup HASH_Local_Functions HASH Local Functions
* @{
*/
/**
* @brief Writes the input buffer in data register.
* @param [in] pu8Data The buffer for source data
* @retval None
*/
static void HASH_WriteData(const uint8_t *pu8Data)
{
uint8_t i;
__IO uint32_t *regDR = &CM_HASH->DR15;
const uint32_t *pu32Data = (const uint32_t *)((uint32_t)pu8Data);
for (i = 0U; i < HASH_GROUP_SIZE_WORD; i++) {
regDR[i] = __REV(pu32Data[i]);
}
}
/**
* @brief Memory copy.
* @param [in] pu8Dest Pointer to a destination address.
* @param [in] pu8Src Pointer to a source address.
* @param [in] u32Size Data size.
* @retval None
*/
static void HASH_MemCopy(uint8_t *pu8Dest, const uint8_t *pu8Src, uint32_t u32Size)
{
uint32_t i = 0UL;
while (i < u32Size) {
pu8Dest[i] = pu8Src[i];
i++;
}
}
/**
* @brief Memory set.
* @param [in] pu8Mem Pointer to an address.
* @param [in] u8Value Data value.
* @param [in] u32Size Data size.
* @retval None
*/
static void HASH_MemSet(uint8_t *pu8Mem, uint8_t u8Value, uint32_t u32Size)
{
uint32_t i = 0UL;
while (i < u32Size) {
pu8Mem[i] = u8Value;
i++;
}
}
/**
* @brief Wait for the HASH to stop
* @param [in] u32Action HASH action. This parameter can be a value of @ref HASH_Action.
* @retval int32_t:
* - LL_OK: No errors occurred
* - LL_ERR_TIMEOUT: Works timeout
*/
static int32_t HASH_Wait(uint32_t u32Action)
{
int32_t i32Ret = LL_OK;
__IO uint32_t u32TimeCount = 0UL;
/* Wait for the HASH to stop */
while (READ_REG32_BIT(CM_HASH->CR, u32Action) != 0UL) {
if (u32TimeCount++ > HASH_TIMEOUT) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
}
return i32Ret;
}
/**
* @brief HASH Filling data
* @param [in] pu8Data The source data buffer
* @param [in] u32DataSize Length of the input buffer in bytes
* @retval int32_t:
* - LL_OK: No errors occurred
* - LL_ERR_TIMEOUT: Works timeout
*/
static int32_t HASH_DoCalc(const uint8_t *pu8Data, uint32_t u32DataSize)
{
uint8_t u8FillBuffer[HASH_GROUP_SIZE];
uint32_t u32BitLenHigh;
uint32_t u32BitLenLow;
uint32_t u32Index = 0U;
uint8_t u8FirstGroup = 1U;
uint8_t u8HashEnd = 0U;
uint8_t u8DataEndMark = 0U;
int32_t i32Ret;
u32BitLenHigh = (u32DataSize >> 29U) & 0x7U;
u32BitLenLow = (u32DataSize << 3U);
/* Stop hash calculating. */
i32Ret = HASH_Wait(HASH_ACTION_START);
while ((i32Ret == LL_OK) && (u8HashEnd == 0U)) {
if (u32DataSize >= HASH_GROUP_SIZE) {
HASH_WriteData(&pu8Data[u32Index]);
u32DataSize -= HASH_GROUP_SIZE;
u32Index += HASH_GROUP_SIZE;
} else if (u32DataSize >= HASH_LAST_GROUP_SIZE_MAX) {
HASH_MemSet(u8FillBuffer, 0, HASH_GROUP_SIZE);
HASH_MemCopy(u8FillBuffer, &pu8Data[u32Index], u32DataSize);
u8FillBuffer[u32DataSize] = 0x80U;
u8DataEndMark = 1U;
HASH_WriteData(u8FillBuffer);
u32DataSize = 0U;
} else {
u8HashEnd = 1U;
}
if (u8HashEnd != 0U) {
HASH_MemSet(u8FillBuffer, 0, HASH_GROUP_SIZE);
if (u32DataSize > 0U) {
HASH_MemCopy(u8FillBuffer, &pu8Data[u32Index], u32DataSize);
}
if (u8DataEndMark == 0U) {
u8FillBuffer[u32DataSize] = 0x80U;
}
u8FillBuffer[63U] = (uint8_t)(u32BitLenLow);
u8FillBuffer[62U] = (uint8_t)(u32BitLenLow >> 8U);
u8FillBuffer[61U] = (uint8_t)(u32BitLenLow >> 16U);
u8FillBuffer[60U] = (uint8_t)(u32BitLenLow >> 24U);
u8FillBuffer[59U] = (uint8_t)(u32BitLenHigh);
u8FillBuffer[58U] = (uint8_t)(u32BitLenHigh >> 8U);
u8FillBuffer[57U] = (uint8_t)(u32BitLenHigh >> 16U);
u8FillBuffer[56U] = (uint8_t)(u32BitLenHigh >> 24U);
HASH_WriteData(u8FillBuffer);
}
/* First group and last group check */
/* check if first group */
if (u8FirstGroup != 0U) {
u8FirstGroup = 0U;
/* Set first group. */
WRITE_REG32(bCM_HASH->CR_b.FST_GRP, 1U);
} else {
/* Set continuous group. */
WRITE_REG32(bCM_HASH->CR_b.FST_GRP, 0U);
}
/* Start hash calculating. */
WRITE_REG32(bCM_HASH->CR_b.START, 1U);
i32Ret = HASH_Wait(HASH_ACTION_START);
}
/* Stop hash calculating. */
WRITE_REG32(bCM_HASH->CR_b.START, 0U);
return i32Ret;
}
/**
* @brief Read message digest.
* @param [out] pu8MsgDigest Buffer for message digest.
* @retval None
*/
static void HASH_ReadMsgDigest(uint8_t *pu8MsgDigest)
{
uint8_t i;
__IO uint32_t *regHR = &CM_HASH->HR7;
uint32_t *pu32MsgDigest = (uint32_t *)((uint32_t)pu8MsgDigest);
for (i = 0U; i < HASH_MSG_DIGEST_SIZE_WORD; i++) {
pu32MsgDigest[i] = __REV(regHR[i]);
}
}
/**
* @}
*/
/**
* @defgroup HASH_Global_Functions HASH Global Functions
* @{
*/
/**
* @brief De-initializes HASH.
* @param None
* @retval int32_t:
* - LL_OK: No error occurred.
*/
int32_t HASH_DeInit(void)
{
uint8_t i;
__IO uint32_t *regDR = &CM_HASH->DR15;
WRITE_REG32(CM_HASH->CR, 0UL);
for (i = 0U; i < HASH_GROUP_SIZE_WORD; i++) {
WRITE_REG32(regDR[i], 0UL);
}
return LL_OK;
}
/**
* @brief HASH calculate.
* @param [in] pu8SrcData Pointer to the source data buffer.
* @param [in] u32SrcDataSize Length of the source data buffer in bytes.
* @param [out] pu8MsgDigest Buffer of the digest. The size must be 32 bytes.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_INVD_PARAM: Parameter error.
* - LL_ERR_TIMEOUT: Works timeout.
*/
int32_t HASH_Calculate(const uint8_t *pu8SrcData, uint32_t u32SrcDataSize, uint8_t *pu8MsgDigest)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if ((pu8SrcData != NULL) && (u32SrcDataSize != 0UL) && (pu8MsgDigest != NULL)) {
/* Set HASH mode */
i32Ret = HASH_DoCalc(pu8SrcData, u32SrcDataSize);
if (i32Ret == LL_OK) {
/* Get the message digest result */
HASH_ReadMsgDigest(pu8MsgDigest);
}
}
return i32Ret;
}
/**
* @}
*/
#endif /* LL_HASH_ENABLE */
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+118
View File
@@ -0,0 +1,118 @@
/**
*******************************************************************************
* @file hc32_ll_icg.c
* @brief This file provides firmware functions to manage the Initial
* Configuration(ICG).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_icg.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_ICG ICG
* @brief Initial Configuration Driver Library
* @{
*/
#if (LL_ICG_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup ICG_Local_Macros ICG Local Macros
* @{
*/
/**
* @brief ICG Start Address
*/
#define ICG_START_ADDR 0x400
#define ICG_START_ADDR_AC6 ".ARM.__at_0x400"
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/**
* @brief ICG parameters configuration
*/
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
const uint32_t u32ICGValue[] __attribute__((section(ICG_START_ADDR_AC6))) =
#elif defined (__GNUC__) && !defined (__CC_ARM)
const uint32_t u32ICGValue[] __attribute__((section(".icg_sec"))) =
#elif defined (__CC_ARM)
const uint32_t u32ICGValue[] __attribute__((at(ICG_START_ADDR))) =
#elif defined (__ICCARM__)
#pragma location = ICG_START_ADDR
__root static const uint32_t u32ICGValue[] =
#else
#error "unsupported compiler!!"
#endif
{
/* ICG 0~1 */
ICG_REG_CFG0_CONST,
ICG_REG_CFG1_CONST,
/* Reserved 2~7 */
ICG_REG_RESV_CONST,
ICG_REG_RESV_CONST,
ICG_REG_RESV_CONST,
ICG_REG_RESV_CONST,
ICG_REG_RESV_CONST,
ICG_REG_RESV_CONST,
};
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
#endif /* LL_ICG_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
File diff suppressed because it is too large Load Diff
+242
View File
@@ -0,0 +1,242 @@
/**
*******************************************************************************
* @file hc32_ll_keyscan.c
* @brief This file provides firmware functions to manage the matrix keyscan
* function (KEYSCAN).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2023-06-30 CDT Add function KEYSCAN_DeInit
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_keyscan.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_KEYSCAN KEYSCAN
* @brief Matrix keyscan Driver Library
* @{
*/
#if (LL_KEYSCAN_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup KEYSCAN_Local_Macros KEYSCAN Local Macros
* @{
*/
/**
* @defgroup KEYSCAN_Check_Parameters_Validity KEYSCAN Check Parameters Validity
* @{
*/
/*! Parameter valid check for KEYSCAN HiZ state cycles. */
#define IS_KEYSCAN_HIZ_CYCLE(clc) \
( ((clc) == KEYSCAN_HIZ_CYCLE_4) || \
((clc) == KEYSCAN_HIZ_CYCLE_8) || \
((clc) == KEYSCAN_HIZ_CYCLE_16) || \
((clc) == KEYSCAN_HIZ_CYCLE_32) || \
((clc) == KEYSCAN_HIZ_CYCLE_64) || \
((clc) == KEYSCAN_HIZ_CYCLE_256) || \
((clc) == KEYSCAN_HIZ_CYCLE_512) || \
((clc) == KEYSCAN_HIZ_CYCLE_1024))
/*! Parameter valid check for KEYSCAN low level output cycles. */
#define IS_KEYSCAN_LOW_CYCLE(clc) \
( ((clc) == KEYSCAN_LOW_CYCLE_4) || \
((clc) == KEYSCAN_LOW_CYCLE_8) || \
((clc) == KEYSCAN_LOW_CYCLE_16) || \
((clc) == KEYSCAN_LOW_CYCLE_32) || \
((clc) == KEYSCAN_LOW_CYCLE_64) || \
((clc) == KEYSCAN_LOW_CYCLE_128) || \
((clc) == KEYSCAN_LOW_CYCLE_256) || \
((clc) == KEYSCAN_LOW_CYCLE_512) || \
((clc) == KEYSCAN_LOW_CYCLE_1K) || \
((clc) == KEYSCAN_LOW_CYCLE_2K) || \
((clc) == KEYSCAN_LOW_CYCLE_4K) || \
((clc) == KEYSCAN_LOW_CYCLE_8K) || \
((clc) == KEYSCAN_LOW_CYCLE_16K) || \
((clc) == KEYSCAN_LOW_CYCLE_32K) || \
((clc) == KEYSCAN_LOW_CYCLE_64K) || \
((clc) == KEYSCAN_LOW_CYCLE_128K) || \
((clc) == KEYSCAN_LOW_CYCLE_256K) || \
((clc) == KEYSCAN_LOW_CYCLE_512K) || \
((clc) == KEYSCAN_LOW_CYCLE_1M) || \
((clc) == KEYSCAN_LOW_CYCLE_2M) || \
((clc) == KEYSCAN_LOW_CYCLE_4M) || \
((clc) == KEYSCAN_LOW_CYCLE_8M) || \
((clc) == KEYSCAN_LOW_CYCLE_16M))
/*! Parameter valid check for KEYSCAN scan clock. */
#define IS_KEYSCAN_CLK(clk) \
( ((clk) == KEYSCAN_CLK_HCLK) || \
((clk) == KEYSCAN_CLK_LRC) || \
((clk) == KEYSCAN_CLK_XTAL32))
/*! Parameter valid check for KEYSCAN keyout pins. */
#define IS_KEYSCAN_OUT(out) \
( ((out) == KEYSCAN_OUT_0T1) || \
((out) == KEYSCAN_OUT_0T2) || \
((out) == KEYSCAN_OUT_0T3) || \
((out) == KEYSCAN_OUT_0T4) || \
((out) == KEYSCAN_OUT_0T5) || \
((out) == KEYSCAN_OUT_0T6) || \
((out) == KEYSCAN_OUT_0T7))
/*! Parameter valid check for KEYSCAN keyin(EIRQ) pins. */
#define IS_KEYSCAN_IN(in) \
( ((in) != 0x00U) && \
(((in) | KEYSCAN_IN_ALL) == KEYSCAN_IN_ALL))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup KEYSCAN_Global_Functions KEYSCAN Global Functions
* @{
*/
/**
* @brief KEYSCAN function config.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void KEYSCAN_Cmd(en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
WRITE_REG32(CM_KEYSCAN->SER, enNewState);
}
/**
* @brief Initialize KEYSCAN config structure. Fill each pstcKeyscanInit with default value
* @param [in] pstcKeyscanInit Pointer to a stc_keyscan_init_t structure that
* contains configuration information.
* @retval int32_t:
* - LL_OK: KEYSCAN structure initialize successful
* - LL_ERR_INVD_PARAM: NULL pointer
*/
int32_t KEYSCAN_StructInit(stc_keyscan_init_t *pstcKeyscanInit)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcKeyscanInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
pstcKeyscanInit->u32HizCycle = KEYSCAN_HIZ_CYCLE_4;
pstcKeyscanInit->u32LowCycle = KEYSCAN_LOW_CYCLE_4;
pstcKeyscanInit->u32KeyClock = KEYSCAN_CLK_HCLK;
pstcKeyscanInit->u32KeyOut = KEYSCAN_OUT_0T1;
pstcKeyscanInit->u32KeyIn = KEYSCAN_IN_0;
}
return i32Ret;
}
/**
* @brief KEYSCAN initialize.
* @param [in] pstcKeyscanInit KEYSCAN config structure.
* @arg u32HizCycle Hiz state keep cycles during low level output.
* @arg u32LowCycle Low level output cycles.
* @arg u32KeyClock Scan clock.
* @arg u32KeyOut KEYOUT selection.
* @arg u32KeyIn KEYIN(EIRQ) selection.
* @retval int32_t:
* - LL_OK: KEYSCAN function initialize successful
* - LL_ERR_INVD_PARAM: NULL pointer
*/
int32_t KEYSCAN_Init(const stc_keyscan_init_t *pstcKeyscanInit)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcKeyscanInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
DDL_ASSERT(IS_KEYSCAN_HIZ_CYCLE(pstcKeyscanInit->u32HizCycle));
DDL_ASSERT(IS_KEYSCAN_LOW_CYCLE(pstcKeyscanInit->u32LowCycle));
DDL_ASSERT(IS_KEYSCAN_CLK(pstcKeyscanInit->u32KeyClock));
DDL_ASSERT(IS_KEYSCAN_OUT(pstcKeyscanInit->u32KeyOut));
DDL_ASSERT(IS_KEYSCAN_IN(pstcKeyscanInit->u32KeyIn));
WRITE_REG32(CM_KEYSCAN->SCR, \
(pstcKeyscanInit->u32HizCycle | pstcKeyscanInit->u32LowCycle | \
pstcKeyscanInit->u32KeyClock | pstcKeyscanInit->u32KeyOut | \
pstcKeyscanInit->u32KeyIn));
}
return i32Ret;
}
/**
* @brief De-initialize the KEYSCAN.
* @param None
* @retval int32_t:
* - LL_OK: De-Initialize success.
*/
int32_t KEYSCAN_DeInit(void)
{
int32_t i32Ret = LL_OK;
WRITE_REG32(CM_KEYSCAN->SER, 0UL);
WRITE_REG32(CM_KEYSCAN->SCR, 0UL);
return i32Ret;
}
/**
* @}
*/
#endif /* LL_KEYSCAN_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+893
View File
@@ -0,0 +1,893 @@
/**
*******************************************************************************
* @file hc32_ll_mpu.c
* @brief This file provides firmware functions to manage the Memory Protection
* Unit(MPU).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2023-09-30 CDT Modify typo
Optimize MPU_ClearStatus function
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_mpu.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_MPU MPU
* @brief Memory Protection Unit Driver Library
* @{
*/
#if (LL_MPU_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup MPU_Local_Macros MPU Local Macros
* @{
*/
/* Number of MPU region */
#define MPU_REGION_MAX_NUM (16UL)
/* Number of MPU unit */
#define MPU_UNIT_MAX_NUM (3UL)
/* MPU Register Combination Mask */
#define MPU_UNIT_CONFIG_MASK (MPU_CR_SMPU2BRP | MPU_CR_SMPU2BWP | MPU_CR_SMPU2ACT | \
MPU_CR_SMPU1BRP | MPU_CR_SMPU1BWP | MPU_CR_SMPU1ACT | \
MPU_CR_FMPUBRP | MPU_CR_FMPUBWP | MPU_CR_FMPUACT)
/* DMA units have 16 regions */
#define MPU_16REGION_UNIT (MPU_UNIT_DMA1 | MPU_UNIT_DMA2)
/* Get the specified register address of the MPU Intrusion Control */
#define MPU_RGD_ADDR(__NUM__) (__IO uint32_t *)((uint32_t)(&(CM_MPU->RGD0)) + ((uint32_t)(__NUM__) << 2U))
#define MPU_RGCR_ADDR(__NUM__) (__IO uint32_t *)((uint32_t)(&(CM_MPU->RGCR0)) + ((uint32_t)(__NUM__) << 2U))
/**
* @defgroup MPU_Check_Parameters_Validity MPU Check Parameters Validity
* @{
*/
#define IS_MPU_UNIT(x) \
( ((x) != 0UL) && \
(((x) | MPU_UNIT_ALL) == MPU_UNIT_ALL))
#define IS_MPU_REGION(x) ((x) <= MPU_REGION_NUM15)
#define IS_MPU_UNIT_REGION(unit, region) \
( (((unit) | MPU_16REGION_UNIT) == MPU_16REGION_UNIT) || \
((region) <= MPU_REGION_NUM7))
#define IS_MPU_BACKGROUND_WR(x) \
( ((x) == MPU_BACKGROUND_WR_DISABLE) || \
((x) == MPU_BACKGROUND_WR_ENABLE))
#define IS_MPU_BACKGROUND_RD(x) \
( ((x) == MPU_BACKGROUND_RD_DISABLE) || \
((x) == MPU_BACKGROUND_RD_ENABLE))
#define IS_MPU_EXP_TYPE(x) \
( ((x) == MPU_EXP_TYPE_NONE) || \
((x) == MPU_EXP_TYPE_BUS_ERR) || \
((x) == MPU_EXP_TYPE_NMI) || \
((x) == MPU_EXP_TYPE_RST))
#define IS_MPU_REGION_WR(x) \
( ((x) == MPU_REGION_WR_DISABLE) || \
((x) == MPU_REGION_WR_ENABLE))
#define IS_MPU_REGION_RD(x) \
( ((x) == MPU_REGION_RD_DISABLE) || \
((x) == MPU_REGION_RD_ENABLE))
#define IS_MPU_REGION_SIZE(x) \
( ((x) >= MPU_REGION_SIZE_32BYTE) && \
((x) <= MPU_REGION_SIZE_4GBYTE))
#define IS_MPU_REGION_BASE_ADDER(addr, size) \
( ((addr) & ((uint32_t)(~((uint64_t)0xFFFFFFFFUL << ((size) + 1U))))) == 0UL)
#define IS_MPU_FLAG(x) \
( ((x) != 0UL) && \
(((x) | MPU_FLAG_ALL) == MPU_FLAG_ALL))
#define IS_MPU_IP_TYPE(x) \
( ((x) != 0UL) && \
(((x) | MPU_IP_ALL) == MPU_IP_ALL))
#define IS_MPU_IP_EXP_TYPE(x) \
( ((x) == MPU_IP_EXP_TYPE_NONE) || \
((x) == MPU_IP_EXP_TYPE_BUS_ERR))
#define IS_MPU_UNLOCK() ((CM_MPU->WP & MPU_WP_MPUWE) == MPU_WP_MPUWE)
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup MPU_Global_Functions MPU Global Functions
* @{
*/
/**
* @brief De-Initialize MPU.
* @param None
* @retval None
*/
void MPU_DeInit(void)
{
uint32_t i;
__IO uint32_t *RGD;
__IO uint32_t *RGE;
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
for (i = 0UL; i < MPU_REGION_MAX_NUM; i++) {
RGD = MPU_RGD_ADDR(i);
WRITE_REG32(*RGD, 0UL);
RGE = MPU_RGCR_ADDR(i);
WRITE_REG32(*RGE, 0UL);
}
WRITE_REG32(CM_MPU->ECLR, MPU_FLAG_ALL);
WRITE_REG32(CM_MPU->IPPR, 0UL);
WRITE_REG32(CM_MPU->CR, 0UL);
}
/**
* @brief Initialize MPU.
* @param [in] pstcMpuInit Pointer to a @ref stc_mpu_init_t structure
* @retval int32_t:
* - LL_OK: Initialize success
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t MPU_Init(const stc_mpu_init_t *pstcMpuInit)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcMpuInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_EXP_TYPE(pstcMpuInit->stcDma1.u32ExceptionType));
DDL_ASSERT(IS_MPU_BACKGROUND_WR(pstcMpuInit->stcDma1.u32BackgroundWrite));
DDL_ASSERT(IS_MPU_BACKGROUND_RD(pstcMpuInit->stcDma1.u32BackgroundRead));
DDL_ASSERT(IS_MPU_EXP_TYPE(pstcMpuInit->stcDma2.u32ExceptionType));
DDL_ASSERT(IS_MPU_BACKGROUND_WR(pstcMpuInit->stcDma2.u32BackgroundWrite));
DDL_ASSERT(IS_MPU_BACKGROUND_RD(pstcMpuInit->stcDma2.u32BackgroundRead));
DDL_ASSERT(IS_MPU_EXP_TYPE(pstcMpuInit->stcUsbFSDma.u32ExceptionType));
DDL_ASSERT(IS_MPU_BACKGROUND_WR(pstcMpuInit->stcUsbFSDma.u32BackgroundWrite));
DDL_ASSERT(IS_MPU_BACKGROUND_RD(pstcMpuInit->stcUsbFSDma.u32BackgroundRead));
MODIFY_REG32(CM_MPU->CR, MPU_UNIT_CONFIG_MASK,
(pstcMpuInit->stcDma2.u32ExceptionType | pstcMpuInit->stcDma2.u32BackgroundWrite |
pstcMpuInit->stcDma2.u32BackgroundRead) |
((pstcMpuInit->stcDma1.u32ExceptionType | pstcMpuInit->stcDma1.u32BackgroundWrite |
pstcMpuInit->stcDma1.u32BackgroundRead) << 8U) |
((pstcMpuInit->stcUsbFSDma.u32ExceptionType | pstcMpuInit->stcUsbFSDma.u32BackgroundWrite |
pstcMpuInit->stcUsbFSDma.u32BackgroundRead) << 16U));
}
return i32Ret;
}
/**
* @brief Fills each stc_mpu_init_t member with default value.
* @param [out] pstcMpuInit Pointer to a @ref stc_mpu_init_t structure
* @retval int32_t:
* - LL_OK: stc_mpu_init_t member initialize success
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t MPU_StructInit(stc_mpu_init_t *pstcMpuInit)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcMpuInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
pstcMpuInit->stcDma1.u32ExceptionType = MPU_EXP_TYPE_NONE;
pstcMpuInit->stcDma1.u32BackgroundWrite = MPU_BACKGROUND_WR_DISABLE;
pstcMpuInit->stcDma1.u32BackgroundRead = MPU_BACKGROUND_RD_DISABLE;
pstcMpuInit->stcDma2.u32ExceptionType = MPU_EXP_TYPE_NONE;
pstcMpuInit->stcDma2.u32BackgroundWrite = MPU_BACKGROUND_WR_DISABLE;
pstcMpuInit->stcDma2.u32BackgroundRead = MPU_BACKGROUND_RD_DISABLE;
pstcMpuInit->stcUsbFSDma.u32ExceptionType = MPU_EXP_TYPE_NONE;
pstcMpuInit->stcUsbFSDma.u32BackgroundWrite = MPU_BACKGROUND_WR_DISABLE;
pstcMpuInit->stcUsbFSDma.u32BackgroundRead = MPU_BACKGROUND_RD_DISABLE;
}
return i32Ret;
}
/**
* @brief Set the exception type of the unit.
* @param [in] u32Unit The type of MPU unit.
* This parameter can be one or any combination of the following values:
* @arg @ref MPU_Unit_Type
* @param [in] u32Type Exception type of MPU unit.
* This parameter can be one of the following values:
* @arg MPU_EXP_TYPE_NONE: The host unit access protection regions will be ignored
* @arg MPU_EXP_TYPE_BUS_ERR: The host unit access protection regions will be ignored and a bus error will be triggered
* @arg MPU_EXP_TYPE_NMI: The host unit access protection regions will be ignored and a NMI interrupt will be triggered
* @arg MPU_EXP_TYPE_RST: The host unit access protection regions will trigger the reset
* @retval None
*/
void MPU_SetExceptionType(uint32_t u32Unit, uint32_t u32Type)
{
uint32_t u32UnitPos = 0UL;
uint32_t u32Temp;
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_UNIT(u32Unit));
DDL_ASSERT(IS_MPU_EXP_TYPE(u32Type));
u32Temp = u32Unit;
while (0UL != u32Temp) {
if (0UL != (u32Temp & 0x1UL)) {
MODIFY_REG32(CM_MPU->CR, MPU_CR_SMPU2ACT << (u32UnitPos << 3U), u32Type << (u32UnitPos << 3U));
}
u32Temp >>= 1UL;
u32UnitPos++;
}
}
/**
* @brief Enable or disable the write of the unit for background space.
* @param [in] u32Unit The type of MPU unit.
* This parameter can be one or any combination of the following values:
* @arg @ref MPU_Unit_Type
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void MPU_BackgroundWriteCmd(uint32_t u32Unit, en_functional_state_t enNewState)
{
uint32_t u32UnitPos = 0UL;
uint32_t u32Temp;
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_UNIT(u32Unit));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
u32Temp = u32Unit;
while (0UL != u32Temp) {
if (0UL != (u32Temp & 0x1UL)) {
if (DISABLE != enNewState) {
CLR_REG32_BIT(CM_MPU->CR, MPU_CR_SMPU2BWP << (u32UnitPos << 3U));
} else {
SET_REG32_BIT(CM_MPU->CR, MPU_CR_SMPU2BWP << (u32UnitPos << 3U));
}
}
u32Temp >>= 1UL;
u32UnitPos++;
}
}
/**
* @brief Enable or disable the read of the unit for background space.
* @param [in] u32Unit The type of MPU unit.
* This parameter can be one or any combination of the following values:
* @arg @ref MPU_Unit_Type
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void MPU_BackgroundReadCmd(uint32_t u32Unit, en_functional_state_t enNewState)
{
uint32_t u32UnitPos = 0UL;
uint32_t u32Temp;
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_UNIT(u32Unit));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
u32Temp = u32Unit;
while (0UL != u32Temp) {
if (0UL != (u32Temp & 0x1UL)) {
if (DISABLE != enNewState) {
CLR_REG32_BIT(CM_MPU->CR, MPU_CR_SMPU2BRP << (u32UnitPos << 3U));
} else {
SET_REG32_BIT(CM_MPU->CR, MPU_CR_SMPU2BRP << (u32UnitPos << 3U));
}
}
u32Temp >>= 1UL;
u32UnitPos++;
}
}
/**
* @brief Enable or disable the access control of the unit.
* @param [in] u32Unit The type of MPU unit.
* This parameter can be one or any combination of the following values:
* @arg @ref MPU_Unit_Type
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void MPU_UnitCmd(uint32_t u32Unit, en_functional_state_t enNewState)
{
uint32_t u32UnitPos = 0UL;
uint32_t u32Temp;
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_UNIT(u32Unit));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
u32Temp = u32Unit;
while (0UL != u32Temp) {
if (0UL != (u32Temp & 0x1UL)) {
if (DISABLE != enNewState) {
SET_REG32_BIT(CM_MPU->CR, MPU_CR_SMPU2E << (u32UnitPos << 3U));
} else {
CLR_REG32_BIT(CM_MPU->CR, MPU_CR_SMPU2E << (u32UnitPos << 3U));
}
}
u32Temp >>= 1UL;
u32UnitPos++;
}
}
/**
* @brief Gets the status of MPU flag.
* @param [in] u32Flag The type of MPU flag.
* This parameter can be one or any combination of the following values:
* @arg @ref MPU_Flag
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t MPU_GetStatus(uint32_t u32Flag)
{
en_flag_status_t enFlagSta = RESET;
/* Check parameters */
DDL_ASSERT(IS_MPU_FLAG(u32Flag));
if (0UL != (READ_REG32_BIT(CM_MPU->SR, u32Flag))) {
enFlagSta = SET;
}
return enFlagSta;
}
/**
* @brief Clear the flag of MPU.
* @param [in] u32Flag The type of MPU flag.
* This parameter can be one or any combination of the following values:
* @arg @ref MPU_Flag
* @retval None
*/
void MPU_ClearStatus(uint32_t u32Flag)
{
/* Check parameters */
DDL_ASSERT(IS_MPU_FLAG(u32Flag));
WRITE_REG32(CM_MPU->ECLR, u32Flag);
}
/**
* @brief Initialize the region.
* @note 'MPU_REGION_NUM8' to 'MPU_REGION_NUM15' are only valid when the MPU unit is 'MPU_UNIT_DMA1' or 'MPU_UNIT_DMA2'.
* @note The effective bits of the 'u32BaseAddr' are related to the 'u32Size' of the region,
* and the low 'u32Size+1' bits are fixed at 0.
* @param [in] u32Num The number of the region.
* This parameter can be one of the following values:
* @arg MPU_REGION_NUM0: MPU region number 0
* @arg MPU_REGION_NUM1: MPU region number 1
* @arg MPU_REGION_NUM2: MPU region number 2
* @arg MPU_REGION_NUM3: MPU region number 3
* @arg MPU_REGION_NUM4: MPU region number 4
* @arg MPU_REGION_NUM5: MPU region number 5
* @arg MPU_REGION_NUM6: MPU region number 6
* @arg MPU_REGION_NUM7: MPU region number 7
* @arg MPU_REGION_NUM8: MPU region number 8
* @arg MPU_REGION_NUM9: MPU region number 9
* @arg MPU_REGION_NUM10: MPU region number 10
* @arg MPU_REGION_NUM11: MPU region number 11
* @arg MPU_REGION_NUM12: MPU region number 12
* @arg MPU_REGION_NUM13: MPU region number 13
* @arg MPU_REGION_NUM14: MPU region number 14
* @arg MPU_REGION_NUM15: MPU region number 15
* @param [in] pstcRegionInit Pointer to a @ref stc_mpu_region_init_t structure
* @retval int32_t:
* - LL_OK: Initialize success
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t MPU_RegionInit(uint32_t u32Num, const stc_mpu_region_init_t *pstcRegionInit)
{
int32_t i32Ret = LL_OK;
__IO uint32_t *RGD;
__IO uint32_t *RGWP;
uint32_t i;
uint32_t u32UnitNum = MPU_UNIT_MAX_NUM;
stc_mpu_region_permission_t RegionBuffer[MPU_UNIT_MAX_NUM];
if (NULL == pstcRegionInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_REGION(u32Num));
DDL_ASSERT(IS_MPU_REGION_SIZE(pstcRegionInit->u32Size));
DDL_ASSERT(IS_MPU_REGION_BASE_ADDER(pstcRegionInit->u32BaseAddr, pstcRegionInit->u32Size));
DDL_ASSERT(IS_MPU_REGION_WR(pstcRegionInit->stcDma1.u32RegionWrite));
DDL_ASSERT(IS_MPU_REGION_RD(pstcRegionInit->stcDma1.u32RegionRead));
DDL_ASSERT(IS_MPU_REGION_WR(pstcRegionInit->stcDma2.u32RegionWrite));
DDL_ASSERT(IS_MPU_REGION_RD(pstcRegionInit->stcDma2.u32RegionRead));
DDL_ASSERT(IS_MPU_REGION_WR(pstcRegionInit->stcUsbFSDma.u32RegionWrite));
DDL_ASSERT(IS_MPU_REGION_RD(pstcRegionInit->stcUsbFSDma.u32RegionRead));
RGD = MPU_RGD_ADDR(u32Num);
WRITE_REG32(*RGD, (pstcRegionInit->u32Size | pstcRegionInit->u32BaseAddr));
/* Configure the read/write permission for the region */
RegionBuffer[0] = pstcRegionInit->stcDma1;
RegionBuffer[1] = pstcRegionInit->stcDma2;
RegionBuffer[2] = pstcRegionInit->stcUsbFSDma;
if ((u32Num >= MPU_REGION_NUM8) && (u32Num <= MPU_REGION_NUM15)) {
u32UnitNum = 2UL;
}
for (i = 0UL; i < u32UnitNum; i++) {
/* Configure the write permission for the region */
RGWP = MPU_RGCR_ADDR(u32Num);
if (MPU_REGION_WR_DISABLE != RegionBuffer[i].u32RegionWrite) {
CLR_REG32_BIT(*RGWP, MPU_RGCR_S2RGWP << (i << 3U));
} else {
SET_REG32_BIT(*RGWP, MPU_RGCR_S2RGWP << (i << 3U));
}
/* Configure the read permission for the region */
if (MPU_REGION_WR_DISABLE != RegionBuffer[i].u32RegionRead) {
CLR_REG32_BIT(*RGWP, MPU_RGCR_S2RGRP << (i << 3U));
} else {
SET_REG32_BIT(*RGWP, MPU_RGCR_S2RGRP << (i << 3U));
}
}
}
return i32Ret;
}
/**
* @brief Fills each stc_mpu_region_init_t member with default value.
* @param [out] pstcRegionInit Pointer to a @ref stc_mpu_region_init_t structure
* @retval int32_t:
* - LL_OK: stc_mpu_region_init_t member initialize success
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t MPU_RegionStructInit(stc_mpu_region_init_t *pstcRegionInit)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcRegionInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
pstcRegionInit->u32BaseAddr = 0UL;
pstcRegionInit->u32Size = MPU_REGION_SIZE_32BYTE;
pstcRegionInit->stcDma1.u32RegionWrite = MPU_REGION_WR_DISABLE;
pstcRegionInit->stcDma1.u32RegionRead = MPU_REGION_RD_DISABLE;
pstcRegionInit->stcDma2.u32RegionWrite = MPU_REGION_WR_DISABLE;
pstcRegionInit->stcDma2.u32RegionRead = MPU_REGION_RD_DISABLE;
pstcRegionInit->stcUsbFSDma.u32RegionWrite = MPU_REGION_WR_DISABLE;
pstcRegionInit->stcUsbFSDma.u32RegionRead = MPU_REGION_RD_DISABLE;
}
return i32Ret;
}
/**
* @brief Set the base address of the region.
* @note The effective bits of the 'u32Addr' are related to the 'size' of the region,
* and the low 'size+1' bits are fixed at 0.
* @param [in] u32Num The number of the region.
* This parameter can be one of the following values:
* @arg MPU_REGION_NUM0: MPU region number 0
* @arg MPU_REGION_NUM1: MPU region number 1
* @arg MPU_REGION_NUM2: MPU region number 2
* @arg MPU_REGION_NUM3: MPU region number 3
* @arg MPU_REGION_NUM4: MPU region number 4
* @arg MPU_REGION_NUM5: MPU region number 5
* @arg MPU_REGION_NUM6: MPU region number 6
* @arg MPU_REGION_NUM7: MPU region number 7
* @arg MPU_REGION_NUM8: MPU region number 8
* @arg MPU_REGION_NUM9: MPU region number 9
* @arg MPU_REGION_NUM10: MPU region number 10
* @arg MPU_REGION_NUM11: MPU region number 11
* @arg MPU_REGION_NUM12: MPU region number 12
* @arg MPU_REGION_NUM13: MPU region number 13
* @arg MPU_REGION_NUM14: MPU region number 14
* @arg MPU_REGION_NUM15: MPU region number 15
* @param [in] u32Addr The base address of the region.
* @retval None
*/
void MPU_SetRegionBaseAddr(uint32_t u32Num, uint32_t u32Addr)
{
__IO uint32_t *RGD;
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_REGION(u32Num));
RGD = MPU_RGD_ADDR(u32Num);
/* Check parameters */
DDL_ASSERT(IS_MPU_REGION_BASE_ADDER(u32Addr, READ_REG32_BIT(*RGD, MPU_RGD_MPURGSIZE)));
MODIFY_REG32(*RGD, MPU_RGD_MPURGADDR, u32Addr);
}
/**
* @brief Set the size of the region.
* @param [in] u32Num The number of the region.
* This parameter can be one of the following values:
* @arg MPU_REGION_NUM0: MPU region number 0
* @arg MPU_REGION_NUM1: MPU region number 1
* @arg MPU_REGION_NUM2: MPU region number 2
* @arg MPU_REGION_NUM3: MPU region number 3
* @arg MPU_REGION_NUM4: MPU region number 4
* @arg MPU_REGION_NUM5: MPU region number 5
* @arg MPU_REGION_NUM6: MPU region number 6
* @arg MPU_REGION_NUM7: MPU region number 7
* @arg MPU_REGION_NUM8: MPU region number 8
* @arg MPU_REGION_NUM9: MPU region number 9
* @arg MPU_REGION_NUM10: MPU region number 10
* @arg MPU_REGION_NUM11: MPU region number 11
* @arg MPU_REGION_NUM12: MPU region number 12
* @arg MPU_REGION_NUM13: MPU region number 13
* @arg MPU_REGION_NUM14: MPU region number 14
* @arg MPU_REGION_NUM15: MPU region number 15
* @param [in] u32Size The size of the region.
* This parameter can be one of the following values:
* @arg MPU_REGION_SIZE_32BYTE: 32 Byte
* @arg MPU_REGION_SIZE_64BYTE: 64 Byte
* @arg MPU_REGION_SIZE_128BYTE: 126 Byte
* @arg MPU_REGION_SIZE_256BYTE: 256 Byte
* @arg MPU_REGION_SIZE_512BYTE: 512 Byte
* @arg MPU_REGION_SIZE_1KBYTE: 1K Byte
* @arg MPU_REGION_SIZE_2KBYTE: 2K Byte
* @arg MPU_REGION_SIZE_4KBYTE: 4K Byte
* @arg MPU_REGION_SIZE_8KBYTE: 8K Byte
* @arg MPU_REGION_SIZE_16KBYTE: 16K Byte
* @arg MPU_REGION_SIZE_32KBYTE: 32K Byte
* @arg MPU_REGION_SIZE_64KBYTE: 64K Byte
* @arg MPU_REGION_SIZE_128KBYTE: 128K Byte
* @arg MPU_REGION_SIZE_256KBYTE: 256K Byte
* @arg MPU_REGION_SIZE_512KBYTE: 512K Byte
* @arg MPU_REGION_SIZE_1MBYTE: 1M Byte
* @arg MPU_REGION_SIZE_2MBYTE: 2M Byte
* @arg MPU_REGION_SIZE_4MBYTE: 4M Byte
* @arg MPU_REGION_SIZE_8MBYTE: 8M Byte
* @arg MPU_REGION_SIZE_16MBYTE: 16M Byte
* @arg MPU_REGION_SIZE_32MBYTE: 32M Byte
* @arg MPU_REGION_SIZE_64MBYTE: 64M Byte
* @arg MPU_REGION_SIZE_128MBYTE: 128M Byte
* @arg MPU_REGION_SIZE_256MBYTE: 256M Byte
* @arg MPU_REGION_SIZE_512MBYTE: 512M Byte
* @arg MPU_REGION_SIZE_1GBYTE: 1G Byte
* @arg MPU_REGION_SIZE_2GBYTE: 2G Byte
* @arg MPU_REGION_SIZE_4GBYTE: 4G Byte
* @retval None
*/
void MPU_SetRegionSize(uint32_t u32Num, uint32_t u32Size)
{
__IO uint32_t *RGD;
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_REGION(u32Num));
DDL_ASSERT(IS_MPU_REGION_SIZE(u32Size));
RGD = MPU_RGD_ADDR(u32Num);
MODIFY_REG32(*RGD, MPU_RGD_MPURGSIZE, u32Size);
}
/**
* @brief Enable or disable the write of the unit for the region.
* @note 'MPU_REGION_NUM8' to 'MPU_REGION_NUM15' are only valid when the MPU unit is 'MPU_UNIT_DMA1' or 'MPU_UNIT_DMA2'.
* @param [in] u32Num The number of the region.
* This parameter can be one of the following values:
* @arg MPU_REGION_NUM0: MPU region number 0
* @arg MPU_REGION_NUM1: MPU region number 1
* @arg MPU_REGION_NUM2: MPU region number 2
* @arg MPU_REGION_NUM3: MPU region number 3
* @arg MPU_REGION_NUM4: MPU region number 4
* @arg MPU_REGION_NUM5: MPU region number 5
* @arg MPU_REGION_NUM6: MPU region number 6
* @arg MPU_REGION_NUM7: MPU region number 7
* @arg MPU_REGION_NUM8: MPU region number 8
* @arg MPU_REGION_NUM9: MPU region number 9
* @arg MPU_REGION_NUM10: MPU region number 10
* @arg MPU_REGION_NUM11: MPU region number 11
* @arg MPU_REGION_NUM12: MPU region number 12
* @arg MPU_REGION_NUM13: MPU region number 13
* @arg MPU_REGION_NUM14: MPU region number 14
* @arg MPU_REGION_NUM15: MPU region number 15
* @param [in] u32Unit The type of MPU unit.
* This parameter can be one or any combination of the following values:
* @arg @ref MPU_Unit_Type
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void MPU_RegionWriteCmd(uint32_t u32Num, uint32_t u32Unit, en_functional_state_t enNewState)
{
__IO uint32_t *RGWP;
uint32_t u32UnitPos = 0UL;
uint32_t u32Temp;
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_REGION(u32Num));
DDL_ASSERT(IS_MPU_UNIT(u32Unit));
DDL_ASSERT(IS_MPU_UNIT_REGION(u32Unit, u32Num));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
u32Temp = u32Unit;
while (0UL != u32Temp) {
if (0UL != (u32Temp & 0x1UL)) {
RGWP = MPU_RGCR_ADDR(u32Num);
if (DISABLE != enNewState) {
CLR_REG32_BIT(*RGWP, MPU_RGCR_S2RGWP << (u32UnitPos << 3U));
} else {
SET_REG32_BIT(*RGWP, MPU_RGCR_S2RGWP << (u32UnitPos << 3U));
}
}
u32Temp >>= 1UL;
u32UnitPos++;
}
}
/**
* @brief Enable or disable the read of the unit for the region.
* @note 'MPU_REGION_NUM8' to 'MPU_REGION_NUM15' are only valid when the MPU unit is 'MPU_UNIT_DMA1' or 'MPU_UNIT_DMA2'.
* @param [in] u32Num The number of the region.
* This parameter can be one of the following values:
* @arg MPU_REGION_NUM0: MPU region number 0
* @arg MPU_REGION_NUM1: MPU region number 1
* @arg MPU_REGION_NUM2: MPU region number 2
* @arg MPU_REGION_NUM3: MPU region number 3
* @arg MPU_REGION_NUM4: MPU region number 4
* @arg MPU_REGION_NUM5: MPU region number 5
* @arg MPU_REGION_NUM6: MPU region number 6
* @arg MPU_REGION_NUM7: MPU region number 7
* @arg MPU_REGION_NUM8: MPU region number 8
* @arg MPU_REGION_NUM9: MPU region number 9
* @arg MPU_REGION_NUM10: MPU region number 10
* @arg MPU_REGION_NUM11: MPU region number 11
* @arg MPU_REGION_NUM12: MPU region number 12
* @arg MPU_REGION_NUM13: MPU region number 13
* @arg MPU_REGION_NUM14: MPU region number 14
* @arg MPU_REGION_NUM15: MPU region number 15
* @param [in] u32Unit The type of MPU unit.
* This parameter can be one or any combination of the following values:
* @arg @ref MPU_Unit_Type
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void MPU_RegionReadCmd(uint32_t u32Num, uint32_t u32Unit, en_functional_state_t enNewState)
{
__IO uint32_t *RGRP;
uint32_t u32UnitPos = 0UL;
uint32_t u32Temp;
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_REGION(u32Num));
DDL_ASSERT(IS_MPU_UNIT(u32Unit));
DDL_ASSERT(IS_MPU_UNIT_REGION(u32Unit, u32Num));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
u32Temp = u32Unit;
while (0UL != u32Temp) {
if (0UL != (u32Temp & 0x1UL)) {
RGRP = MPU_RGCR_ADDR(u32Num);
if (DISABLE != enNewState) {
CLR_REG32_BIT(*RGRP, MPU_RGCR_S2RGRP << (u32UnitPos << 3U));
} else {
SET_REG32_BIT(*RGRP, MPU_RGCR_S2RGRP << (u32UnitPos << 3U));
}
}
u32Temp >>= 1UL;
u32UnitPos++;
}
}
/**
* @brief Enable or disable the access control of the unit for the region.
* @note 'MPU_REGION_NUM8' to 'MPU_REGION_NUM15' are only valid when the MPU unit is 'MPU_UNIT_DMA1' or 'MPU_UNIT_DMA2'.
* @param [in] u32Num The number of the region.
* This parameter can be one of the following values:
* @arg MPU_REGION_NUM0: MPU region number 0
* @arg MPU_REGION_NUM1: MPU region number 1
* @arg MPU_REGION_NUM2: MPU region number 2
* @arg MPU_REGION_NUM3: MPU region number 3
* @arg MPU_REGION_NUM4: MPU region number 4
* @arg MPU_REGION_NUM5: MPU region number 5
* @arg MPU_REGION_NUM6: MPU region number 6
* @arg MPU_REGION_NUM7: MPU region number 7
* @arg MPU_REGION_NUM8: MPU region number 8
* @arg MPU_REGION_NUM9: MPU region number 9
* @arg MPU_REGION_NUM10: MPU region number 10
* @arg MPU_REGION_NUM11: MPU region number 11
* @arg MPU_REGION_NUM12: MPU region number 12
* @arg MPU_REGION_NUM13: MPU region number 13
* @arg MPU_REGION_NUM14: MPU region number 14
* @arg MPU_REGION_NUM15: MPU region number 15
* @param [in] u32Unit The type of MPU unit.
* This parameter can be one or any combination of the following values:
* @arg @ref MPU_Unit_Type
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void MPU_RegionCmd(uint32_t u32Num, uint32_t u32Unit, en_functional_state_t enNewState)
{
__IO uint32_t *RGE;
uint32_t u32UnitPos = 0UL;
uint32_t u32Temp;
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_REGION(u32Num));
DDL_ASSERT(IS_MPU_UNIT(u32Unit));
DDL_ASSERT(IS_MPU_UNIT_REGION(u32Unit, u32Num));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
u32Temp = u32Unit;
while (0UL != u32Temp) {
if (0UL != (u32Temp & 0x1UL)) {
RGE = MPU_RGCR_ADDR(u32Num);
if (DISABLE != enNewState) {
SET_REG32_BIT(*RGE, MPU_RGCR_S2RGE << (u32UnitPos << 3U));
} else {
CLR_REG32_BIT(*RGE, MPU_RGCR_S2RGE << (u32UnitPos << 3U));
}
}
u32Temp >>= 1UL;
u32UnitPos++;
}
}
/**
* @brief Set the type of exception to access the protected IP.
* @param [in] u32Type Exception type of MPU IP.
* This parameter can be one of the following values:
* @arg MPU_IP_EXP_TYPE_NONE: Access to the protected IP will be ignored
* @arg MPU_IP_EXP_TYPE_BUS_ERR: Access to the protected IP will trigger a bus error
* @retval None
*/
void MPU_IP_SetExceptionType(uint32_t u32Type)
{
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_IP_EXP_TYPE(u32Type));
WRITE_REG32(bCM_MPU->IPPR_b.BUSERRE, (u32Type >> MPU_IPPR_BUSERRE_POS));
}
/**
* @brief Enable or disable write for the IP.
* @param [in] u32Periph The peripheral of the chip.
* This parameter can be one or any combination of the following values:
* @arg MPU_IP_AES: AES module
* @arg MPU_IP_HASH: HASH module
* @arg MPU_IP_TRNG: TRNG module
* @arg MPU_IP_CRC: CRC module
* @arg MPU_IP_EFM: EFM module
* @arg MPU_IP_WDT: WDT module
* @arg MPU_IP_SWDT: SWDT module
* @arg MPU_IP_BKSRAM: BKSRAM module
* @arg MPU_IP_RTC: RTC module
* @arg MPU_IP_MPU: MPU module
* @arg MPU_IP_SRAMC: SRAMC module
* @arg MPU_IP_INTC: INTC module
* @arg MPU_IP_RMU_CMU_PWC: RMU, CMU and PWC modules
* @arg MPU_IP_FCG: PWR_FCG0/1/2/3 and PWR_FCG0PC registers
* @arg MPU_IP_ALL: All of the above
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void MPU_IP_WriteCmd(uint32_t u32Periph, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_IP_TYPE(u32Periph));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (DISABLE != enNewState) {
CLR_REG32_BIT(CM_MPU->IPPR, (u32Periph << 1U));
} else {
SET_REG32_BIT(CM_MPU->IPPR, (u32Periph << 1U));
}
}
/**
* @brief Enable or disable read for the IP.
* @param [in] u32Periph The peripheral of the chip.
* This parameter can be one or any combination of the following values:
* @arg MPU_IP_AES: AES module
* @arg MPU_IP_HASH: HASH module
* @arg MPU_IP_TRNG: TRNG module
* @arg MPU_IP_CRC: CRC module
* @arg MPU_IP_EFM: EFM module
* @arg MPU_IP_WDT: WDT module
* @arg MPU_IP_SWDT: SWDT module
* @arg MPU_IP_BKSRAM: BKSRAM module
* @arg MPU_IP_RTC: RTC module
* @arg MPU_IP_MPU: MPU module
* @arg MPU_IP_SRAMC: SRAMC module
* @arg MPU_IP_INTC: INTC module
* @arg MPU_IP_RMU_CMU_PWC: RMU, CMU and PWC modules
* @arg MPU_IP_FCG: PWR_FCG0/1/2/3 and PWR_FCG0PC registers
* @arg MPU_IP_ALL: All of the above
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void MPU_IP_ReadCmd(uint32_t u32Periph, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_MPU_UNLOCK());
DDL_ASSERT(IS_MPU_IP_TYPE(u32Periph));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (DISABLE != enNewState) {
CLR_REG32_BIT(CM_MPU->IPPR, u32Periph);
} else {
SET_REG32_BIT(CM_MPU->IPPR, u32Periph);
}
}
/**
* @}
*/
#endif /* LL_MPU_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+334
View File
@@ -0,0 +1,334 @@
/**
*******************************************************************************
* @file hc32_ll_ots.c
* @brief This file provides firmware functions to manage the OTS.
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2022-10-31 CDT API fixed: OTS_CalculateTemp()
2023-06-30 CDT Modify typo
Modify API OTS_DeInit()
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_ots.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_OTS OTS
* @brief OTS Driver Library
* @{
*/
#if (LL_OTS_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup OTS_Local_Macros OTS Local Macros
* @{
*/
/**
* @defgroup OTS_Configuration_Bit_Mask OTS Configuration Bit Mask
* @{
*/
#define OTS_CTL_INIT_MSK (OTS_CTL_OTSCK | OTS_CTL_TSSTP)
/**
* @}
*/
/**
* @defgroup OTS_Factor OTS Factor
* @{
*/
#define OTS_DR1_FACTOR (1.0F)
#define OTS_DR2_FACTOR (1.0F)
#define OTS_ECR_XTAL_FACTOR (1.0F)
/**
* @}
*/
/**
* @defgroup OTS_Check_Parameters_Validity OTS check parameters validity
* @{
*/
#define IS_OTS_CLK(x) (((x) == OTS_CLK_HRC) || ((x) == OTS_CLK_XTAL))
#define IS_OTS_AUTO_OFF_EN(x) (((x) == OTS_AUTO_OFF_DISABLE) || ((x) == OTS_AUTO_OFF_ENABLE))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/**
* @defgroup OTS_Local_Variables OTS Local Variables
* @{
*/
static float32_t m_f32SlopeK = 0.0F;
static float32_t m_f32OffsetM = 0.0F;
/**
* @}
*/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup OTS_Global_Functions OTS Global Functions
* @{
*/
/**
* @brief Initializes OTS according to the specified parameters in the structure stc_ots_init_t.
* @param [in] pstcOTSInit Pointer to a stc_ots_init_t structure value that
* contains the configuration information for OTS.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_INVD_PARAM: pstcOTSInit == NULL.
*/
int32_t OTS_Init(const stc_ots_init_t *pstcOTSInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (pstcOTSInit != NULL) {
DDL_ASSERT(IS_OTS_CLK(pstcOTSInit->u16ClockSrc));
DDL_ASSERT(IS_OTS_AUTO_OFF_EN(pstcOTSInit->u16AutoOffEn));
/* Stop OTS sampling. */
OTS_Stop();
WRITE_REG16(CM_OTS->CTL, (pstcOTSInit->u16ClockSrc | pstcOTSInit->u16AutoOffEn));
m_f32SlopeK = pstcOTSInit->f32SlopeK;
m_f32OffsetM = pstcOTSInit->f32OffsetM;
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief Set a default value for OTS initialization structure.
* @param [in] pstcOTSInit Pointer to a stc_ots_init_t structure that
* contains configuration information.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_INVD_PARAM: pstcOTSInit == NULL.
*/
int32_t OTS_StructInit(stc_ots_init_t *pstcOTSInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (pstcOTSInit != NULL) {
pstcOTSInit->u16ClockSrc = OTS_CLK_HRC;
pstcOTSInit->f32SlopeK = 0.0F;
pstcOTSInit->f32OffsetM = 0.0F;
pstcOTSInit->u16AutoOffEn = OTS_AUTO_OFF_ENABLE;
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief De-initializes OTS peripheral. Reset the registers of OTS.
* @param None
* @retval int32_t:
* - LL_OK: De-Initialize success.
*/
int32_t OTS_DeInit(void)
{
/* Stop OTS. */
OTS_Stop();
/* Set the value of all registers to the reset value. */
WRITE_REG16(CM_OTS->CTL, 0U);
WRITE_REG16(CM_OTS->DR1, 0U);
WRITE_REG16(CM_OTS->DR2, 0U);
WRITE_REG16(CM_OTS->ECR, 0U);
return LL_OK;
}
/**
* @brief Get temperature via normal mode.
* @param [out] pf32Temp Pointer to a float32_t type address that the temperature value to be stored.
* @param [in] u32Timeout Timeout value.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_TIMEOUT: Works timeout.
* - LL_ERR_INVD_PARAM: pf32Temp == NULL.
*/
int32_t OTS_Polling(float32_t *pf32Temp, uint32_t u32Timeout)
{
__IO uint32_t u32TimeCount = u32Timeout;
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (pf32Temp != NULL) {
i32Ret = LL_ERR_TIMEOUT;
OTS_Start();
while (u32TimeCount-- != 0U) {
if (READ_REG32(bCM_OTS->CTL_b.OTSST) == 0UL) {
*pf32Temp = OTS_CalculateTemp();
i32Ret = LL_OK;
break;
}
}
OTS_Stop();
}
return i32Ret;
}
/**
* @brief Enable or disable the OTS interrupt.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void OTS_IntCmd(en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
WRITE_REG32(bCM_OTS->CTL_b.OTSIE, enNewState);
}
/**
* @brief OTS scaling experiment. Get the value of the data register at the specified temperature to calculate K and M.
* @param [out] pu16Dr1: Pointer to an address to store the value of data register 1.
* @param [out] pu16Dr2: Pointer to an address to store the value of data register 2.
* @param [out] pu16Ecr: Pointer to an address to store the value of register ECR.
* @param [out] pf32A: Pointer to an address to store the parameter A.
* @param [in] u32Timeout: Timeout value.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_TIMEOUT: Works timeout.
* - LL_ERR_INVD_PARAM: If one the following cases matches:
* - pu16Dr1 == NULL.
* - pu16Dr2 == NULL.
* - pu16Ecr == NULL.
* - pf32A == NULL.
*/
int32_t OTS_ScalingExperiment(uint16_t *pu16Dr1, uint16_t *pu16Dr2,
uint16_t *pu16Ecr, float32_t *pf32A,
uint32_t u32Timeout)
{
float32_t f32Dr1;
float32_t f32Dr2;
float32_t f32Ecr;
__IO uint32_t u32TimeCount = u32Timeout;
int32_t i32Ret = LL_ERR_INVD_PARAM;
if ((NULL != pu16Dr1) && (NULL != pu16Dr2) && \
(NULL != pu16Ecr) && (NULL != pf32A)) {
i32Ret = LL_ERR_TIMEOUT;
OTS_Start();
while (u32TimeCount-- != 0U) {
if (READ_REG32(bCM_OTS->CTL_b.OTSST) == 0UL) {
i32Ret = LL_OK;
break;
}
}
OTS_Stop();
if (i32Ret == LL_OK) {
*pu16Dr1 = READ_REG16(CM_OTS->DR1);
*pu16Dr2 = READ_REG16(CM_OTS->DR2);
f32Dr1 = (float32_t)(*pu16Dr1);
f32Dr2 = (float32_t)(*pu16Dr2);
if (READ_REG8_BIT(CM_OTS->CTL, OTS_CTL_OTSCK) == OTS_CLK_HRC) {
*pu16Ecr = READ_REG16(CM_OTS->ECR);
f32Ecr = (float32_t)(*pu16Ecr);
} else {
*pu16Ecr = 1U;
f32Ecr = OTS_ECR_XTAL_FACTOR;
}
if ((f32Dr1 != 0.0F) && (f32Dr2 != 0.0F) && (f32Ecr != 0.0F)) {
*pf32A = ((OTS_DR1_FACTOR / f32Dr1) - (OTS_DR2_FACTOR / f32Dr2)) * f32Ecr;
}
}
}
return i32Ret;
}
/**
* @brief Calculate the temperature value.
* @param None
* @retval A float32_t type value of temperature.
*/
float32_t OTS_CalculateTemp(void)
{
float32_t f32Ret = -300.0F;
uint16_t u16Dr1 = READ_REG16(CM_OTS->DR1);
uint16_t u16Dr2 = READ_REG16(CM_OTS->DR2);
uint16_t u16Ecr = READ_REG16(CM_OTS->ECR);
float32_t f32Dr1 = (float32_t)u16Dr1;
float32_t f32Dr2 = (float32_t)u16Dr2;
float32_t f32Ecr = (float32_t)u16Ecr;
if (READ_REG8_BIT(CM_OTS->CTL, OTS_CTL_OTSCK) == OTS_CLK_XTAL) {
f32Ecr = OTS_ECR_XTAL_FACTOR;
}
if ((f32Dr1 != 0.0F) && (f32Dr2 != 0.0F) && (f32Ecr != 0.0F)) {
f32Ret = m_f32SlopeK * ((OTS_DR1_FACTOR / f32Dr1) - (OTS_DR2_FACTOR / f32Dr2)) * f32Ecr + m_f32OffsetM;
}
return f32Ret;
}
/**
* @}
*/
#endif /* LL_OTS_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
File diff suppressed because it is too large Load Diff
+481
View File
@@ -0,0 +1,481 @@
/**
*******************************************************************************
* @file hc32_ll_qspi.c
* @brief This file provides firmware functions to manage the QSPI.
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2023-01-15 CDT Modify the conditions for entering direct communication mode
2023-09-30 CDT Optimize QSPI_ClearStatus function
Modify return value type of QSPI_DeInit function
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_qspi.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_QSPI QSPI
* @brief QSPI Driver Library
* @{
*/
#if (LL_QSPI_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup QSPI_Local_Macros QSPI Local Macros
* @{
*/
/* QSPI registers Mask */
#define QSPI_CR_CLR_MASK (QSPI_CR_DIV | QSPI_CR_SPIMD3 | QSPI_CR_PFSAE | \
QSPI_CR_PFE | QSPI_CR_MDSEL)
#define QSPI_FCR_CLR_MASK (QSPI_FCR_DUTY | QSPI_FCR_DMCYCN | QSPI_FCR_SSNLD | \
QSPI_FCR_SSNHD | QSPI_FCR_FOUR_BIC | QSPI_FCR_AWSL)
#define QSPI_CUSTOM_MD_CLR_MASK (QSPI_CR_IPRSL | QSPI_CR_APRSL | QSPI_CR_DPRSL)
/**
* @defgroup QSPI_Check_Parameters_Validity QSPI check parameters validity
* @{
*/
#define IS_QSPI_CLK_DIV(x) \
( ((x) != 0U) && \
(((x) | QSPI_CLK_DIV64) == QSPI_CLK_DIV64))
#define IS_QSPI_SPI_MD(x) \
( ((x) == QSPI_SPI_MD0) || \
((x) == QSPI_SPI_MD3))
#define IS_QSPI_PREFETCH_MD(x) \
( ((x) == QSPI_PREFETCH_MD_INVD) || \
((x) == QSPI_PREFETCH_MD_EDGE_STOP) || \
((x) == QSPI_PREFETCH_MD_IMMED_STOP))
#define IS_QSPI_READ_MD(x) \
( ((x) == QSPI_RD_MD_STD_RD) || \
((x) == QSPI_RD_MD_FAST_RD) || \
((x) == QSPI_RD_MD_DUAL_OUTPUT_FAST_RD) || \
((x) == QSPI_RD_MD_DUAL_IO_FAST_RD) || \
((x) == QSPI_RD_MD_QUAD_OUTPUT_FAST_RD) || \
((x) == QSPI_RD_MD_QUAD_IO_FAST_RD) || \
((x) == QSPI_RD_MD_CUSTOM_STANDARD_RD) || \
((x) == QSPI_RD_MD_CUSTOM_FAST_RD))
#define IS_QSPI_DUMMY_CYCLE(x) (((x) | QSPI_DUMMY_CYCLE18) == QSPI_DUMMY_CYCLE18)
#define IS_QSPI_ADDR_WIDTH(x) \
( ((x) == QSPI_ADDR_WIDTH_8BIT) || \
((x) == QSPI_ADDR_WIDTH_16BIT) || \
((x) == QSPI_ADDR_WIDTH_24BIT) || \
((x) == QSPI_ADDR_WIDTH_32BIT_INSTR_24BIT) || \
((x) == QSPI_ADDR_WIDTH_32BIT_INSTR_32BIT))
#define IS_QSPI_QSSN_SETUP_TIME(x) \
( ((x) == QSPI_QSSN_SETUP_ADVANCE_QSCK0P5) || \
((x) == QSPI_QSSN_SETUP_ADVANCE_QSCK1P5))
#define IS_QSPI_QSSN_RELEASE_TIME(x) \
( ((x) == QSPI_QSSN_RELEASE_DELAY_QSCK0P5) || \
((x) == QSPI_QSSN_RELEASE_DELAY_QSCK1P5) || \
((x) == QSPI_QSSN_RELEASE_DELAY_QSCK32) || \
((x) == QSPI_QSSN_RELEASE_DELAY_QSCK128) || \
((x) == QSPI_QSSN_RELEASE_DELAY_INFINITE))
#define IS_QSPI_QSSN_INTERVAL_TIME(x) ((x) <= QSPI_QSSN_INTERVAL_QSCK16)
#define IS_QSPI_INSTR_PROTOCOL(x) \
( ((x) == QSPI_INSTR_PROTOCOL_1LINE) || \
((x) == QSPI_INSTR_PROTOCOL_2LINE) || \
((x) == QSPI_INSTR_PROTOCOL_4LINE))
#define IS_QSPI_ADDR_PROTOCOL(x) \
( ((x) == QSPI_ADDR_PROTOCOL_1LINE) || \
((x) == QSPI_ADDR_PROTOCOL_2LINE) || \
((x) == QSPI_ADDR_PROTOCOL_4LINE))
#define IS_QSPI_DATA_PROTOCOL(x) \
( ((x) == QSPI_DATA_PROTOCOL_1LINE) || \
((x) == QSPI_DATA_PROTOCOL_2LINE) || \
((x) == QSPI_DATA_PROTOCOL_4LINE))
#define IS_QSPI_WP_PIN_LVL(x) \
( ((x) == QSPI_WP_PIN_LOW) || \
((x) == QSPI_WP_PIN_HIGH))
#define IS_QSPI_FLAG(x) \
( ((x) != 0U) && \
(((x) | QSPI_FLAG_ALL) == QSPI_FLAG_ALL))
#define IS_QSPI_CLR_FLAG(x) \
( ((x) != 0U) && \
(((x) | QSPI_FLAG_CLR_ALL) == QSPI_FLAG_CLR_ALL))
#define IS_QSPI_BLOCK_SIZE(x) ((x) <= (QSPI_EXAR_EXADR >> QSPI_EXAR_EXADR_POS))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/**
* @defgroup QSPI_Local_Variable QSPI Local Variable
* @{
*/
/* Current read mode */
static uint32_t m_u32ReadMode = 0U;
/**
* @}
*/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup QSPI_Global_Functions QSPI Global Functions
* @{
*/
/**
* @brief De-initializes QSPI.
* @param None
* @retval int32_t:
* - LL_OK: No error occurred.
* - LL_ERR_TIMEOUT: Works timeout.
*/
int32_t QSPI_DeInit(void)
{
WRITE_REG32(CM_QSPI->CR, 0x003F0000UL);
WRITE_REG32(CM_QSPI->CSCR, 0x0FUL);
WRITE_REG32(CM_QSPI->FCR, 0x8033UL);
WRITE_REG32(CM_QSPI->CCMD, 0x0UL);
WRITE_REG32(CM_QSPI->XCMD, 0xFFUL);
WRITE_REG32(CM_QSPI->SR2, QSPI_FLAG_ROM_ACCESS_ERR);
WRITE_REG32(CM_QSPI->EXAR, 0UL);
return LL_OK;
}
/**
* @brief Initialize QSPI.
* @param [in] pstcQspiInit Pointer to a @ref stc_qspi_init_t structure
* @retval int32_t:
* - LL_OK: Initialize success
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t QSPI_Init(const stc_qspi_init_t *pstcQspiInit)
{
int32_t i32Ret = LL_OK;
uint32_t u32Duty = 0UL;
if (NULL == pstcQspiInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_QSPI_CLK_DIV(pstcQspiInit->u32ClockDiv));
DDL_ASSERT(IS_QSPI_SPI_MD(pstcQspiInit->u32SpiMode));
DDL_ASSERT(IS_QSPI_PREFETCH_MD(pstcQspiInit->u32PrefetchMode));
DDL_ASSERT(IS_QSPI_READ_MD(pstcQspiInit->u32ReadMode));
DDL_ASSERT(IS_QSPI_DUMMY_CYCLE(pstcQspiInit->u32DummyCycle));
DDL_ASSERT(IS_QSPI_ADDR_WIDTH(pstcQspiInit->u32AddrWidth));
DDL_ASSERT(IS_QSPI_QSSN_SETUP_TIME(pstcQspiInit->u32SetupTime));
DDL_ASSERT(IS_QSPI_QSSN_RELEASE_TIME(pstcQspiInit->u32ReleaseTime));
DDL_ASSERT(IS_QSPI_QSSN_INTERVAL_TIME(pstcQspiInit->u32IntervalTime));
/* Duty cycle compensation */
if (0UL == (pstcQspiInit->u32ClockDiv & QSPI_CLK_DIV2)) {
u32Duty = QSPI_FCR_DUTY;
}
MODIFY_REG32(CM_QSPI->CR, QSPI_CR_CLR_MASK, (pstcQspiInit->u32ClockDiv | pstcQspiInit->u32SpiMode |
pstcQspiInit->u32PrefetchMode | pstcQspiInit->u32ReadMode));
WRITE_REG32(CM_QSPI->CSCR, ((pstcQspiInit->u32ReleaseTime >> 8U) | pstcQspiInit->u32IntervalTime));
MODIFY_REG32(CM_QSPI->FCR, QSPI_FCR_CLR_MASK, (pstcQspiInit->u32DummyCycle | pstcQspiInit->u32AddrWidth |
pstcQspiInit->u32SetupTime | (pstcQspiInit->u32ReleaseTime & 0xFFU) | u32Duty));
}
return i32Ret;
}
/**
* @brief Fills each stc_qspi_init_t member with default value.
* @param [out] pstcQspiInit Pointer to a @ref stc_qspi_init_t structure
* @retval int32_t:
* - LL_OK: stc_qspi_init_t member initialize success
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t QSPI_StructInit(stc_qspi_init_t *pstcQspiInit)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcQspiInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
pstcQspiInit->u32ClockDiv = QSPI_CLK_DIV2;
pstcQspiInit->u32SpiMode = QSPI_SPI_MD0;
pstcQspiInit->u32PrefetchMode = QSPI_PREFETCH_MD_INVD;
pstcQspiInit->u32ReadMode = QSPI_RD_MD_STD_RD;
pstcQspiInit->u32DummyCycle = QSPI_DUMMY_CYCLE3;
pstcQspiInit->u32AddrWidth = QSPI_ADDR_WIDTH_24BIT;
pstcQspiInit->u32SetupTime = QSPI_QSSN_SETUP_ADVANCE_QSCK0P5;
pstcQspiInit->u32ReleaseTime = QSPI_QSSN_RELEASE_DELAY_QSCK0P5;
pstcQspiInit->u32IntervalTime = QSPI_QSSN_INTERVAL_QSCK1;
}
return i32Ret;
}
/**
* @brief Set the level of WP pin.
* @param [in] u32Level The level value.
* This parameter can be one of the following values:
* @arg QSPI_WP_PIN_LOW: WP(QSIO2) pin output low
* @arg QSPI_WP_PIN_HIGH: WP(QSIO2) pin output high
* @retval None
*/
void QSPI_SetWpPinLevel(uint32_t u32Level)
{
/* Check parameters */
DDL_ASSERT(IS_QSPI_WP_PIN_LVL(u32Level));
MODIFY_REG32(CM_QSPI->FCR, QSPI_FCR_WPOL, u32Level);
}
/**
* @brief Set the prefetch mode.
* @param [in] u32Mode The prefetch mode.
* This parameter can be one of the following values:
* @arg QSPI_PREFETCH_MD_INVD: Disable prefetch
* @arg QSPI_PREFETCH_MD_EDGE_STOP: Stop prefetch at the edge of byte
* @arg QSPI_PREFETCH_MD_IMMED_STOP: Stop prefetch at current position immediately
* @retval None
*/
void QSPI_SetPrefetchMode(uint32_t u32Mode)
{
/* Check parameters */
DDL_ASSERT(IS_QSPI_PREFETCH_MD(u32Mode));
MODIFY_REG32(CM_QSPI->CR, (QSPI_CR_PFE | QSPI_CR_PFSAE), u32Mode);
}
/**
* @brief Selects the block to access.
* @param [in] u8Block Memory block number (range is 0 to 63)
* @retval None
*/
void QSPI_SelectMemoryBlock(uint8_t u8Block)
{
/* Check parameters */
DDL_ASSERT(IS_QSPI_BLOCK_SIZE(u8Block));
WRITE_REG32(CM_QSPI->EXAR, ((uint32_t)u8Block << QSPI_EXAR_EXADR_POS));
}
/**
* @brief Set the read mode.
* @param [in] u32Mode Read mode.
* This parameter can be one of the following values:
* @arg QSPI_RD_MD_STD_RD: Standard read mode (no dummy cycles)
* @arg QSPI_RD_MD_FAST_RD: Fast read mode (dummy cycles between address and data)
* @arg QSPI_RD_MD_DUAL_OUTPUT_FAST_RD: Fast read dual output mode (data on 2 lines)
* @arg QSPI_RD_MD_DUAL_IO_FAST_RD: Fast read dual I/O mode (address and data on 2 lines)
* @arg QSPI_RD_MD_QUAD_OUTPUT_FAST_RD: Fast read quad output mode (data on 4 lines)
* @arg QSPI_RD_MD_QUAD_IO_FAST_RD: Fast read quad I/O mode (address and data on 4 lines)
* @arg QSPI_RD_MD_CUSTOM_STANDARD_RD: Custom standard read mode
* @arg QSPI_RD_MD_CUSTOM_FAST_RD: Custom fast read mode
* @retval None
*/
void QSPI_SetReadMode(uint32_t u32Mode)
{
/* Check parameters */
DDL_ASSERT(IS_QSPI_READ_MD(u32Mode));
MODIFY_REG32(CM_QSPI->CR, QSPI_CR_MDSEL, u32Mode);
}
/**
* @brief Configure the custom read.
* @param [in] pstcCustomMode Pointer to a @ref stc_qspi_custom_mode_t structure
* @retval int32_t:
* - LL_OK: Initialize success
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t QSPI_CustomReadConfig(const stc_qspi_custom_mode_t *pstcCustomMode)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcCustomMode) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_QSPI_INSTR_PROTOCOL(pstcCustomMode->u32InstrProtocol));
DDL_ASSERT(IS_QSPI_ADDR_PROTOCOL(pstcCustomMode->u32AddrProtocol));
DDL_ASSERT(IS_QSPI_DATA_PROTOCOL(pstcCustomMode->u32DataProtocol));
MODIFY_REG32(CM_QSPI->CR, QSPI_CUSTOM_MD_CLR_MASK, (pstcCustomMode->u32InstrProtocol |
pstcCustomMode->u32AddrProtocol | pstcCustomMode->u32DataProtocol));
WRITE_REG32(CM_QSPI->CCMD, pstcCustomMode->u8InstrCode);
}
return i32Ret;
}
/**
* @brief Enable or disable XIP mode.
* @param [in] u8ModeCode Enter or exit XIP mode code
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void QSPI_XipModeCmd(uint8_t u8ModeCode, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
WRITE_REG32(CM_QSPI->XCMD, u8ModeCode);
if (ENABLE == enNewState) {
SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_XIPE);
} else {
CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_XIPE);
}
}
/**
* @brief Enter direct communication mode.
* @param None
* @retval None
*/
void QSPI_EnterDirectCommMode(void)
{
/* Backup the read mode */
m_u32ReadMode = READ_REG32_BIT(CM_QSPI->CR, QSPI_CR_MDSEL);
if (m_u32ReadMode <= QSPI_RD_MD_QUAD_IO_FAST_RD) {
/* Set standard read mode */
CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_MDSEL);
}
/* Enter direct communication mode */
SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
}
/**
* @brief Exit direct communication mode.
* @param None
* @retval None
*/
void QSPI_ExitDirectCommMode(void)
{
/* Exit direct communication mode */
CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
if (m_u32ReadMode <= QSPI_RD_MD_QUAD_IO_FAST_RD) {
/* Recovery the read mode */
SET_REG32_BIT(CM_QSPI->CR, m_u32ReadMode);
}
}
/**
* @brief Get the size of prefetched buffer.
* @param None
* @retval uint8_t Prefetched buffer size.
*/
uint8_t QSPI_GetPrefetchBufSize(void)
{
return (uint8_t)(READ_REG32_BIT(CM_QSPI->SR, QSPI_SR_PFNUM) >> QSPI_SR_PFNUM_POS);
}
/**
* @brief Get QSPI flag.
* @param [in] u32Flag QSPI flag type
* This parameter can be one or any combination of the following values:
* @arg QSPI_FLAG_DIRECT_COMM_BUSY: Serial transfer being processed
* @arg QSPI_FLAG_XIP_MD: XIP mode
* @arg QSPI_FLAG_ROM_ACCESS_ERR: ROM access detection status in direct communication mode
* @arg QSPI_FLAG_PREFETCH_BUF_FULL: Prefetch buffer is full
* @arg QSPI_FLAG_PREFETCH_STOP: Prefetch function operating
* @arg QSPI_FLAG_ALL: All of the above
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t QSPI_GetStatus(uint32_t u32Flag)
{
en_flag_status_t enFlagSta = RESET;
/* Check parameters */
DDL_ASSERT(IS_QSPI_FLAG(u32Flag));
if (0UL != READ_REG32_BIT(CM_QSPI->SR, u32Flag)) {
enFlagSta = SET;
}
return enFlagSta;
}
/**
* @brief Clear QSPI flag.
* @param [in] u32Flag QSPI flag type
* This parameter can be one or any combination of the following values:
* @arg QSPI_FLAG_ROM_ACCESS_ERR: ROM access detection status in direct communication mode
* @arg QSPI_FLAG_CLR_ALL: All of the above
* @retval None
*/
void QSPI_ClearStatus(uint32_t u32Flag)
{
/* Check parameters */
DDL_ASSERT(IS_QSPI_CLR_FLAG(u32Flag));
WRITE_REG32(CM_QSPI->SR2, u32Flag);
}
/**
* @}
*/
#endif /* LL_QSPI_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+137
View File
@@ -0,0 +1,137 @@
/**
*******************************************************************************
* @file hc32_ll_rmu.c
* @brief This file provides firmware functions to manage the Reset Manage Unit
* (RMU).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_rmu.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_RMU RMU
* @brief RMU Driver Library
* @{
*/
#if (LL_RMU_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup RMU_Local_Macros RMU Local Macros
* @{
*/
/**
* @defgroup RMU_Check_Parameters_Validity RMU Check Parameters Validity
* @{
*/
/*! Parameter validity check for RMU reset cause. */
#define IS_VALID_RMU_RST_FLAG(x) \
( ((x) != 0UL) && \
(((x) | RMU_FLAG_ALL) == RMU_FLAG_ALL))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup RMU_Global_Functions RMU Global Functions
* @{
*/
/**
* @brief Get the reset cause.
* @param [in] u32RmuResetCause Reset flags that need to be queried, @ref RMU_ResetCause in details
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t RMU_GetStatus(uint32_t u32RmuResetCause)
{
en_flag_status_t enStatus;
DDL_ASSERT(IS_VALID_RMU_RST_FLAG(u32RmuResetCause));
enStatus = ((0UL == READ_REG32_BIT(CM_RMU->RSTF0, u32RmuResetCause)) ? RESET : SET);
return enStatus;
}
/**
* @brief Clear reset Status.
* @param None
* @retval NOne
* @note Clear reset flag should be done after read RMU_RSTF0 register.
* Call PWC_Unlock(PWC_UNLOCK_CODE_1) unlock RMU_RSTF0 register first.
*/
void RMU_ClearStatus(void)
{
SET_REG_BIT(CM_RMU->RSTF0, RMU_RSTF0_CLRF);
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
}
/**
* @}
*/
#endif /* LL_RMU_ENABLE */
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/
+936
View File
@@ -0,0 +1,936 @@
/**
*******************************************************************************
* @file hc32_ll_rtc.c
* @brief This file provides firmware functions to manage the Real-Time
* Clock(RTC).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_rtc.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_RTC RTC
* @brief Real-Time Clock Driver Library
* @{
*/
#if (LL_RTC_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup RTC_Local_Macros RTC Local Macros
* @{
*/
/* RTC software reset timeout(ms) */
#define RTC_SW_RST_TIMEOUT (100UL)
/* RTC mode switch timeout(ms) */
#define RTC_MD_SWITCH_TIMEOUT (100UL)
/**
* @defgroup RTC_Check_Parameters_Validity RTC Check Parameters Validity
* @{
*/
#define IS_RTC_DATA_FMT(x) \
( ((x) == RTC_DATA_FMT_DEC) || \
((x) == RTC_DATA_FMT_BCD))
#define IS_RTC_CLK_SRC(x) \
( ((x) == RTC_CLK_SRC_XTAL32) || \
((x) == RTC_CLK_SRC_LRC))
#define IS_RTC_HOUR_FMT(x) \
( ((x) == RTC_HOUR_FMT_12H) || \
((x) == RTC_HOUR_FMT_24H))
#define IS_RTC_INT_PERIOD(x) \
( ((x) == RTC_INT_PERIOD_INVD) || \
((x) == RTC_INT_PERIOD_PER_HALF_SEC) || \
((x) == RTC_INT_PERIOD_PER_SEC) || \
((x) == RTC_INT_PERIOD_PER_MINUTE) || \
((x) == RTC_INT_PERIOD_PER_HOUR) || \
((x) == RTC_INT_PERIOD_PER_DAY) || \
((x) == RTC_INT_PERIOD_PER_MONTH))
#define IS_RTC_CLK_COMPEN(x) \
( ((x) == RTC_CLK_COMPEN_DISABLE) || \
((x) == RTC_CLK_COMPEN_ENABLE))
#define IS_RTC_CLK_COMPEN_MD(x) \
( ((x) == RTC_CLK_COMPEN_MD_DISTRIBUTED) || \
((x) == RTC_CLK_COMPEN_MD_UNIFORM))
#define IS_RTC_HOUR_12H_AM_PM(x) \
( ((x) == RTC_HOUR_12H_AM) || \
((x) == RTC_HOUR_12H_PM))
#define IS_RTC_GET_FLAG(x) \
( ((x) != 0U) && \
(((x) | RTC_FLAG_ALL) == RTC_FLAG_ALL))
#define IS_RTC_CLR_FLAG(x) \
( ((x) != 0U) && \
(((x) | RTC_FLAG_CLR_ALL) == RTC_FLAG_CLR_ALL))
#define IS_RTC_INT(x) \
( ((x) != 0U) && \
(((x) | RTC_INT_ALL) == RTC_INT_ALL))
#define IS_RTC_YEAR(x) ((x) <= 99U)
#define IS_RTC_MONTH(x) (((x) >= 1U) && ((x) <= 12U))
#define IS_RTC_DAY(x) (((x) >= 1U) && ((x) <= 31U))
#define IS_RTC_HOUR_12H(x) (((x) >= 1U) && ((x) <= 12U))
#define IS_RTC_HOUR_24H(x) ((x) <= 23U)
#define IS_RTC_MINUTE(x) ((x) <= 59U)
#define IS_RTC_SEC(x) ((x) <= 59U)
#define IS_RTC_WEEKDAY(x) ((x) <= 6U)
#define IS_RTC_ALARM_WEEKDAY(x) (((x) >= 0x01U) && ((x) <= 0x7FU))
#define IS_RTC_COMPEN_VALUE(x) ((x) <= 0x1FFU)
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup RTC_Global_Functions RTC Global Functions
* @{
*/
/**
* @brief De-Initialize RTC.
* @param None
* @retval int32_t:
* - LL_OK: De-Initialize success
* - LL_ERR_TIMEOUT: De-Initialize timeout
*/
int32_t RTC_DeInit(void)
{
__IO uint32_t u32Count;
int32_t i32Ret = LL_OK;
WRITE_REG32(bCM_RTC->CR0_b.RESET, RESET);
/* Waiting for normal count status or end of RTC software reset */
u32Count = RTC_SW_RST_TIMEOUT * (HCLK_VALUE / 20000UL);
while (0UL != READ_REG32(bCM_RTC->CR0_b.RESET)) {
if (0UL == u32Count) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
u32Count--;
}
if (LL_OK == i32Ret) {
/* Reset all RTC registers */
WRITE_REG32(bCM_RTC->CR0_b.RESET, SET);
/* Waiting for RTC software reset to complete */
u32Count = RTC_SW_RST_TIMEOUT * (HCLK_VALUE / 20000UL);
while (0UL != READ_REG32(bCM_RTC->CR0_b.RESET)) {
if (0UL == u32Count) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
u32Count--;
}
}
return i32Ret;
}
/**
* @brief Initialize RTC.
* @param [in] pstcRtcInit Pointer to a @ref stc_rtc_init_t structure
* @retval int32_t:
* - LL_OK: Initialize success
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t RTC_Init(const stc_rtc_init_t *pstcRtcInit)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcRtcInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_RTC_CLK_SRC(pstcRtcInit->u8ClockSrc));
DDL_ASSERT(IS_RTC_HOUR_FMT(pstcRtcInit->u8HourFormat));
DDL_ASSERT(IS_RTC_INT_PERIOD(pstcRtcInit->u8IntPeriod));
DDL_ASSERT(IS_RTC_CLK_COMPEN(pstcRtcInit->u8ClockCompen));
DDL_ASSERT(IS_RTC_COMPEN_VALUE(pstcRtcInit->u16CompenValue));
DDL_ASSERT(IS_RTC_CLK_COMPEN_MD(pstcRtcInit->u8CompenMode));
/* RTC CR3 Configuration */
MODIFY_REG8(CM_RTC->CR3, (RTC_CR3_LRCEN | RTC_CR3_RCKSEL), pstcRtcInit->u8ClockSrc);
/* RTC CR1 Configuration */
MODIFY_REG8(CM_RTC->CR1, (RTC_CR1_PRDS | RTC_CR1_AMPM | RTC_CR1_ONEHZSEL),
(pstcRtcInit->u8IntPeriod | pstcRtcInit->u8HourFormat | pstcRtcInit->u8CompenMode));
/* RTC Compensation Configuration */
MODIFY_REG8(CM_RTC->ERRCRH, (RTC_ERRCRH_COMPEN | RTC_ERRCRH_COMP8),
(pstcRtcInit->u8ClockCompen | (uint8_t)((pstcRtcInit->u16CompenValue >> 8U) & 0x01U)));
WRITE_REG8(CM_RTC->ERRCRL, (uint8_t)(pstcRtcInit->u16CompenValue & 0xFFU));
}
return i32Ret;
}
/**
* @brief Fills each stc_rtc_init_t member with default value.
* @param [out] pstcRtcInit Pointer to a @ref stc_rtc_init_t structure
* @retval int32_t:
* - LL_OK: stc_rtc_init_t member initialize success
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t RTC_StructInit(stc_rtc_init_t *pstcRtcInit)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcRtcInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
pstcRtcInit->u8ClockSrc = RTC_CLK_SRC_LRC;
pstcRtcInit->u8HourFormat = RTC_HOUR_FMT_24H;
pstcRtcInit->u8IntPeriod = RTC_INT_PERIOD_INVD;
pstcRtcInit->u8ClockCompen = RTC_CLK_COMPEN_DISABLE;
pstcRtcInit->u8CompenMode = RTC_CLK_COMPEN_MD_DISTRIBUTED;
pstcRtcInit->u16CompenValue = 0U;
}
return i32Ret;
}
/**
* @brief Enter RTC read/write mode.
* @param None
* @retval int32_t:
* - LL_OK: Enter mode success
* - LL_ERR_TIMEOUT: Enter mode timeout
*/
int32_t RTC_EnterRwMode(void)
{
__IO uint32_t u32Count;
int32_t i32Ret = LL_OK;
/* Mode switch when RTC is running */
if (0UL != READ_REG32(bCM_RTC->CR1_b.START)) {
if (1UL != READ_REG32(bCM_RTC->CR2_b.RWEN)) {
WRITE_REG32(bCM_RTC->CR2_b.RWREQ, SET);
/* Waiting for RWEN bit set */
u32Count = RTC_MD_SWITCH_TIMEOUT * (HCLK_VALUE / 20000UL);
while (1UL != READ_REG32(bCM_RTC->CR2_b.RWEN)) {
if (0UL == u32Count) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
u32Count--;
}
}
}
return i32Ret;
}
/**
* @brief Exit RTC read/write mode.
* @param None
* @retval int32_t:
* - LL_OK: Exit mode success
* - LL_ERR_TIMEOUT: Exit mode timeout
*/
int32_t RTC_ExitRwMode(void)
{
__IO uint32_t u32Count;
int32_t i32Ret = LL_OK;
/* Mode switch when RTC is running */
if (0UL != READ_REG32(bCM_RTC->CR1_b.START)) {
if (0UL != READ_REG32(bCM_RTC->CR2_b.RWEN)) {
WRITE_REG32(bCM_RTC->CR2_b.RWREQ, RESET);
/* Waiting for RWEN bit reset */
u32Count = RTC_MD_SWITCH_TIMEOUT * (HCLK_VALUE / 20000UL);
while (0UL != READ_REG32(bCM_RTC->CR2_b.RWEN)) {
if (0UL == u32Count) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
u32Count--;
}
}
}
return i32Ret;
}
/**
* @brief Confirm the condition for RTC to enter low power mode.
* @param None
* @retval int32_t:
* - LL_OK: Can enter low power mode
* - LL_ERR_TIMEOUT: Can't enter low power mode
*/
int32_t RTC_ConfirmLPMCond(void)
{
__IO uint32_t u32Count;
int32_t i32Ret = LL_OK;
/* Check RTC work status */
if (0UL != READ_REG32(bCM_RTC->CR1_b.START)) {
WRITE_REG32(bCM_RTC->CR2_b.RWREQ, SET);
/* Waiting for RTC RWEN bit set */
u32Count = RTC_MD_SWITCH_TIMEOUT * (HCLK_VALUE / 20000UL);
while (1UL != READ_REG32(bCM_RTC->CR2_b.RWEN)) {
if (0UL == u32Count) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
u32Count--;
}
if (LL_OK == i32Ret) {
WRITE_REG32(bCM_RTC->CR2_b.RWREQ, RESET);
/* Waiting for RTC RWEN bit reset */
u32Count = RTC_MD_SWITCH_TIMEOUT * (HCLK_VALUE / 20000UL);
while (0UL != READ_REG32(bCM_RTC->CR2_b.RWEN)) {
if (0UL == u32Count) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
u32Count--;
}
}
}
return i32Ret;
}
/**
* @brief Set the RTC interrupt period.
* @param [in] u8Period Specifies the interrupt period.
* This parameter can be one of the following values:
* @arg RTC_INT_PERIOD_INVD: Period interrupt invalid
* @arg RTC_INT_PERIOD_PER_HALF_SEC: Interrupt per half second
* @arg RTC_INT_PERIOD_PER_SEC: Interrupt per second
* @arg RTC_INT_PERIOD_PER_MINUTE: Interrupt per minute
* @arg RTC_INT_PERIOD_PER_HOUR: Interrupt per hour
* @arg RTC_INT_PERIOD_PER_DAY: Interrupt per day
* @arg RTC_INT_PERIOD_PER_MONTH: Interrupt per month
* @retval None
*/
void RTC_SetIntPeriod(uint8_t u8Period)
{
uint32_t u32RtcSta;
uint32_t u32IntSta;
/* Check parameters */
DDL_ASSERT(IS_RTC_INT_PERIOD(u8Period));
u32RtcSta = READ_REG32(bCM_RTC->CR1_b.START);
u32IntSta = READ_REG32(bCM_RTC->CR2_b.PRDIE);
/* Disable period interrupt when START=1 and clear period flag after write */
if ((0UL != u32IntSta) && (0UL != u32RtcSta)) {
WRITE_REG32(bCM_RTC->CR2_b.PRDIE, RESET);
}
/* RTC CR1 Configuration */
MODIFY_REG8(CM_RTC->CR1, RTC_CR1_PRDS, u8Period);
if ((0UL != u32IntSta) && (0UL != u32RtcSta)) {
WRITE_REG32(bCM_RTC->CR2_b.PRDIE, SET);
}
}
/**
* @brief Set the RTC clock source.
* @param [in] u8Src Specifies the clock source.
* This parameter can be one of the following values:
* @arg @ref RTC_Clock_Source
* @retval None
*/
void RTC_SetClockSrc(uint8_t u8Src)
{
/* Check parameters */
DDL_ASSERT(IS_RTC_CLK_SRC(u8Src));
MODIFY_REG8(CM_RTC->CR3, (RTC_CR3_LRCEN | RTC_CR3_RCKSEL), u8Src);
}
/**
* @brief Set RTC clock compensation value.
* @param [in] u16Value Specifies the clock compensation value of RTC.
* @arg This parameter can be a number between Min_Data = 0 and Max_Data = 0x1FF.
* @retval None
*/
void RTC_SetClockCompenValue(uint16_t u16Value)
{
/* Check parameters */
DDL_ASSERT(IS_RTC_COMPEN_VALUE(u16Value));
WRITE_REG32(bCM_RTC->ERRCRH_b.COMP8, ((uint32_t)u16Value >> 8U) & 0x01U);
WRITE_REG8(CM_RTC->ERRCRL, (uint8_t)(u16Value & 0x00FFU));
}
/**
* @brief Get RTC counter status.
* @param None
* @retval An @ref en_functional_state_t enumeration value.
* - ENABLE: RTC counter started
* - DISABLE: RTC counter stopped
*/
en_functional_state_t RTC_GetCounterState(void)
{
en_functional_state_t enState = DISABLE;
if (0UL != READ_REG32(bCM_RTC->CR1_b.START)) {
enState = ENABLE;
}
return enState;
}
/**
* @brief Enable or disable RTC count.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void RTC_Cmd(en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
WRITE_REG32(bCM_RTC->CR1_b.START, enNewState);
}
/**
* @brief Enable or disable RTC LRC function.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void RTC_LrcCmd(en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
WRITE_REG32(bCM_RTC->CR3_b.LRCEN, enNewState);
}
/**
* @brief Enable or disable RTC 1HZ output.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void RTC_OneHzOutputCmd(en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
WRITE_REG32(bCM_RTC->CR1_b.ONEHZOE, enNewState);
}
/**
* @brief Enable or disable clock compensation.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void RTC_ClockCompenCmd(en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
WRITE_REG32(bCM_RTC->ERRCRH_b.COMPEN, enNewState);
}
/**
* @brief Set RTC current date.
* @param [in] u8Format Specifies the format of the entered parameters.
* This parameter can be one of the following values:
* @arg RTC_DATA_FMT_DEC: Decimal data format
* @arg RTC_DATA_FMT_BCD: BCD data format
* @param [in] pstcRtcDate Pointer to a @ref stc_rtc_date_t structure
* @retval int32_t:
* - LL_OK: Set date success
* - LL_ERR: Set date failed
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t RTC_SetDate(uint8_t u8Format, stc_rtc_date_t *pstcRtcDate)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcRtcDate) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_RTC_DATA_FMT(u8Format));
if (RTC_DATA_FMT_DEC != u8Format) {
DDL_ASSERT(IS_RTC_YEAR(RTC_BCD2DEC(pstcRtcDate->u8Year)));
DDL_ASSERT(IS_RTC_MONTH(RTC_BCD2DEC(pstcRtcDate->u8Month)));
DDL_ASSERT(IS_RTC_DAY(RTC_BCD2DEC(pstcRtcDate->u8Day)));
} else {
DDL_ASSERT(IS_RTC_YEAR(pstcRtcDate->u8Year));
DDL_ASSERT(IS_RTC_MONTH(pstcRtcDate->u8Month));
DDL_ASSERT(IS_RTC_DAY(pstcRtcDate->u8Day));
}
DDL_ASSERT(IS_RTC_WEEKDAY(pstcRtcDate->u8Weekday));
/* Enter read/write mode */
if (LL_OK != RTC_EnterRwMode()) {
i32Ret = LL_ERR;
} else {
if (RTC_DATA_FMT_DEC == u8Format) {
pstcRtcDate->u8Year = RTC_DEC2BCD(pstcRtcDate->u8Year);
pstcRtcDate->u8Month = RTC_DEC2BCD(pstcRtcDate->u8Month);
pstcRtcDate->u8Day = RTC_DEC2BCD(pstcRtcDate->u8Day);
}
WRITE_REG8(CM_RTC->YEAR, pstcRtcDate->u8Year);
WRITE_REG8(CM_RTC->MON, pstcRtcDate->u8Month);
WRITE_REG8(CM_RTC->DAY, pstcRtcDate->u8Day);
WRITE_REG8(CM_RTC->WEEK, pstcRtcDate->u8Weekday);
/* Exit read/write mode */
if (LL_OK != RTC_ExitRwMode()) {
i32Ret = LL_ERR;
}
}
}
return i32Ret;
}
/**
* @brief Get RTC current date.
* @param [in] u8Format Specifies the format of the returned parameters.
* This parameter can be one of the following values:
* @arg RTC_DATA_FMT_DEC: Decimal data format
* @arg RTC_DATA_FMT_BCD: BCD data format
* @param [out] pstcRtcDate Pointer to a @ref stc_rtc_date_t structure
* @retval int32_t:
* - LL_OK: Get date success
* - LL_ERR: Get date failed
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t RTC_GetDate(uint8_t u8Format, stc_rtc_date_t *pstcRtcDate)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcRtcDate) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_RTC_DATA_FMT(u8Format));
/* Enter read/write mode */
if (LL_OK != RTC_EnterRwMode()) {
i32Ret = LL_ERR;
} else {
/* Get RTC date registers */
pstcRtcDate->u8Year = READ_REG8(CM_RTC->YEAR);
pstcRtcDate->u8Month = READ_REG8(CM_RTC->MON);
pstcRtcDate->u8Day = READ_REG8(CM_RTC->DAY);
pstcRtcDate->u8Weekday = READ_REG8(CM_RTC->WEEK);
/* Check decimal format*/
if (RTC_DATA_FMT_DEC == u8Format) {
pstcRtcDate->u8Year = RTC_BCD2DEC(pstcRtcDate->u8Year);
pstcRtcDate->u8Month = RTC_BCD2DEC(pstcRtcDate->u8Month);
pstcRtcDate->u8Day = RTC_BCD2DEC(pstcRtcDate->u8Day);
}
/* exit read/write mode */
if (LL_OK != RTC_ExitRwMode()) {
i32Ret = LL_ERR;
}
}
}
return i32Ret;
}
/**
* @brief Set RTC current time.
* @param [in] u8Format Specifies the format of the entered parameters.
* This parameter can be one of the following values:
* @arg RTC_DATA_FMT_DEC: Decimal data format
* @arg RTC_DATA_FMT_BCD: BCD data format
* @param [in] pstcRtcTime Pointer to a @ref stc_rtc_time_t structure
* @retval int32_t:
* - LL_OK: Set time success
* - LL_ERR: Set time failed
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t RTC_SetTime(uint8_t u8Format, stc_rtc_time_t *pstcRtcTime)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcRtcTime) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_RTC_DATA_FMT(u8Format));
if (RTC_DATA_FMT_DEC != u8Format) {
if (RTC_HOUR_FMT_12H == READ_REG32(bCM_RTC->CR1_b.AMPM)) {
DDL_ASSERT(IS_RTC_HOUR_12H(RTC_BCD2DEC(pstcRtcTime->u8Hour)));
DDL_ASSERT(IS_RTC_HOUR_12H_AM_PM(pstcRtcTime->u8AmPm));
} else {
DDL_ASSERT(IS_RTC_HOUR_24H(RTC_BCD2DEC(pstcRtcTime->u8Hour)));
}
DDL_ASSERT(IS_RTC_MINUTE(RTC_BCD2DEC(pstcRtcTime->u8Minute)));
DDL_ASSERT(IS_RTC_SEC(RTC_BCD2DEC(pstcRtcTime->u8Second)));
} else {
if (RTC_HOUR_FMT_12H == READ_REG32(bCM_RTC->CR1_b.AMPM)) {
DDL_ASSERT(IS_RTC_HOUR_12H(pstcRtcTime->u8Hour));
DDL_ASSERT(IS_RTC_HOUR_12H_AM_PM(pstcRtcTime->u8AmPm));
} else {
DDL_ASSERT(IS_RTC_HOUR_24H(pstcRtcTime->u8Hour));
}
DDL_ASSERT(IS_RTC_MINUTE(pstcRtcTime->u8Minute));
DDL_ASSERT(IS_RTC_SEC(pstcRtcTime->u8Second));
}
/* Enter read/write mode */
if (LL_OK != RTC_EnterRwMode()) {
i32Ret = LL_ERR;
} else {
if (RTC_DATA_FMT_DEC == u8Format) {
pstcRtcTime->u8Hour = RTC_DEC2BCD(pstcRtcTime->u8Hour);
pstcRtcTime->u8Minute = RTC_DEC2BCD(pstcRtcTime->u8Minute);
pstcRtcTime->u8Second = RTC_DEC2BCD(pstcRtcTime->u8Second);
}
if ((RTC_HOUR_FMT_12H == READ_REG32(bCM_RTC->CR1_b.AMPM)) &&
(RTC_HOUR_12H_PM == pstcRtcTime->u8AmPm)) {
SET_REG8_BIT(pstcRtcTime->u8Hour, RTC_HOUR_12H_PM);
}
WRITE_REG8(CM_RTC->HOUR, pstcRtcTime->u8Hour);
WRITE_REG8(CM_RTC->MIN, pstcRtcTime->u8Minute);
WRITE_REG8(CM_RTC->SEC, pstcRtcTime->u8Second);
/* Exit read/write mode */
if (LL_OK != RTC_ExitRwMode()) {
i32Ret = LL_ERR;
}
}
}
return i32Ret;
}
/**
* @brief Get RTC current time.
* @param [in] u8Format Specifies the format of the returned parameters.
* This parameter can be one of the following values:
* @arg RTC_DATA_FMT_DEC: Decimal data format
* @arg RTC_DATA_FMT_BCD: BCD data format
* @param [out] pstcRtcTime Pointer to a @ref stc_rtc_time_t structure
* @retval int32_t:
* - LL_OK: Get time success
* - LL_ERR: Get time failed
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t RTC_GetTime(uint8_t u8Format, stc_rtc_time_t *pstcRtcTime)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcRtcTime) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_RTC_DATA_FMT(u8Format));
/* Enter read/write mode */
if (LL_OK != RTC_EnterRwMode()) {
i32Ret = LL_ERR;
} else {
/* Get RTC time registers */
pstcRtcTime->u8Hour = READ_REG8(CM_RTC->HOUR);
pstcRtcTime->u8Minute = READ_REG8(CM_RTC->MIN);
pstcRtcTime->u8Second = READ_REG8(CM_RTC->SEC);
if (RTC_HOUR_FMT_12H == READ_REG32(bCM_RTC->CR1_b.AMPM)) {
if (RTC_HOUR_12H_PM == (pstcRtcTime->u8Hour & RTC_HOUR_12H_PM)) {
CLR_REG8_BIT(pstcRtcTime->u8Hour, RTC_HOUR_12H_PM);
pstcRtcTime->u8AmPm = RTC_HOUR_12H_PM;
} else {
pstcRtcTime->u8AmPm = RTC_HOUR_12H_AM;
}
} else {
pstcRtcTime->u8AmPm = RTC_HOUR_24H;
}
/* Check decimal format*/
if (RTC_DATA_FMT_DEC == u8Format) {
pstcRtcTime->u8Hour = RTC_BCD2DEC(pstcRtcTime->u8Hour);
pstcRtcTime->u8Minute = RTC_BCD2DEC(pstcRtcTime->u8Minute);
pstcRtcTime->u8Second = RTC_BCD2DEC(pstcRtcTime->u8Second);
}
/* exit read/write mode */
if (LL_OK != RTC_ExitRwMode()) {
i32Ret = LL_ERR;
}
}
}
return i32Ret;
}
/**
* @brief Set RTC alarm time.
* @param [in] u8Format Specifies the format of the entered parameters.
* This parameter can be one of the following values:
* @arg RTC_DATA_FMT_DEC: Decimal data format
* @arg RTC_DATA_FMT_BCD: BCD data format
* @param [in] pstcRtcAlarm Pointer to a @ref stc_rtc_alarm_t structure
* @retval int32_t:
* - LL_OK: Set RTC alarm time success
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t RTC_SetAlarm(uint8_t u8Format, stc_rtc_alarm_t *pstcRtcAlarm)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcRtcAlarm) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_RTC_DATA_FMT(u8Format));
if (RTC_DATA_FMT_DEC != u8Format) {
if (RTC_HOUR_FMT_12H == READ_REG32(bCM_RTC->CR1_b.AMPM)) {
DDL_ASSERT(IS_RTC_HOUR_12H(RTC_BCD2DEC(pstcRtcAlarm->u8AlarmHour)));
DDL_ASSERT(IS_RTC_HOUR_12H_AM_PM(pstcRtcAlarm->u8AlarmAmPm));
} else {
DDL_ASSERT(IS_RTC_HOUR_24H(RTC_BCD2DEC(pstcRtcAlarm->u8AlarmHour)));
}
DDL_ASSERT(IS_RTC_MINUTE(RTC_BCD2DEC(pstcRtcAlarm->u8AlarmMinute)));
} else {
if (RTC_HOUR_FMT_12H == READ_REG32(bCM_RTC->CR1_b.AMPM)) {
DDL_ASSERT(IS_RTC_HOUR_12H(pstcRtcAlarm->u8AlarmHour));
DDL_ASSERT(IS_RTC_HOUR_12H_AM_PM(pstcRtcAlarm->u8AlarmAmPm));
} else {
DDL_ASSERT(IS_RTC_HOUR_24H(pstcRtcAlarm->u8AlarmHour));
}
DDL_ASSERT(IS_RTC_MINUTE(pstcRtcAlarm->u8AlarmMinute));
}
DDL_ASSERT(IS_RTC_ALARM_WEEKDAY(pstcRtcAlarm->u8AlarmWeekday));
/* Configure alarm registers */
if (RTC_DATA_FMT_DEC == u8Format) {
pstcRtcAlarm->u8AlarmHour = RTC_DEC2BCD(pstcRtcAlarm->u8AlarmHour);
pstcRtcAlarm->u8AlarmMinute = RTC_DEC2BCD(pstcRtcAlarm->u8AlarmMinute);
}
if ((RTC_HOUR_FMT_12H == READ_REG32(bCM_RTC->CR1_b.AMPM)) &&
(RTC_HOUR_12H_PM == pstcRtcAlarm->u8AlarmAmPm)) {
SET_REG8_BIT(pstcRtcAlarm->u8AlarmHour, RTC_HOUR_12H_PM);
}
WRITE_REG8(CM_RTC->ALMHOUR, pstcRtcAlarm->u8AlarmHour);
WRITE_REG8(CM_RTC->ALMMIN, pstcRtcAlarm->u8AlarmMinute);
WRITE_REG8(CM_RTC->ALMWEEK, pstcRtcAlarm->u8AlarmWeekday);
}
return i32Ret;
}
/**
* @brief Get RTC alarm time.
* @param [in] u8Format Specifies the format of the returned parameters.
* This parameter can be one of the following values:
* @arg RTC_DATA_FMT_DEC: Decimal data format
* @arg RTC_DATA_FMT_BCD: BCD data format
* @param [out] pstcRtcAlarm Pointer to a @ref stc_rtc_alarm_t structure
* @retval int32_t:
* - LL_OK: Get RTC alarm time success
* - LL_ERR_INVD_PARAM: Invalid parameter
*/
int32_t RTC_GetAlarm(uint8_t u8Format, stc_rtc_alarm_t *pstcRtcAlarm)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcRtcAlarm) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_RTC_DATA_FMT(u8Format));
/* Get RTC date and time register */
pstcRtcAlarm->u8AlarmWeekday = READ_REG8(CM_RTC->ALMWEEK);
pstcRtcAlarm->u8AlarmMinute = READ_REG8(CM_RTC->ALMMIN);
pstcRtcAlarm->u8AlarmHour = READ_REG8(CM_RTC->ALMHOUR);
if (RTC_HOUR_FMT_12H == READ_REG32(bCM_RTC->CR1_b.AMPM)) {
if (RTC_HOUR_12H_PM == (pstcRtcAlarm->u8AlarmHour & RTC_HOUR_12H_PM)) {
CLR_REG8_BIT(pstcRtcAlarm->u8AlarmHour, RTC_HOUR_12H_PM);
pstcRtcAlarm->u8AlarmAmPm = RTC_HOUR_12H_PM;
} else {
pstcRtcAlarm->u8AlarmAmPm = RTC_HOUR_12H_AM;
}
} else {
pstcRtcAlarm->u8AlarmAmPm = RTC_HOUR_24H;
}
/* Check decimal format*/
if (RTC_DATA_FMT_DEC == u8Format) {
pstcRtcAlarm->u8AlarmHour = RTC_BCD2DEC(pstcRtcAlarm->u8AlarmHour);
pstcRtcAlarm->u8AlarmMinute = RTC_BCD2DEC(pstcRtcAlarm->u8AlarmMinute);
}
}
return i32Ret;
}
/**
* @brief Enable or disable RTC alarm.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void RTC_AlarmCmd(en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
WRITE_REG32(bCM_RTC->CR2_b.ALME, enNewState);
}
/**
* @brief Enable or disable specified RTC interrupt.
* @param [in] u32IntType Specifies the RTC interrupt source.
* This parameter can be one or any combination of the following values:
* @arg @ref RTC_Interrupt
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void RTC_IntCmd(uint32_t u32IntType, en_functional_state_t enNewState)
{
uint32_t u32IntTemp;
/* Check parameters */
DDL_ASSERT(IS_RTC_INT(u32IntType));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
u32IntTemp = u32IntType & 0x0000FFUL;
if (0UL != u32IntTemp) {
if (DISABLE != enNewState) {
SET_REG8_BIT(CM_RTC->CR2, u32IntTemp);
} else {
CLR_REG8_BIT(CM_RTC->CR2, u32IntTemp);
}
}
}
/**
* @brief Get RTC flag status.
* @param [in] u32Flag Specifies the RTC flag type.
* This parameter can be one or any combination of the following values:
* @arg @ref RTC_Flag
* @arg RTC_FLAG_ALL: All of the above
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t RTC_GetStatus(uint32_t u32Flag)
{
uint8_t u8FlagTemp;
en_flag_status_t enFlagSta = RESET;
/* Check parameters */
DDL_ASSERT(IS_RTC_GET_FLAG(u32Flag));
u8FlagTemp = (uint8_t)(u32Flag & 0xFFU);
if (0U != u8FlagTemp) {
if (0U != (READ_REG8_BIT(CM_RTC->CR2, u8FlagTemp))) {
enFlagSta = SET;
}
}
return enFlagSta;
}
/**
* @brief Clear RTC flag.
* @param [in] u32Flag Specifies the RTC flag type.
* This parameter can be one or any combination of the following values:
* @arg @ref RTC_Flag
* @arg RTC_FLAG_CLR_ALL: All of the above
* @retval None
*/
void RTC_ClearStatus(uint32_t u32Flag)
{
uint8_t u8FlagTemp;
/* Check parameters */
DDL_ASSERT(IS_RTC_CLR_FLAG(u32Flag));
u8FlagTemp = (uint8_t)(u32Flag & 0xFFU);
if (0U != u8FlagTemp) {
CLR_REG8_BIT(CM_RTC->CR1, RTC_CR1_ALMFCLR);
}
}
/**
* @}
*/
#endif /* LL_RTC_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
File diff suppressed because it is too large Load Diff
+994
View File
@@ -0,0 +1,994 @@
/**
*******************************************************************************
* @file hc32_ll_spi.c
* @brief This file provides firmware functions to manage the Serial Peripheral
* Interface(SPI).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2023-01-15 CDT Add frame level processing for API SPI_TxRx(),SPI_Tx()
2023-06-30 CDT Modify SPI_GetStatus,SPI_TxRx,SPI_Tx function
Add SPI_SetSckPolarity,SPI_SetSckPhase functions
Modify return type of fuction SPI_DeInit
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_spi.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_SPI SPI
* @brief Serial Peripheral Interface Driver Library
* @{
*/
#if (LL_SPI_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup SPI_Local_Macros SPI Local Macros
* @{
*/
#define SPI_CFG1_DEFAULT (0x00000010UL)
#define SPI_CFG2_DEFAULT (0x00000F1DUL)
#define SPI_SS0_VALID_CFG (0UL)
#define SPI_SS1_VALID_CFG (SPI_CFG2_SSA_0)
#define SPI_SS2_VALID_CFG (SPI_CFG2_SSA_1)
#define SPI_SS3_VALID_CFG (SPI_CFG2_SSA_0 | SPI_CFG2_SSA_1)
#define SPI_SR_DEFAULT (0x00000020UL)
/**
* @defgroup SPI_Check_Parameters_Validity SPI Check Parameters Validity
* @{
*/
/*! Parameter valid check for SPI peripheral */
#define IS_VALID_SPI_UNIT(x) \
( (CM_SPI1 == (x)) || \
(CM_SPI2 == (x)) || \
(CM_SPI3 == (x)) || \
(CM_SPI4 == (x)))
/*! Parameter valid check for SPI wire mode */
#define IS_SPI_WIRE_MD(x) \
( ((x) == SPI_4_WIRE) || \
((x) == SPI_3_WIRE))
/*! Parameter valid check for SPI transfer mode */
#define IS_SPI_TRANS_MD(x) \
( ((x) == SPI_FULL_DUPLEX) || \
((x) == SPI_SEND_ONLY))
/*! Parameter valid check for SPI master slave mode */
#define IS_SPI_MASTER_SLAVE(x) \
( ((x) == SPI_SLAVE) || \
((x) == SPI_MASTER))
/*! Parameter valid check for SPI loopback mode */
#define IS_SPI_SPLPBK(x) \
( ((x) == SPI_LOOPBACK_INVD) || \
((x) == SPI_LOOPBACK_MOSI_INVT) || \
((x) == SPI_LOOPBACK_MOSI))
/*! Parameter valid check for SPI communication suspend function status */
#define IS_SPI_SUSPD_MD_STD(x) \
( ((x) == SPI_COM_SUSP_FUNC_OFF) || \
((x) == SPI_COM_SUSP_FUNC_ON))
/*! Parameter valid check for SPI data frame level */
#define IS_SPI_DATA_FRAME(x) \
( ((x) == SPI_1_FRAME) || \
((x) == SPI_2_FRAME) || \
((x) == SPI_3_FRAME) || \
((x) == SPI_4_FRAME))
/*! Parameter valid check for SPI fault detect function status */
#define IS_SPI_MD_FAULT_DETECT_CMD(x) \
( ((x) == SPI_MD_FAULT_DETECT_DISABLE) || \
((x) == SPI_MD_FAULT_DETECT_ENABLE))
/*! Parameter valid check for SPI parity check mode */
#define IS_SPI_PARITY_CHECK(x) \
( ((x) == SPI_PARITY_INVD) || \
((x) == SPI_PARITY_EVEN) || \
((x) == SPI_PARITY_ODD))
/*! Parameter valid check for SPI interval time delay */
#define IS_SPI_INTERVAL_DELAY(x) \
( ((x) == SPI_INTERVAL_TIME_1SCK) || \
((x) == SPI_INTERVAL_TIME_2SCK) || \
((x) == SPI_INTERVAL_TIME_3SCK) || \
((x) == SPI_INTERVAL_TIME_4SCK) || \
((x) == SPI_INTERVAL_TIME_5SCK) || \
((x) == SPI_INTERVAL_TIME_6SCK) || \
((x) == SPI_INTERVAL_TIME_7SCK) || \
((x) == SPI_INTERVAL_TIME_8SCK))
/*! Parameter valid check for SPI release time delay */
#define IS_SPI_RELEASE_DELAY(x) \
( ((x) == SPI_RELEASE_TIME_1SCK) || \
((x) == SPI_RELEASE_TIME_2SCK) || \
((x) == SPI_RELEASE_TIME_3SCK) || \
((x) == SPI_RELEASE_TIME_4SCK) || \
((x) == SPI_RELEASE_TIME_5SCK) || \
((x) == SPI_RELEASE_TIME_6SCK) || \
((x) == SPI_RELEASE_TIME_7SCK) || \
((x) == SPI_RELEASE_TIME_8SCK))
/*! Parameter valid check for SPI Setup time delay delay */
#define IS_SPI_SETUP_DELAY(x) \
( ((x) == SPI_SETUP_TIME_1SCK) || \
((x) == SPI_SETUP_TIME_2SCK) || \
((x) == SPI_SETUP_TIME_3SCK) || \
((x) == SPI_SETUP_TIME_4SCK) || \
((x) == SPI_SETUP_TIME_5SCK) || \
((x) == SPI_SETUP_TIME_6SCK) || \
((x) == SPI_SETUP_TIME_7SCK) || \
((x) == SPI_SETUP_TIME_8SCK))
/*! Parameter valid check for SPI read data register target buffer */
#define IS_SPI_RD_TARGET_BUFF(x) \
( ((x) == SPI_RD_TARGET_RD_BUF) || \
((x) == SPI_RD_TARGET_WR_BUF))
/*! Parameter valid check for SPI mode */
#define IS_SPI_SPI_MD(x) \
( ((x) == SPI_MD_0) || \
((x) == SPI_MD_1) || \
((x) == SPI_MD_2) || \
((x) == SPI_MD_3))
/*! Parameter valid check for SPI SCK Polarity */
#define IS_SPI_SCK_POLARITY(x) \
( ((x) == SPI_SCK_POLARITY_LOW) || \
((x) == SPI_SCK_POLARITY_HIGH))
/*! Parameter valid check for SPI SCK Phase */
#define IS_SPI_SCK_PHASE(x) \
( ((x) == SPI_SCK_PHASE_ODD_EDGE_SAMPLE) || \
((x) == SPI_SCK_PHASE_EVEN_EDGE_SAMPLE))
/*! Parameter valid check for SPI SS signal */
#define IS_SPI_SS_PIN(x) \
( ((x) == SPI_PIN_SS0) || \
((x) == SPI_PIN_SS1) || \
((x) == SPI_PIN_SS2) || \
((x) == SPI_PIN_SS3))
/*! Parameter valid check for SPI baudrate prescaler */
#define IS_SPI_BIT_RATE_DIV(x) \
( ((x) == SPI_BR_CLK_DIV2) || \
((x) == SPI_BR_CLK_DIV4) || \
((x) == SPI_BR_CLK_DIV8) || \
((x) == SPI_BR_CLK_DIV16) || \
((x) == SPI_BR_CLK_DIV32) || \
((x) == SPI_BR_CLK_DIV64) || \
((x) == SPI_BR_CLK_DIV128) || \
((x) == SPI_BR_CLK_DIV256))
/*! Parameter valid check for SPI data bits */
#define IS_SPI_DATA_SIZE(x) \
( ((x) == SPI_DATA_SIZE_4BIT) || \
((x) == SPI_DATA_SIZE_5BIT) || \
((x) == SPI_DATA_SIZE_6BIT) || \
((x) == SPI_DATA_SIZE_7BIT) || \
((x) == SPI_DATA_SIZE_8BIT) || \
((x) == SPI_DATA_SIZE_9BIT) || \
((x) == SPI_DATA_SIZE_10BIT) || \
((x) == SPI_DATA_SIZE_11BIT) || \
((x) == SPI_DATA_SIZE_12BIT) || \
((x) == SPI_DATA_SIZE_13BIT) || \
((x) == SPI_DATA_SIZE_14BIT) || \
((x) == SPI_DATA_SIZE_15BIT) || \
((x) == SPI_DATA_SIZE_16BIT) || \
((x) == SPI_DATA_SIZE_20BIT) || \
((x) == SPI_DATA_SIZE_24BIT) || \
((x) == SPI_DATA_SIZE_32BIT))
/*! Parameter valid check for SPI LSB MSB mode */
#define IS_SPI_FIRST_BIT(x) \
( ((x) == SPI_FIRST_MSB) || \
((x) == SPI_FIRST_LSB))
/*! Parameter valid check for SPI Communication mode */
#define IS_SPI_COMM_MD(x) \
( ((x) == SPI_COMM_MD_NORMAL) || \
((x) == SPI_COMM_MD_CONTINUE))
/*! Parameter valid check for interrupt flag */
#define IS_SPI_INT(x) \
( ((x) != 0UL) && \
(((x) | SPI_IRQ_ALL) == SPI_IRQ_ALL))
/*! Parameter valid check for SPI status flag */
#define IS_SPI_STD_FLAG(x) \
( ((x) != 0UL) && \
(((x) | SPI_FLAG_ALL) == SPI_FLAG_ALL))
/*! Parameter valid check for SPI status flag for clear */
#define IS_SPI_CLR_STD_FLAG(x) \
( ((x) != 0UL) && \
(((x) | SPI_FLAG_CLR_ALL) == SPI_FLAG_CLR_ALL))
/*! Parameter valid check for SPI command*/
#define IS_SPI_CMD_ALLOWED(x) \
( (READ_REG32_BIT(SPIx->SR, SPI_FLAG_MD_FAULT) == 0UL) || \
((x) == DISABLE))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup SPI_Local_Func SPI Local Functions
* @{
*/
/**
* @brief SPI check status.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] u32FlagMask Bit mask of status flag.
* @param [in] u32Value Valid value of the status.
* @param [in] u32Timeout Timeout value.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_TIMEOUT: SPI transmit timeout.
*/
static int32_t SPI_WaitStatus(const CM_SPI_TypeDef *SPIx, uint32_t u32FlagMask, uint32_t u32Value, uint32_t u32Timeout)
{
int32_t i32Ret = LL_OK;
while (READ_REG32_BIT(SPIx->SR, u32FlagMask) != u32Value) {
if (u32Timeout == 0UL) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
u32Timeout--;
}
return i32Ret;
}
/**
* @brief SPI transmit and receive data in full duplex mode.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] pvTxBuf The pointer to the buffer which contains the data to be sent.
* @param [out] pvRxBuf The pointer to the buffer which the received data will be stored.
* @param [in] u32Len The length of the data in byte or half word.
* @param [in] u32Timeout Timeout value.
* @retval int32_t:
* - LL_OK: No errors occurred
* - LL_ERR_TIMEOUT: SPI transmit and receive timeout.
*/
static int32_t SPI_TxRx(CM_SPI_TypeDef *SPIx, const void *pvTxBuf, void *pvRxBuf, uint32_t u32Len, uint32_t u32Timeout)
{
uint32_t u32BitSize;
__IO uint32_t u32TxCnt = 0U, u32RxCnt = 0U;
__IO uint32_t u32Count = 0U;
int32_t i32Ret = LL_OK;
uint32_t u32Tmp;
__UNUSED __IO uint32_t u32Read;
__IO uint32_t u32FrameCnt;
uint32_t u32FrameNum = READ_REG32_BIT(SPIx->CFG1, SPI_CFG1_FTHLV) + 1UL;
DDL_ASSERT(0UL == (u32Len % u32FrameNum));
/* Get data bit size, SPI_DATA_SIZE_4BIT ~ SPI_DATA_SIZE_32BIT */
u32BitSize = READ_REG32_BIT(SPIx->CFG2, SPI_CFG2_DSIZE);
while (u32RxCnt < u32Len) {
/* Tx data */
if (u32TxCnt < u32Len) {
/* Wait TX buffer empty. */
i32Ret = SPI_WaitStatus(SPIx, SPI_FLAG_TX_BUF_EMPTY, SPI_FLAG_TX_BUF_EMPTY, 0U);
if (i32Ret == LL_OK) {
if (pvTxBuf != NULL) {
u32FrameCnt = 0UL;
while (u32FrameCnt < u32FrameNum) {
if (u32BitSize <= SPI_DATA_SIZE_8BIT) {
/* SPI_DATA_SIZE_4BIT ~ SPI_DATA_SIZE_8BIT */
WRITE_REG32(SPIx->DR, ((const uint8_t *)pvTxBuf)[u32TxCnt]);
} else if (u32BitSize <= SPI_DATA_SIZE_16BIT) {
/* SPI_DATA_SIZE_9BIT ~ SPI_DATA_SIZE_16BIT */
WRITE_REG32(SPIx->DR, ((const uint16_t *)pvTxBuf)[u32TxCnt]);
} else {
/* SPI_DATA_SIZE_20BIT ~ SPI_DATA_SIZE_32BIT */
WRITE_REG32(SPIx->DR, ((const uint32_t *)pvTxBuf)[u32TxCnt]);
}
u32FrameCnt++;
u32TxCnt++;
}
} else {
u32FrameCnt = 0UL;
while (u32FrameCnt < u32FrameNum) {
WRITE_REG32(SPIx->DR, 0xFFFFFFFFUL);
u32FrameCnt++;
u32TxCnt++;
}
}
}
}
/* RX data */
i32Ret = SPI_WaitStatus(SPIx, SPI_FLAG_RX_BUF_FULL, SPI_FLAG_RX_BUF_FULL, 0U);
if (i32Ret == LL_OK) {
if (pvRxBuf != NULL) {
u32FrameCnt = 0UL;
while (u32FrameCnt < u32FrameNum) {
u32Tmp = READ_REG32(SPIx->DR);
if (u32BitSize <= SPI_DATA_SIZE_8BIT) {
/* SPI_DATA_SIZE_4BIT ~ SPI_DATA_SIZE_8BIT */
((uint8_t *)pvRxBuf)[u32RxCnt] = (uint8_t)u32Tmp;
} else if (u32BitSize <= SPI_DATA_SIZE_16BIT) {
/* SPI_DATA_SIZE_9BIT ~ SPI_DATA_SIZE_16BIT */
((uint16_t *)pvRxBuf)[u32RxCnt] = (uint16_t)u32Tmp;
} else {
/* SPI_DATA_SIZE_20BIT ~ SPI_DATA_SIZE_32BIT */
((uint32_t *)pvRxBuf)[u32RxCnt] = (uint32_t)u32Tmp;
}
u32FrameCnt++;
u32RxCnt++;
}
} else {
/* Dummy read */
u32FrameCnt = 0UL;
while (u32FrameCnt < u32FrameNum) {
u32Read = READ_REG32(SPIx->DR);
u32FrameCnt++;
u32RxCnt++;
}
}
}
/* check timeout */
if (u32Count > u32Timeout) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
u32Count++;
}
if ((SPI_CR1_MSTR == READ_REG32_BIT(SPIx->CR1, SPI_CR1_MSTR)) && (i32Ret == LL_OK)) {
i32Ret = SPI_WaitStatus(SPIx, SPI_FLAG_IDLE, 0UL, u32Timeout);
}
return i32Ret;
}
/**
* @brief SPI send data only.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] pvTxBuf The pointer to the buffer which contains the data to be sent.
* @param [in] u32Len The length of the data in byte or half word or word.
* @param [in] u32Timeout Timeout value.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_TIMEOUT: SPI transmit timeout.
*/
static int32_t SPI_Tx(CM_SPI_TypeDef *SPIx, const void *pvTxBuf, uint32_t u32Len, uint32_t u32Timeout)
{
__IO uint32_t u32TxCnt = 0U;
uint32_t u32BitSize;
int32_t i32Ret = LL_OK;
__IO uint32_t u32FrameCnt;
uint32_t u32FrameNum = READ_REG32_BIT(SPIx->CFG1, SPI_CFG1_FTHLV) + 1UL;
DDL_ASSERT(0UL == (u32Len % u32FrameNum));
/* Get data bit size, SPI_DATA_SIZE_4BIT ~ SPI_DATA_SIZE_32BIT */
u32BitSize = READ_REG32_BIT(SPIx->CFG2, SPI_CFG2_DSIZE);
while (u32TxCnt < u32Len) {
u32FrameCnt = 0UL;
while (u32FrameCnt < u32FrameNum) {
if (u32BitSize <= SPI_DATA_SIZE_8BIT) {
/* SPI_DATA_SIZE_4BIT ~ SPI_DATA_SIZE_8BIT */
WRITE_REG32(SPIx->DR, ((const uint8_t *)pvTxBuf)[u32TxCnt]);
} else if (u32BitSize <= SPI_DATA_SIZE_16BIT) {
/* SPI_DATA_SIZE_9BIT ~ SPI_DATA_SIZE_16BIT */
WRITE_REG32(SPIx->DR, ((const uint16_t *)pvTxBuf)[u32TxCnt]);
} else {
/* SPI_DATA_SIZE_20BIT ~ SPI_DATA_SIZE_32BIT */
WRITE_REG32(SPIx->DR, ((const uint32_t *)pvTxBuf)[u32TxCnt]);
}
u32FrameCnt++;
u32TxCnt++;
}
/* Wait TX buffer empty. */
i32Ret = SPI_WaitStatus(SPIx, SPI_FLAG_TX_BUF_EMPTY, SPI_FLAG_TX_BUF_EMPTY, u32Timeout);
if (i32Ret != LL_OK) {
break;
}
}
if ((SPI_CR1_MSTR == READ_REG32_BIT(SPIx->CR1, SPI_CR1_MSTR)) && (i32Ret == LL_OK)) {
i32Ret = SPI_WaitStatus(SPIx, SPI_FLAG_IDLE, 0UL, u32Timeout);
}
return i32Ret;
}
/**
* @}
*/
/**
* @defgroup SPI_Global_Functions SPI Global Functions
* @{
*/
/**
* @brief Initializes the SPI peripheral according to the specified parameters
* in the structure stc_spi_init.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] pstcSpiInit Pointer to a stc_spi_init_t structure that contains
* the configuration information for the SPI.
* @retval int32_t:
* - LL_OK: No errors occurred
* - LL_ERR_INVD_PARAM: pstcSpiInit == NULL or configuration parameter error.
*/
int32_t SPI_Init(CM_SPI_TypeDef *SPIx, const stc_spi_init_t *pstcSpiInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
if (NULL != pstcSpiInit) {
DDL_ASSERT(IS_SPI_WIRE_MD(pstcSpiInit->u32WireMode));
DDL_ASSERT(IS_SPI_TRANS_MD(pstcSpiInit->u32TransMode));
DDL_ASSERT(IS_SPI_MASTER_SLAVE(pstcSpiInit->u32MasterSlave));
DDL_ASSERT(IS_SPI_MD_FAULT_DETECT_CMD(pstcSpiInit->u32ModeFaultDetect));
DDL_ASSERT(IS_SPI_PARITY_CHECK(pstcSpiInit->u32Parity));
DDL_ASSERT(IS_SPI_SPI_MD(pstcSpiInit->u32SpiMode));
DDL_ASSERT(IS_SPI_BIT_RATE_DIV(pstcSpiInit->u32BaudRatePrescaler));
DDL_ASSERT(IS_SPI_DATA_SIZE(pstcSpiInit->u32DataBits));
DDL_ASSERT(IS_SPI_FIRST_BIT(pstcSpiInit->u32FirstBit));
DDL_ASSERT(IS_SPI_SUSPD_MD_STD(pstcSpiInit->u32SuspendMode));
DDL_ASSERT(IS_SPI_DATA_FRAME(pstcSpiInit->u32FrameLevel));
/* Configuration parameter check */
if ((SPI_MASTER == pstcSpiInit->u32MasterSlave) && (SPI_MD_FAULT_DETECT_ENABLE == pstcSpiInit->u32ModeFaultDetect)) {
/* pstcSpiInit->u32ModeFaultDetect can not be SPI_MD_FAULT_DETECT_ENABLE in master mode */
} else if ((SPI_3_WIRE == pstcSpiInit->u32WireMode) && (SPI_SLAVE == pstcSpiInit->u32MasterSlave)
&& ((SPI_MD_0 == pstcSpiInit->u32SpiMode) || (SPI_MD_2 == pstcSpiInit->u32SpiMode))) {
/* SPI_3_WIRE can not support SPI_MD_0 and SPI_MD_2 */
} else {
WRITE_REG32(SPIx->CR1, pstcSpiInit->u32WireMode | pstcSpiInit->u32TransMode | pstcSpiInit->u32MasterSlave
| pstcSpiInit->u32SuspendMode | pstcSpiInit->u32ModeFaultDetect | pstcSpiInit->u32Parity);
MODIFY_REG32(SPIx->CFG1, SPI_CFG1_FTHLV, pstcSpiInit->u32FrameLevel);
WRITE_REG32(SPIx->CFG2, pstcSpiInit->u32SpiMode | pstcSpiInit->u32BaudRatePrescaler | pstcSpiInit->u32DataBits
| pstcSpiInit->u32FirstBit);
i32Ret = LL_OK;
}
}
return i32Ret;
}
/**
* @brief De-initializes the SPI peripheral.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @retval int32_t:
* - LL_OK: No error occurred.
*/
int32_t SPI_DeInit(CM_SPI_TypeDef *SPIx)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
WRITE_REG32(SPIx->CR1, 0UL);
WRITE_REG32(SPIx->CFG1, SPI_CFG1_DEFAULT);
WRITE_REG32(SPIx->CFG2, SPI_CFG2_DEFAULT);
CLR_REG32_BIT(SPIx->SR, SPI_FLAG_CLR_ALL);
return LL_OK;
}
/**
* @brief Set a default value for the SPI initialization structure.
* @param [in] pstcSpiInit Pointer to a stc_spi_init_t structure that
* contains configuration information.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_INVD_PARAM: pstcSpiInit == NULL.
*/
int32_t SPI_StructInit(stc_spi_init_t *pstcSpiInit)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (NULL != pstcSpiInit) {
pstcSpiInit->u32WireMode = SPI_4_WIRE;
pstcSpiInit->u32TransMode = SPI_FULL_DUPLEX;
pstcSpiInit->u32MasterSlave = SPI_MASTER;
pstcSpiInit->u32ModeFaultDetect = SPI_MD_FAULT_DETECT_DISABLE;
pstcSpiInit->u32Parity = SPI_PARITY_INVD;
pstcSpiInit->u32SpiMode = SPI_MD_0;
pstcSpiInit->u32BaudRatePrescaler = SPI_BR_CLK_DIV8;
pstcSpiInit->u32DataBits = SPI_DATA_SIZE_8BIT;
pstcSpiInit->u32FirstBit = SPI_FIRST_MSB;
pstcSpiInit->u32SuspendMode = SPI_COM_SUSP_FUNC_OFF;
pstcSpiInit->u32FrameLevel = SPI_1_FRAME;
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief Enable or disable SPI interrupt.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] u32IntType SPI interrupt type. Can be one or any
* combination of the parameter @ref SPI_Int_Type_Define
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void SPI_IntCmd(CM_SPI_TypeDef *SPIx, uint32_t u32IntType, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
DDL_ASSERT(IS_SPI_INT(u32IntType));
if (enNewState == ENABLE) {
SET_REG32_BIT(SPIx->CR1, u32IntType);
} else {
CLR_REG32_BIT(SPIx->CR1, u32IntType);
}
}
/**
* @brief SPI function enable or disable.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void SPI_Cmd(CM_SPI_TypeDef *SPIx, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
DDL_ASSERT(IS_SPI_CMD_ALLOWED(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(SPIx->CR1, SPI_CR1_SPE);
} else {
CLR_REG32_BIT(SPIx->CR1, SPI_CR1_SPE);
}
}
/**
* @brief Write SPI data register.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] u32Data The data will be written to the data register.
* @retval None.
*/
void SPI_WriteData(CM_SPI_TypeDef *SPIx, uint32_t u32Data)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
WRITE_REG32(SPIx->DR, u32Data);
}
/**
* @brief Read SPI data register.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @retval uint32_t A 32-bit data of SPI data register.
*/
uint32_t SPI_ReadData(const CM_SPI_TypeDef *SPIx)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
return READ_REG32(SPIx->DR);
}
/**
* @brief SPI get status flag.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] u32Flag SPI state flag. Can be one or any
* combination of the parameter of @ref SPI_State_Flag_Define
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t SPI_GetStatus(const CM_SPI_TypeDef *SPIx, uint32_t u32Flag)
{
en_flag_status_t enFlag = RESET;
uint32_t u32Status;
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
DDL_ASSERT(IS_SPI_STD_FLAG(u32Flag));
u32Status = READ_REG32(SPIx->SR);
if (SPI_FLAG_IDLE == (SPI_FLAG_IDLE & u32Flag)) {
CLR_REG32_BIT(u32Flag, SPI_FLAG_IDLE);
if (0U == (u32Status & SPI_FLAG_IDLE)) {
enFlag = SET;
}
}
if (0U != READ_REG32_BIT(u32Status, u32Flag)) {
enFlag = SET;
}
return enFlag;
}
/**
* @brief SPI clear state flag.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] u32Flag SPI state flag. Can be one or any combination of the parameter below
* @arg SPI_FLAG_OVERLOAD
* @arg SPI_FLAG_MD_FAULT
* @arg SPI_FLAG_PARITY_ERR
* @arg SPI_FLAG_UNDERLOAD
* @retval None
*/
void SPI_ClearStatus(CM_SPI_TypeDef *SPIx, uint32_t u32Flag)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
DDL_ASSERT(IS_SPI_CLR_STD_FLAG(u32Flag));
CLR_REG32_BIT(SPIx->SR, u32Flag);
}
/**
* @brief SPI loopback function configuration.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] u32Mode Loopback mode. Can be one parameter @ref SPI_Loopback_Selection_Define
* @retval None
*/
void SPI_LoopbackModeConfig(CM_SPI_TypeDef *SPIx, uint32_t u32Mode)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
DDL_ASSERT(IS_SPI_SPLPBK(u32Mode));
MODIFY_REG32(SPIx->CR1, SPI_CR1_SPLPBK | SPI_CR1_SPLPBK2, u32Mode);
}
/**
* @brief SPI parity check error self diagnosis function enable or disable.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void SPI_ParityCheckCmd(CM_SPI_TypeDef *SPIx, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(SPIx->CR1, SPI_CR1_PATE);
} else {
CLR_REG32_BIT(SPIx->CR1, SPI_CR1_PATE);
}
}
/**
* @brief SPI signals delay time configuration
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] pstcDelayConfig Pointer to a stc_spi_delay_t structure that contains
* the configuration information for the SPI delay time.
* @retval int32_t:
* - LL_OK: No errors occurred
* - LL_ERR_INVD_PARAM: pstcDelayConfig == NULL
*/
int32_t SPI_DelayTimeConfig(CM_SPI_TypeDef *SPIx, const stc_spi_delay_t *pstcDelayConfig)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
if (NULL != pstcDelayConfig) {
DDL_ASSERT(IS_SPI_INTERVAL_DELAY(pstcDelayConfig->u32IntervalDelay));
DDL_ASSERT(IS_SPI_RELEASE_DELAY(pstcDelayConfig->u32ReleaseDelay));
DDL_ASSERT(IS_SPI_SETUP_DELAY(pstcDelayConfig->u32SetupDelay));
/* Interval delay */
if (SPI_INTERVAL_TIME_1SCK == pstcDelayConfig->u32IntervalDelay) {
CLR_REG32_BIT(SPIx->CFG2, SPI_CFG2_MIDIE);
CLR_REG32_BIT(SPIx->CFG1, SPI_CFG1_MIDI);
} else {
MODIFY_REG32(SPIx->CFG1, SPI_CFG1_MIDI, pstcDelayConfig->u32IntervalDelay);
SET_REG32_BIT(SPIx->CFG2, SPI_CFG2_MIDIE);
}
/* SCK release delay */
if (SPI_RELEASE_TIME_1SCK == pstcDelayConfig->u32ReleaseDelay) {
CLR_REG32_BIT(SPIx->CFG2, SPI_CFG2_MSSDLE);
CLR_REG32_BIT(SPIx->CFG1, SPI_CFG1_MSSDL);
} else {
SET_REG32_BIT(SPIx->CFG2, SPI_CFG2_MSSDLE);
MODIFY_REG32(SPIx->CFG1, SPI_CFG1_MSSDL, pstcDelayConfig->u32ReleaseDelay);
}
/* Setup delay */
if (SPI_SETUP_TIME_1SCK == pstcDelayConfig->u32SetupDelay) {
CLR_REG32_BIT(SPIx->CFG2, SPI_CFG2_MSSIE);
CLR_REG32_BIT(SPIx->CFG1, SPI_CFG1_MSSI);
} else {
SET_REG32_BIT(SPIx->CFG2, SPI_CFG2_MSSIE);
MODIFY_REG32(SPIx->CFG1, SPI_CFG1_MSSI, pstcDelayConfig->u32SetupDelay);
}
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief Set a default value for the SPI delay time configuration structure.
* @param [in] pstcDelayConfig Pointer to a stc_spi_delay_t structure that
* contains configuration information.
* @retval int32_t:
* - LL_OK: No errors occurred.
* - LL_ERR_INVD_PARAM: pstcDelayConfig == NULL.
*/
int32_t SPI_DelayStructInit(stc_spi_delay_t *pstcDelayConfig)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (NULL != pstcDelayConfig) {
pstcDelayConfig->u32IntervalDelay = SPI_INTERVAL_TIME_1SCK;
pstcDelayConfig->u32ReleaseDelay = SPI_RELEASE_TIME_1SCK;
pstcDelayConfig->u32SetupDelay = SPI_SETUP_TIME_1SCK;
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @brief SPI SS signal valid level configuration
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] u32SSPin Specify the SS pin @ref SPI_SS_Pin_Define
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void SPI_SSValidLevelConfig(CM_SPI_TypeDef *SPIx, uint32_t u32SSPin, en_functional_state_t enNewState)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
DDL_ASSERT(IS_SPI_SS_PIN(u32SSPin));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(SPIx->CFG1, u32SSPin);
} else {
CLR_REG32_BIT(SPIx->CFG1, u32SSPin);
}
}
/**
* @brief Set the SPI SCK polarity.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] u32Polarity Specify the SPI SCK polarity @ref SPI_SCK_Polarity_Define
* @retval None
*/
void SPI_SetSckPolarity(CM_SPI_TypeDef *SPIx, uint32_t u32Polarity)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
DDL_ASSERT(IS_SPI_SCK_POLARITY(u32Polarity));
if (SPI_SCK_POLARITY_LOW == u32Polarity) {
CLR_REG32_BIT(SPIx->CFG2, SPI_CFG2_CPOL);
} else {
SET_REG32_BIT(SPIx->CFG2, SPI_CFG2_CPOL);
}
}
/**
* @brief Set the SPI SCK phase.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] u32Phase Specify the SPI SCK phase @ref SPI_SCK_Phase_Define
* @retval None
*/
void SPI_SetSckPhase(CM_SPI_TypeDef *SPIx, uint32_t u32Phase)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
DDL_ASSERT(IS_SPI_SCK_PHASE(u32Phase));
if (SPI_SCK_PHASE_ODD_EDGE_SAMPLE == u32Phase) {
CLR_REG32_BIT(SPIx->CFG2, SPI_CFG2_CPHA);
} else {
SET_REG32_BIT(SPIx->CFG2, SPI_CFG2_CPHA);
}
}
/**
* @brief SPI valid SS signal configuration
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] u32SSPin Specify the SS pin @ref SPI_SS_Pin_Define
* @retval None
*/
void SPI_SSPinSelect(CM_SPI_TypeDef *SPIx, uint32_t u32SSPin)
{
uint32_t u32RegConfig;
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
DDL_ASSERT(IS_SPI_SS_PIN(u32SSPin));
switch (u32SSPin) {
case SPI_PIN_SS0:
u32RegConfig = SPI_SS0_VALID_CFG;
break;
case SPI_PIN_SS1:
u32RegConfig = SPI_SS1_VALID_CFG;
break;
case SPI_PIN_SS2:
u32RegConfig = SPI_SS2_VALID_CFG;
break;
case SPI_PIN_SS3:
u32RegConfig = SPI_SS3_VALID_CFG;
break;
default:
u32RegConfig = SPI_SS0_VALID_CFG;
break;
}
MODIFY_REG32(SPIx->CFG2, SPI_CFG2_SSA, u32RegConfig);
}
/**
* @brief SPI read buffer configuration
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] u32ReadBuf Target buffer for read operation @ref SPI_Read_Target_Buf_Define
* @retval None
*/
void SPI_ReadBufConfig(CM_SPI_TypeDef *SPIx, uint32_t u32ReadBuf)
{
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
DDL_ASSERT(IS_SPI_RD_TARGET_BUFF(u32ReadBuf));
MODIFY_REG32(SPIx->CFG1, SPI_CFG1_SPRDTD, u32ReadBuf);
}
/**
* @brief SPI transmit data.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] pvTxBuf The pointer to the buffer which contains the data to be sent.
* @param [in] u32TxLen The length of the data to be sent.
* @param [in] u32Timeout Timeout value.
* @retval int32_t:
* - LL_OK: No errors occurred
* - LL_ERR_TIMEOUT: SPI transmit timeout.
* - LL_ERR_INVD_PARAM: pvTxBuf == NULL or u32TxLen == 0U
* @note -No SS pin active and inactive operation in 3-wire mode. Add operations of SS pin depending on your application.
* -In the send only slave mode, the function needs to increase an appropriate delay after calling to ensure the
* integrity of data transmission.
*/
int32_t SPI_Trans(CM_SPI_TypeDef *SPIx, const void *pvTxBuf, uint32_t u32TxLen, uint32_t u32Timeout)
{
uint32_t u32Flags;
int32_t i32Ret = LL_ERR_INVD_PARAM;
if ((pvTxBuf != NULL) && (u32TxLen != 0U)) {
u32Flags = READ_REG32_BIT(SPIx->CR1, SPI_CR1_TXMDS);
if (u32Flags == SPI_SEND_ONLY) {
/* Transmit data in send only mode. */
i32Ret = SPI_Tx(SPIx, pvTxBuf, u32TxLen, u32Timeout);
} else {
/* Transmit data in full duplex mode. */
i32Ret = SPI_TxRx(SPIx, pvTxBuf, NULL, u32TxLen, u32Timeout);
}
}
return i32Ret;
}
/**
* @brief SPI receive data.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] pvRxBuf The pointer to the buffer which the received data to be stored.
* @param [in] u32RxLen The length of the data to be received.
* @param [in] u32Timeout Timeout value.
* @retval int32_t:
* - LL_OK: No errors occurred
* - LL_ERR_TIMEOUT: SPI receive timeout.
* - LL_ERR_INVD_PARAM: pvRxBuf == NULL or u32RxLen == 0U
* @note -No SS pin active and inactive operation in 3-wire mode. Add operations of SS pin depending on your application.
*/
int32_t SPI_Receive(CM_SPI_TypeDef *SPIx, void *pvRxBuf, uint32_t u32RxLen, uint32_t u32Timeout)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if ((pvRxBuf != NULL) && (u32RxLen != 0U)) {
/* Receives data in full duplex master mode. */
i32Ret = SPI_TxRx(SPIx, NULL, pvRxBuf, u32RxLen, u32Timeout);
}
return i32Ret;
}
/**
* @brief SPI transmit and receive data.
* @param [in] SPIx SPI unit
* @arg CM_SPIx or CM_SPI
* @param [in] pvTxBuf The pointer to the buffer which contains the data to be sent.
* If this pointer is NULL and the pvRxBuf is NOT NULL, the MOSI output high
* and the the received data will be stored in the buffer pointed by pvRxBuf.
* @param [out] pvRxBuf The pointer to the buffer which the received data will be stored.
* This for full duplex transfer.
* @param [in] u32Len The length of the data(in byte or half word) to be sent and received.
* @param [in] u32Timeout Timeout value.
* @retval int32_t:
* - LL_OK: No errors occurred
* - LL_ERR_TIMEOUT: SPI transmit and receive timeout.
* - LL_ERR_INVD_PARAM: pvRxBuf == NULL or pvRxBuf == NULL or u32Len == 0U
* @note SPI receives data while sending data.
*/
int32_t SPI_TransReceive(CM_SPI_TypeDef *SPIx, const void *pvTxBuf, void *pvRxBuf, uint32_t u32Len, uint32_t u32Timeout)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if ((pvTxBuf != NULL) && (pvRxBuf != NULL) && (u32Len != 0U)) {
/* Transmit and receive data in full duplex master mode. */
i32Ret = SPI_TxRx(SPIx, pvTxBuf, pvRxBuf, u32Len, u32Timeout);
}
return i32Ret;
}
/**
* @}
*/
#endif /* LL_SPI_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+302
View File
@@ -0,0 +1,302 @@
/**
*******************************************************************************
* @file hc32_ll_sram.c
* @brief This file provides firmware functions to manage the SRAM.
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2022-10-31 CDT Deleted redundant comments
2023-06-30 CDT API fixed: SRAM_ClearStatus()
2023-09-30 CDT API fixed: SRAM_SetWaitCycle()
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_sram.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_SRAM SRAM
* @brief SRAM Driver Library
* @{
*/
#if (LL_SRAM_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup SRAM_Local_Macros SRAM Local Macros
* @{
*/
/**
* @defgroup SRAM_Configuration_Bits_Mask SRAM Configuration Bits Mask
* @{
*/
#define SRAM_ECC_MD_MASK (SRAMC_CKCR_ECCMOD)
#define SRAM_CYCLE_MASK (0x00000007UL)
/**
* @}
*/
/**
* @defgroup SRAM_Check_Parameters_Validity SRAM check parameters validity
* @{
*/
#define IS_SRAM_BIT_MASK(x, mask) (((x) != 0U) && (((x) | (mask)) == (mask)))
#define IS_SRAM_ERR_MD(x) (((x) == SRAM_ERR_MD_NMI) || ((x) == SRAM_ERR_MD_RST))
#define IS_SRAM_WAIT_CYCLE(x) ((x) <= SRAM_WAIT_CYCLE7)
#define IS_SRAM_SEL(x) IS_SRAM_BIT_MASK(x, SRAM_SRAM_ALL)
#define IS_SRAM_ECC_SRAM(x) ((x) == SRAM_ECC_SRAM3)
#define IS_SRAM_FLAG(x) IS_SRAM_BIT_MASK(x, SRAM_FLAG_ALL)
#define IS_SRAM_WTPR_UNLOCK() (CM_SRAMC->WTPR == SRAM_REG_UNLOCK_KEY)
#define IS_SRAM_CKPR_UNLOCK() (CM_SRAMC->CKPR == SRAM_REG_UNLOCK_KEY)
#define IS_SRAM_ECC_MD(x) \
( ((x) == SRAM_ECC_MD_INVD) || \
((x) == SRAM_ECC_MD1) || \
((x) == SRAM_ECC_MD2) || \
((x) == SRAM_ECC_MD3))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup SRAM_Global_Functions SRAM Global Functions
* @{
*/
/**
* @brief Initializes SRAM.
* @param None
* @retval None
*/
void SRAM_Init(void)
{
SET_REG32_BIT(CM_SRAMC->CKSR, SRAM_FLAG_ALL);
}
/**
* @brief De-initializes SRAM. RESET the registers of SRAM.
* @param None
* @retval None
* @note Call SRAM_REG_Unlock to unlock registers WTCR and CKCR first.
*/
void SRAM_DeInit(void)
{
/* Call SRAM_REG_Unlock to unlock register WTCR and CKCR. */
DDL_ASSERT(IS_SRAM_WTPR_UNLOCK());
DDL_ASSERT(IS_SRAM_CKPR_UNLOCK());
WRITE_REG32(CM_SRAMC->WTCR, 0U);
WRITE_REG32(CM_SRAMC->CKCR, 0U);
SET_REG32_BIT(CM_SRAMC->CKSR, SRAM_FLAG_ALL);
}
/**
* @brief Specifies access wait cycle for SRAM.
* @param [in] u32SramSel The SRAM selection.
* This parameter can be values of @ref SRAM_Sel
* @param [in] u32WriteCycle The write access wait cycle for the specified SRAM
* This parameter can be a value of @ref SRAM_Access_Wait_Cycle
* @param [in] u32ReadCycle The read access wait cycle for the specified SRAM.
* This parameter can be a value of @ref SRAM_Access_Wait_Cycle
* @arg SRAM_WAIT_CYCLE0: Wait 0 CPU cycle.
* @arg SRAM_WAIT_CYCLE1: Wait 1 CPU cycle.
* @arg SRAM_WAIT_CYCLE2: Wait 2 CPU cycles.
* @arg SRAM_WAIT_CYCLE3: Wait 3 CPU cycles.
* @arg SRAM_WAIT_CYCLE4: Wait 4 CPU cycles.
* @arg SRAM_WAIT_CYCLE5: Wait 5 CPU cycles.
* @arg SRAM_WAIT_CYCLE6: Wait 6 CPU cycles.
* @arg SRAM_WAIT_CYCLE7: Wait 7 CPU cycles.
* @retval None
* @note Call SRAM_REG_Unlock to unlock register WTCR first.
*/
void SRAM_SetWaitCycle(uint32_t u32SramSel, uint32_t u32WriteCycle, uint32_t u32ReadCycle)
{
uint8_t i = 0U;
uint8_t u8OfsWt;
uint8_t u8OfsRd;
DDL_ASSERT(IS_SRAM_SEL(u32SramSel));
DDL_ASSERT(IS_SRAM_WAIT_CYCLE(u32WriteCycle));
DDL_ASSERT(IS_SRAM_WAIT_CYCLE(u32ReadCycle));
DDL_ASSERT(IS_SRAM_WTPR_UNLOCK());
while (u32SramSel != 0UL) {
if ((u32SramSel & 0x1UL) != 0UL) {
u8OfsRd = i * 8U;
u8OfsWt = u8OfsRd + 4U;
MODIFY_REG32(CM_SRAMC->WTCR,
((SRAM_CYCLE_MASK << u8OfsWt) | (SRAM_CYCLE_MASK << u8OfsRd)),
((u32WriteCycle << u8OfsWt) | (u32ReadCycle << u8OfsRd)));
}
u32SramSel >>= 1U;
i++;
}
}
/**
* @brief Specifies ECC mode.
* @param [in] u32SramSel The SRAM selection. This function is used to specify the
* ECC mode for members SRAM_ECC_XXXX of @ref SRAM_Sel
* @param [in] u32EccMode The ECC mode.
* This parameter can be a value of @ref SRAM_ECC_Mode
* @arg SRAM_ECC_MD_INVD: The ECC mode is invalid.
* @arg SRAM_ECC_MD1: When 1-bit error occurred:
* ECC error corrects.
* No 1-bit-error status flag setting, no interrupt or reset.
* When 2-bit error occurred:
* ECC error detects.
* 2-bit-error status flag sets and interrupt or reset occurred.
* @arg SRAM_ECC_MD2: When 1-bit error occurred:
* ECC error corrects.
* 1-bit-error status flag sets, no interrupt or reset.
* When 2-bit error occurred:
* ECC error detects.
* 2-bit-error status flag sets and interrupt or reset occurred.
* @arg SRAM_ECC_MD3: When 1-bit error occurred:
* ECC error corrects.
* 1-bit-error status flag sets and interrupt or reset occurred.
* When 2-bit error occurred:
* ECC error detects.
* 2-bit-error status flag sets and interrupt or reset occurred.
* @retval None
* @note Call SRAM_REG_Unlock to unlock register CKCR first.
*/
void SRAM_SetEccMode(uint32_t u32SramSel, uint32_t u32EccMode)
{
DDL_ASSERT(IS_SRAM_ECC_SRAM(u32SramSel));
DDL_ASSERT(IS_SRAM_ECC_MD(u32EccMode));
DDL_ASSERT(IS_SRAM_CKPR_UNLOCK());
if ((u32SramSel & SRAM_SRAM3) != 0U) {
MODIFY_REG32(CM_SRAMC->CKCR, SRAM_ECC_MD_MASK, u32EccMode);
}
}
/**
* @brief Specifies the operation which is operated after check error occurred.
* @param [in] u32SramSel The SRAM selection.
* This parameter can be values of @ref SRAM_Sel
* @param [out] u32ErrMode The operation after check error occurred.
* This parameter can be a value of @ref SRAM_Err_Mode
* @arg SRAM_ERR_MD_NMI: Check error generates NMI(non-maskable interrupt).
* @arg SRAM_ERR_MD_RST: Check error generates system reset.
* @retval None
* @note Call SRAM_REG_Unlock to unlock register CKCR first.
*/
void SRAM_SetErrorMode(uint32_t u32SramSel, uint32_t u32ErrMode)
{
DDL_ASSERT(IS_SRAM_SEL(u32SramSel));
DDL_ASSERT(IS_SRAM_ERR_MD(u32ErrMode));
DDL_ASSERT(IS_SRAM_CKPR_UNLOCK());
if ((u32SramSel & (SRAM_SRAM12 | SRAM_SRAMR | SRAM_SRAMH)) != 0U) {
WRITE_REG32(bCM_SRAMC->CKCR_b.PYOAD, u32ErrMode);
}
if ((u32SramSel & SRAM_SRAM3) != 0U) {
WRITE_REG32(bCM_SRAMC->CKCR_b.ECCOAD, u32ErrMode);
}
}
/**
* @brief Get the status of the specified flag of SRAM.
* @param [in] u32Flag The flag of SRAM.
* This parameter can be a value of @ref SRAM_Err_Status_Flag
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t SRAM_GetStatus(uint32_t u32Flag)
{
en_flag_status_t enStatus = RESET;
DDL_ASSERT(IS_SRAM_FLAG(u32Flag));
if (READ_REG32_BIT(CM_SRAMC->CKSR, u32Flag) != 0U) {
enStatus = SET;
}
return enStatus;
}
/**
* @brief Clear the status of the specified flag of SRAM.
* @param [in] u32Flag The flag of SRAM.
* This parameter can be values of @ref SRAM_Err_Status_Flag
* @retval None
*/
void SRAM_ClearStatus(uint32_t u32Flag)
{
DDL_ASSERT(IS_SRAM_FLAG(u32Flag));
WRITE_REG32(CM_SRAMC->CKSR, u32Flag);
}
/**
* @}
*/
#endif /* LL_SRAM_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+182
View File
@@ -0,0 +1,182 @@
/**
*******************************************************************************
* @file hc32_ll_swdt.c
* @brief This file provides firmware functions to manage the Specialized Watch
* Dog Timer(SWDT).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2023-09-30 CDT Optimize SWDT_ClearStatus function timeout
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_swdt.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_SWDT SWDT
* @brief Specialized Watch Dog Timer
* @{
*/
#if (LL_SWDT_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup SWDT_Local_Macros SWDT Local Macros
* @{
*/
/* SWDT Refresh Key */
#define SWDT_REFRESH_KEY_START (0x0123UL)
#define SWDT_REFRESH_KEY_END (0x3210UL)
/* SWDT clear flag timeout(ms) */
#define SWDT_CLR_FLAG_TIMEOUT (400UL)
/**
* @defgroup SWDT_Check_Parameters_Validity SWDT Check Parameters Validity
* @{
*/
#define IS_SWDT_FLAG(x) \
( ((x) != 0UL) && \
(((x) | SWDT_FLAG_ALL) == SWDT_FLAG_ALL))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @addtogroup SWDT_Global_Functions
* @{
*/
/**
* @brief SWDT feed dog.
* @note In software startup mode, Start counter when refreshing for the first time.
* @param None
* @retval None
*/
void SWDT_FeedDog(void)
{
WRITE_REG32(CM_SWDT->RR, SWDT_REFRESH_KEY_START);
WRITE_REG32(CM_SWDT->RR, SWDT_REFRESH_KEY_END);
}
/**
* @brief Get SWDT flag status.
* @param [in] u32Flag SWDT flag type
* This parameter can be one or any combination of the following values:
* @arg SWDT_FLAG_UDF: Count underflow flag
* @arg SWDT_FLAG_REFRESH: Refresh error flag
* @arg SWDT_FLAG_ALL: All of the above
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t SWDT_GetStatus(uint32_t u32Flag)
{
en_flag_status_t enFlagSta = RESET;
/* Check parameters */
DDL_ASSERT(IS_SWDT_FLAG(u32Flag));
if (0UL != (READ_REG32_BIT(CM_SWDT->SR, u32Flag))) {
enFlagSta = SET;
}
return enFlagSta;
}
/**
* @brief Clear SWDT flag.
* @param [in] u32Flag SWDT flag type
* This parameter can be one or any combination of the following values:
* @arg SWDT_FLAG_UDF: Count underflow flag
* @arg SWDT_FLAG_REFRESH: Refresh error flag
* @arg SWDT_FLAG_ALL: All of the above
* @retval int32_t:
* - LL_OK: Clear flag success
* - LL_ERR_TIMEOUT: Clear flag timeout
*/
int32_t SWDT_ClearStatus(uint32_t u32Flag)
{
__IO uint32_t u32Count;
int32_t i32Ret = LL_OK;
/* Check parameters */
DDL_ASSERT(IS_SWDT_FLAG(u32Flag));
/* Waiting for FLAG bit clear */
u32Count = SWDT_CLR_FLAG_TIMEOUT * (HCLK_VALUE / 25000UL);
while (0UL != READ_REG32_BIT(CM_SWDT->SR, u32Flag)) {
CLR_REG32_BIT(CM_SWDT->SR, u32Flag);
if (0UL == u32Count) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
u32Count--;
}
return i32Ret;
}
/**
* @}
*/
#endif /* LL_SWDT_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
+625
View File
@@ -0,0 +1,625 @@
/**
*******************************************************************************
* @file hc32_ll_tmr0.c
* @brief This file provides firmware functions to manage the TMR0
* (TMR0).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_tmr0.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_TMR0 TMR0
* @brief TMR0 Driver Library
* @{
*/
#if (LL_TMR0_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup TMR0_Local_Macros TMR0 Local Macros
* @{
*/
/* Max channel number */
#define TMR0_CH_MAX (2UL)
#define TMR0_CLK_SRC_MASK (TMR0_BCONR_SYNSA | TMR0_BCONR_SYNCLKA | TMR0_BCONR_ASYNCLKA)
#define TMR0_BCONR_CLR_MASK (TMR0_BCONR_CAPMDA | TMR0_BCONR_CKDIVA | TMR0_BCONR_HICPA | TMR0_CLK_SRC_MASK)
/**
* @defgroup TMR0_Register_Address TMR0 Register Address
* @{
*/
#define TMR0_CNTR_ADDR(__UNIT__, __CH__) (__IO uint32_t*)((uint32_t)(&((__UNIT__)->CNTAR)) + ((__CH__) << 2UL))
#define TMR0_CMPR_ADDR(__UNIT__, __CH__) (__IO uint32_t*)((uint32_t)(&((__UNIT__)->CMPAR)) + ((__CH__) << 2UL))
/**
* @}
*/
#define TMR0_CH_OFFSET(__CH__) ((__CH__) << 4U)
/**
* @defgroup TMR0_Check_Parameters_Validity TMR0 Check Parameters Validity
* @{
*/
#define IS_TMR0_UNIT(x) \
( ((x) == CM_TMR0_1) || \
((x) == CM_TMR0_2))
#define IS_TMR0_CH(x) \
( ((x) == TMR0_CH_A) || \
((x) == TMR0_CH_B))
#define IS_TMR0_CLK_SRC(x) \
( ((x) == TMR0_CLK_SRC_INTERN_CLK) || \
((x) == TMR0_CLK_SRC_SPEC_EVT) || \
((x) == TMR0_CLK_SRC_LRC) || \
((x) == TMR0_CLK_SRC_XTAL32))
#define IS_TMR0_CLK_DIV(x) \
( ((x) == TMR0_CLK_DIV1) || \
((x) == TMR0_CLK_DIV2) || \
((x) == TMR0_CLK_DIV4) || \
((x) == TMR0_CLK_DIV8) || \
((x) == TMR0_CLK_DIV16) || \
((x) == TMR0_CLK_DIV32) || \
((x) == TMR0_CLK_DIV64) || \
((x) == TMR0_CLK_DIV128) || \
((x) == TMR0_CLK_DIV256) || \
((x) == TMR0_CLK_DIV512) || \
((x) == TMR0_CLK_DIV1024))
#define IS_TMR0_FUNC(x) \
( ((x) == TMR0_FUNC_CMP) || \
((x) == TMR0_FUNC_CAPT))
#define IS_TMR0_INT(x) \
( ((x) != 0U) && \
(((x) | TMR0_INT_ALL) == TMR0_INT_ALL))
#define IS_TMR0_FLAG(x) \
( ((x) != 0U) && \
(((x) | TMR0_FLAG_ALL) == TMR0_FLAG_ALL))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup TMR0_Global_Functions TMR0 Global Functions
* @{
*/
/**
* @brief De-Initialize TMR0 function
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @retval None
*/
void TMR0_DeInit(CM_TMR0_TypeDef *TMR0x)
{
uint32_t u32Ch;
__IO uint32_t *CNTR;
__IO uint32_t *CMPR;
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
WRITE_REG32(TMR0x->BCONR, 0UL);
WRITE_REG32(TMR0x->STFLR, 0UL);
for (u32Ch = 0UL; u32Ch < TMR0_CH_MAX; u32Ch++) {
CNTR = TMR0_CNTR_ADDR(TMR0x, u32Ch);
WRITE_REG32(*CNTR, 0UL);
CMPR = TMR0_CMPR_ADDR(TMR0x, u32Ch);
WRITE_REG32(*CMPR, 0x0000FFFFUL);
}
}
/**
* @brief Initialize TMR0 function.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @param [in] pstcTmr0Init Pointer to a @ref stc_tmr0_init_t.
* @retval int32_t:
* - LL_OK: Initialize success
* - LL_ERR_INVD_PARAM: pstcTmr0Init is NULL
*/
int32_t TMR0_Init(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch, const stc_tmr0_init_t *pstcTmr0Init)
{
__IO uint32_t *CNTR;
__IO uint32_t *CMPR;
int32_t i32Ret = LL_OK;
if (NULL == pstcTmr0Init) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
DDL_ASSERT(IS_TMR0_CLK_SRC(pstcTmr0Init->u32ClockSrc));
DDL_ASSERT(IS_TMR0_CLK_DIV(pstcTmr0Init->u32ClockDiv));
DDL_ASSERT(IS_TMR0_FUNC(pstcTmr0Init->u32Func));
CNTR = TMR0_CNTR_ADDR(TMR0x, u32Ch);
WRITE_REG32(*CNTR, 0UL);
CMPR = TMR0_CMPR_ADDR(TMR0x, u32Ch);
WRITE_REG32(*CMPR, pstcTmr0Init->u16CompareValue);
MODIFY_REG32(TMR0x->BCONR, (TMR0_BCONR_CLR_MASK << TMR0_CH_OFFSET(u32Ch)),
((pstcTmr0Init->u32ClockSrc | pstcTmr0Init->u32ClockDiv |
pstcTmr0Init->u32Func) << TMR0_CH_OFFSET(u32Ch)));
}
return i32Ret;
}
/**
* @brief Set the fields of structure stc_tmr0_init_t to default values.
* @param [out] pstcTmr0Init Pointer to a @ref stc_tmr0_init_t structure.
* @retval int32_t:
* - LL_OK: Initialize success
* - LL_ERR_INVD_PARAM: pstcTmr0Init is NULL
*/
int32_t TMR0_StructInit(stc_tmr0_init_t *pstcTmr0Init)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcTmr0Init) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
pstcTmr0Init->u32ClockSrc = TMR0_CLK_SRC_INTERN_CLK;
pstcTmr0Init->u32ClockDiv = TMR0_CLK_DIV1;
pstcTmr0Init->u32Func = TMR0_FUNC_CMP;
pstcTmr0Init->u16CompareValue = 0xFFFFU;
}
return i32Ret;
}
/**
* @brief Start TMR0.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @retval None
*/
void TMR0_Start(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch)
{
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
SET_REG32_BIT(TMR0x->BCONR, (TMR0_BCONR_CSTA << TMR0_CH_OFFSET(u32Ch)));
}
/**
* @brief Stop TMR0.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @retval None
*/
void TMR0_Stop(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch)
{
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
CLR_REG32_BIT(TMR0x->BCONR, (TMR0_BCONR_CSTA << TMR0_CH_OFFSET(u32Ch)));
}
/**
* @brief Set Tmr0 counter value.
* @note Setting the count requires stop tmr0.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @param [in] u16Value The data to write to the counter register
* @retval None
*/
void TMR0_SetCountValue(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch, uint16_t u16Value)
{
__IO uint32_t *CNTR;
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
CNTR = TMR0_CNTR_ADDR(TMR0x, u32Ch);
WRITE_REG32(*CNTR, u16Value);
}
/**
* @brief Get Tmr0 counter value.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @retval uint16_t The counter register data
*/
uint16_t TMR0_GetCountValue(const CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch)
{
__IO uint32_t *CNTR;
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
CNTR = TMR0_CNTR_ADDR(TMR0x, u32Ch);
return (uint16_t)READ_REG32(*CNTR);
}
/**
* @brief Set Tmr0 compare value.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @param [in] u16Value The data to write to the compare register
* @retval None
*/
void TMR0_SetCompareValue(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch, uint16_t u16Value)
{
__IO uint32_t *CMPR;
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
CMPR = TMR0_CMPR_ADDR(TMR0x, u32Ch);
WRITE_REG32(*CMPR, u16Value);
}
/**
* @brief Get Tmr0 compare value.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @retval The compare register data
*/
uint16_t TMR0_GetCompareValue(const CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch)
{
__IO uint32_t *CMPR;
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
CMPR = TMR0_CMPR_ADDR(TMR0x, u32Ch);
return (uint16_t)READ_REG32(*CMPR);
}
/**
* @brief Set clock source.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @param [in] u32Src Specifies the clock source
* This parameter can be a value of the following:
* @arg @ref TMR0_Clock_Source
* @retval None
*/
void TMR0_SetClockSrc(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch, uint32_t u32Src)
{
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
DDL_ASSERT(IS_TMR0_CLK_SRC(u32Src));
MODIFY_REG32(TMR0x->BCONR, (TMR0_CLK_SRC_MASK << TMR0_CH_OFFSET(u32Ch)), (u32Src << TMR0_CH_OFFSET(u32Ch)));
}
/**
* @brief Set the division of clock.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @param [in] u32Div Specifies the clock source division
* This parameter can be a value of the following:
* @arg TMR0_CLK_DIV1: Clock source / 1
* @arg TMR0_CLK_DIV2: Clock source / 2
* @arg TMR0_CLK_DIV4: Clock source / 4
* @arg TMR0_CLK_DIV8: Clock source / 8
* @arg TMR0_CLK_DIV16: Clock source / 16
* @arg TMR0_CLK_DIV32: Clock source / 32
* @arg TMR0_CLK_DIV64: Clock source / 64
* @arg TMR0_CLK_DIV128: Clock source / 128
* @arg TMR0_CLK_DIV256: Clock source / 256
* @arg TMR0_CLK_DIV512: Clock source / 512
* @arg TMR0_CLK_DIV1024: Clock source / 1024
* @retval None.
*/
void TMR0_SetClockDiv(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch, uint32_t u32Div)
{
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
DDL_ASSERT(IS_TMR0_CLK_DIV(u32Div));
MODIFY_REG32(TMR0x->BCONR, (TMR0_BCONR_CKDIVA << TMR0_CH_OFFSET(u32Ch)), (u32Div << TMR0_CH_OFFSET(u32Ch)));
}
/**
* @brief Set Tmr0 Function.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @param [in] u32Func Select TMR0 function
* This parameter can be a value of the following:
* @arg TMR0_FUNC_CMP: Select the Compare function
* @arg TMR0_FUNC_CAPT: Select the Capture function
* @retval None
*/
void TMR0_SetFunc(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch, uint32_t u32Func)
{
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
DDL_ASSERT(IS_TMR0_FUNC(u32Func));
MODIFY_REG32(TMR0x->BCONR, ((TMR0_BCONR_CAPMDA | TMR0_BCONR_HICPA) << TMR0_CH_OFFSET(u32Ch)),
(u32Func << TMR0_CH_OFFSET(u32Ch)));
}
/**
* @brief Enable or disable HardWare trigger capture function.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void TMR0_HWCaptureCondCmd(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(TMR0x->BCONR, (TMR0_BCONR_HICPA << TMR0_CH_OFFSET(u32Ch)));
} else {
CLR_REG32_BIT(TMR0x->BCONR, (TMR0_BCONR_HICPA << TMR0_CH_OFFSET(u32Ch)));
}
}
/**
* @brief Enable or disable HardWare trigger start function.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void TMR0_HWStartCondCmd(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(TMR0x->BCONR, (TMR0_BCONR_HSTAA << TMR0_CH_OFFSET(u32Ch)));
} else {
CLR_REG32_BIT(TMR0x->BCONR, (TMR0_BCONR_HSTAA << TMR0_CH_OFFSET(u32Ch)));
}
}
/**
* @brief Enable or disable HardWare trigger stop function.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void TMR0_HWStopCondCmd(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(TMR0x->BCONR, (TMR0_BCONR_HSTPA << TMR0_CH_OFFSET(u32Ch)));
} else {
CLR_REG32_BIT(TMR0x->BCONR, (TMR0_BCONR_HSTPA << TMR0_CH_OFFSET(u32Ch)));
}
}
/**
* @brief Enable or disable HardWare trigger clear function.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Ch TMR0 channel
* This parameter can be one of the following values:
* @arg @ref TMR0_Channel
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void TMR0_HWClearCondCmd(CM_TMR0_TypeDef *TMR0x, uint32_t u32Ch, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_CH(u32Ch));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(TMR0x->BCONR, (TMR0_BCONR_HCLEA << TMR0_CH_OFFSET(u32Ch)));
} else {
CLR_REG32_BIT(TMR0x->BCONR, (TMR0_BCONR_HCLEA << TMR0_CH_OFFSET(u32Ch)));
}
}
/**
* @brief Enable or disable specified Tmr0 interrupt.
* @note The comparison matching interrupt of channel 'TMR0_INT_CMP_A' in unit 'CM_TMR0_1' is only available in asynchronous counting mode.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32IntType TMR0 interrupt type
* This parameter can be any combination value of the following values:
* @arg @ref TMR0_Interrupt.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void TMR0_IntCmd(CM_TMR0_TypeDef *TMR0x, uint32_t u32IntType, en_functional_state_t enNewState)
{
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_INT(u32IntType));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (DISABLE != enNewState) {
SET_REG32_BIT(TMR0x->BCONR, u32IntType);
} else {
CLR_REG32_BIT(TMR0x->BCONR, u32IntType);
}
}
/**
* @brief Get Tmr0 status.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Flag TMR0 flag type
* This parameter can be any combination value of the following values:
* @arg @ref TMR0_FLAG
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t TMR0_GetStatus(const CM_TMR0_TypeDef *TMR0x, uint32_t u32Flag)
{
en_flag_status_t enFlagSta = RESET;
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_FLAG(u32Flag));
if (0UL != (READ_REG32_BIT(TMR0x->STFLR, u32Flag))) {
enFlagSta = SET;
}
return enFlagSta;
}
/**
* @brief Clear Tmr0 status.
* @param [in] TMR0x Pointer to TMR0 unit instance
* This parameter can be one of the following values:
* @arg CM_TMR0 or CM_TMR0_x: TMR0 unit instance
* @param [in] u32Flag TMR0 flag type
* This parameter can be any combination value of the following values:
* @arg @ref TMR0_FLAG
* @retval None
*/
void TMR0_ClearStatus(CM_TMR0_TypeDef *TMR0x, uint32_t u32Flag)
{
/* Check parameters */
DDL_ASSERT(IS_TMR0_UNIT(TMR0x));
DDL_ASSERT(IS_TMR0_FLAG(u32Flag));
CLR_REG32_BIT(TMR0x->STFLR, u32Flag);
}
/**
* @}
*/
#endif /* LL_TMR0_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+262
View File
@@ -0,0 +1,262 @@
/**
*******************************************************************************
* @file hc32_ll_trng.c
* @brief This file provides firmware functions to manage the True Random
* Number Generator(TRNG).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2022-10-31 CDT API fixed: TRNG_Init()
2023-06-30 CDT API fixed: rewrite TRNG_GenerateRandom() to Support get multiple random data
API optimized for better random numbers: TRNG_GenerateRandom(), TRNG_GetRandom()
Add TRNG_Cmd,TRNG_DeInit functions and optimize TRNG_Start function
2023-09-30 CDT Optimize the processing of discarded data and enable TRNG in TRNG_Init()
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_trng.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_TRNG TRNG
* @brief TRNG Driver Library
* @{
*/
#if (LL_TRNG_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup TRNG_Local_Macros TRNG Local Macros
* @{
*/
#define TRNG_TIMEOUT (20000UL)
/**
* @defgroup TRNG_Check_Parameters_Validity TRNG Check Parameters Validity
* @{
*/
#define IS_TRNG_SHIFT_CNT(x) \
( ((x) == TRNG_SHIFT_CNT32) || \
((x) == TRNG_SHIFT_CNT64) || \
((x) == TRNG_SHIFT_CNT128) || \
((x) == TRNG_SHIFT_CNT256))
#define IS_RNG_RELOAD_INIT_VAL_EN(x) \
( ((x) == TRNG_RELOAD_INIT_VAL_ENABLE) || \
((x) == TRNG_RELOAD_INIT_VAL_DISABLE))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup TRNG_Global_Functions TRNG Global Functions
* @{
*/
/**
* @brief De-initializes TRNG.
* @param None
* @retval int32_t:
* - LL_OK: No error occurred.
* - LL_ERR_TIMEOUT: Works timeout.
*/
int32_t TRNG_DeInit(void)
{
int32_t i32Ret = LL_ERR_TIMEOUT;
__IO uint32_t u32TimeCount = TRNG_TIMEOUT;
/* Wait generating done */
while (u32TimeCount-- != 0UL) {
if (READ_REG32(bCM_TRNG->CR_b.RUN) == 0U) {
i32Ret = LL_OK;
break;
}
}
if (i32Ret == LL_OK) {
WRITE_REG32(CM_TRNG->CR, 0UL);
WRITE_REG32(CM_TRNG->MR, 0x00000012UL);
}
return i32Ret;
}
/**
* @brief Initializes TRNG.
* @param [in] u32ShiftCount TRNG shift control. This parameter can be a value of @ref TRNG_Shift_Ctrl
* @arg TRNG_SHIFT_CNT32: Shift 32 times when capturing random noise.
* @arg TRNG_SHIFT_CNT64: Shift 64 times when capturing random noise.
* @arg TRNG_SHIFT_CNT128: Shift 128 times when capturing random noise.
* @arg TRNG_SHIFT_CNT256: Shift 256 times when capturing random noise.
* @param [in] u32ReloadInitValueEn Enable or disable load new initial value.
* This parameter can be a value of @ref TRNG_Reload_Init_Value
* @arg TRNG_RELOAD_INIT_VAL_ENABLE: Enable load new initial value.
* @arg TRNG_RELOAD_INIT_VAL_DISABLE: Disable load new initial value.
* @retval None
*/
void TRNG_Init(uint32_t u32ShiftCount, uint32_t u32ReloadInitValueEn)
{
uint32_t au32Random[20U];
DDL_ASSERT(IS_TRNG_SHIFT_CNT(u32ShiftCount));
DDL_ASSERT(IS_RNG_RELOAD_INIT_VAL_EN(u32ReloadInitValueEn));
WRITE_REG32(CM_TRNG->MR, u32ShiftCount | u32ReloadInitValueEn);
/* Enable TRNG */
SET_REG32_BIT(CM_TRNG->CR, TRNG_CR_EN);
/* Discard the first 10 generated data (64bit), 20 for 32bit variable storage */
(void)TRNG_GenerateRandom(au32Random, 20U);
}
/**
* @brief Start TRNG and get random number.
* @param [out] pu32Random The destination buffer to store the random number.
* @param [in] u32RandomLen The size(in word) of the destination buffer.
* @retval int32_t:
* - LL_OK: No error occurred.
* - LL_ERR_TIMEOUT: Works timeout.
* - LL_ERR_INVD_PARAM: pu32Random == NULL or u8RandomLen == 0
*/
int32_t TRNG_GenerateRandom(uint32_t *pu32Random, uint32_t u32RandomLen)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
__IO uint32_t u32TimeCount = TRNG_TIMEOUT;
uint32_t u32Count = 0U;
if ((pu32Random != NULL) && (u32RandomLen > 0U)) {
while (u32RandomLen != u32Count) {
/* Start TRNG */
WRITE_REG32(bCM_TRNG->CR_b.RUN, 1U);
/* Wait generating done. */
i32Ret = LL_ERR_TIMEOUT;
while (u32TimeCount-- != 0UL) {
if (READ_REG32(bCM_TRNG->CR_b.RUN) == 0U) {
i32Ret = LL_OK;
break;
}
}
if (i32Ret == LL_OK) {
/* Get the random number. */
/* XOR with 0x55555555 for better random number */
pu32Random[u32Count++] = READ_REG32(CM_TRNG->DR0) ^ 0x55555555UL;
if (u32Count < u32RandomLen) {
pu32Random[u32Count++] = READ_REG32(CM_TRNG->DR1) ^ 0x55555555UL;
}
}
}
}
return i32Ret;
}
/**
* @brief Start TRNG
* @param None
* @retval None
*/
void TRNG_Start(void)
{
WRITE_REG32(bCM_TRNG->CR_b.RUN, 1U);
}
/**
* @brief TRNG function enable or disable.
* @param [in] enNewState An @ref en_functional_state_t enumeration value.
* @retval None
*/
void TRNG_Cmd(en_functional_state_t enNewState)
{
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
if (ENABLE == enNewState) {
SET_REG32_BIT(CM_TRNG->CR, TRNG_CR_EN);
} else {
CLR_REG32_BIT(CM_TRNG->CR, TRNG_CR_EN);
}
}
/**
* @brief Get random number.
* @param [out] pu32Random The destination buffer to store the random number.
* @param [in] u8RandomLen The size(in word) of the destination buffer.(MAX = 2U)
* @retval int32_t:
* - LL_OK: No error occurred.
* - LL_ERR_INVD_PARAM: pu32Random == NULL or u8RandomLen == 0
*/
int32_t TRNG_GetRandom(uint32_t *pu32Random, uint8_t u8RandomLen)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if ((pu32Random != NULL) && (u8RandomLen > 0U)) {
/* Get the random number. */
/* XOR with 0x55555555 for better random number */
pu32Random[0U] = READ_REG32(CM_TRNG->DR0) ^ 0x55555555UL;
if (u8RandomLen > 1U) {
pu32Random[1U] = READ_REG32(CM_TRNG->DR1) ^ 0x55555555UL;
}
i32Ret = LL_OK;
}
return i32Ret;
}
/**
* @}
*/
#endif /* LL_TRNG_ENABLE */
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+440
View File
@@ -0,0 +1,440 @@
/**
*******************************************************************************
* @file hc32_ll_utility.c
* @brief This file provides utility functions for DDL.
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2022-06-30 CDT Support re-target printf for IAR EW version 9 or later
2023-06-30 CDT Modify register USART DR to USART TDR
Prohibit DDL_DelayMS and DDL_DelayUS functions from being optimized
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_UTILITY UTILITY
* @brief DDL Utility Driver
* @{
*/
#if (LL_UTILITY_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/**
* @defgroup UTILITY_Local_Variables UTILITY Local Variables
* @{
*/
static uint32_t m_u32TickStep = 0UL;
static __IO uint32_t m_u32TickCount = 0UL;
#if (LL_PRINT_ENABLE == DDL_ON)
static void *m_pvPrintDevice = NULL;
static uint32_t m_u32PrintTimeout = 0UL;
#endif
/**
* @}
*/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup UTILITY_Local_Functions UTILITY Local Functions
* @{
*/
#if (LL_PRINT_ENABLE == DDL_ON)
/**
* @brief Set print device.
* @param [in] pvPrintDevice Pointer to print device
* @retval None
*/
__STATIC_INLINE void LL_SetPrintDevice(void *pvPrintDevice)
{
m_pvPrintDevice = pvPrintDevice;
}
/**
* @brief Get print device.
* @param None
* @retval Pointer to print device
*/
__STATIC_INLINE void *LL_GetPrintDevice(void)
{
return m_pvPrintDevice;
}
/**
* @brief Set print timeout.
* @param [in] u32Timeout Print timeout value
* @retval None
*/
__STATIC_INLINE void LL_SetPrintTimeout(uint32_t u32Timeout)
{
m_u32PrintTimeout = u32Timeout;
}
/**
* @brief Get print timeout.
* @param None
* @retval Print timeout value
*/
__STATIC_INLINE uint32_t LL_GetPrintTimeout(void)
{
return m_u32PrintTimeout;
}
#endif /* LL_PRINT_ENABLE */
/**
* @}
*/
/**
* @defgroup UTILITY_Global_Functions UTILITY Global Functions
* @{
*/
/**
* @brief Delay function, delay ms approximately
* @param [in] u32Count ms
* @retval None
*/
#if defined (__CC_ARM) /*!< ARM Compiler */
#pragma push
#pragma O0
#endif
__NO_OPTIMIZE void DDL_DelayMS(uint32_t u32Count)
{
__IO uint32_t i;
const uint32_t u32Cyc = (HCLK_VALUE + 10000UL - 1UL) / 10000UL;
while (u32Count-- > 0UL) {
i = u32Cyc;
while (i-- > 0UL) {
}
}
}
/**
* @brief Delay function, delay us approximately
* @param [in] u32Count us
* @retval None
*/
__NO_OPTIMIZE void DDL_DelayUS(uint32_t u32Count)
{
__IO uint32_t i;
const uint32_t u32Cyc = (HCLK_VALUE + 10000000UL - 1UL) / 10000000UL;
while (u32Count-- > 0UL) {
i = u32Cyc;
while (i-- > 0UL) {
}
}
}
#if defined (__CC_ARM) /*!< ARM Compiler */
#pragma pop
#endif
/**
* @brief This function Initializes the interrupt frequency of the SysTick.
* @param [in] u32Freq SysTick interrupt frequency (1 to 1000).
* @retval int32_t:
* - LL_OK: SysTick Initializes succeed
* - LL_ERR: SysTick Initializes failed
*/
__WEAKDEF int32_t SysTick_Init(uint32_t u32Freq)
{
int32_t i32Ret = LL_ERR;
if ((0UL != u32Freq) && (u32Freq <= 1000UL)) {
m_u32TickStep = 1000UL / u32Freq;
/* Configure the SysTick interrupt */
if (0UL == SysTick_Config(HCLK_VALUE / u32Freq)) {
i32Ret = LL_OK;
}
}
return i32Ret;
}
/**
* @brief This function provides minimum delay (in milliseconds).
* @param [in] u32Delay Delay specifies the delay time.
* @retval None
*/
__WEAKDEF void SysTick_Delay(uint32_t u32Delay)
{
const uint32_t tickStart = SysTick_GetTick();
uint32_t tickEnd = u32Delay;
uint32_t tickMax;
if (m_u32TickStep != 0UL) {
tickMax = 0xFFFFFFFFUL / m_u32TickStep * m_u32TickStep;
/* Add a freq to guarantee minimum wait */
if ((u32Delay >= tickMax) || ((tickMax - u32Delay) < m_u32TickStep)) {
tickEnd = tickMax;
}
while ((SysTick_GetTick() - tickStart) < tickEnd) {
}
}
}
/**
* @brief This function is called to increment a global variable "u32TickCount".
* @note This variable is incremented in SysTick ISR.
* @param None
* @retval None
*/
__WEAKDEF void SysTick_IncTick(void)
{
m_u32TickCount += m_u32TickStep;
}
/**
* @brief Provides a tick value in millisecond.
* @param None
* @retval Tick value
*/
__WEAKDEF uint32_t SysTick_GetTick(void)
{
return m_u32TickCount;
}
/**
* @brief Suspend SysTick increment.
* @param None
* @retval None
*/
__WEAKDEF void SysTick_Suspend(void)
{
/* Disable SysTick Interrupt */
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
}
/**
* @brief Resume SysTick increment.
* @param None
* @retval None
*/
__WEAKDEF void SysTick_Resume(void)
{
/* Enable SysTick Interrupt */
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
}
#ifdef __DEBUG
/**
* @brief DDL assert error handle function
* @param [in] file Point to the current assert the wrong file.
* @param [in] line Point line assert the wrong file in the current.
* @retval None
*/
__WEAKDEF void DDL_AssertHandler(const char *file, int line)
{
/* Users can re-implement this function to print information */
DDL_Printf("Wrong parameters value: file %s on line %d\r\n", file, line);
for (;;) {
}
}
#endif /* __DEBUG */
#if (LL_PRINT_ENABLE == DDL_ON)
#if (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) || \
(defined (__ICCARM__) && (__VER__ < 9000000)) || (defined (__CC_ARM))
/**
* @brief Re-target fputc function.
* @param [in] ch
* @param [in] f
* @retval int32_t
*/
int32_t fputc(int32_t ch, FILE *f)
{
(void)f; /* Prevent unused argument compilation warning */
return (LL_OK == DDL_ConsoleOutputChar((char)ch)) ? ch : -1;
}
#elif (defined (__ICCARM__) && (__VER__ >= 9000000))
#include <LowLevelIOInterface.h>
#pragma module_name = "?__write"
size_t __dwrite(int handle, const unsigned char *buffer, size_t size)
{
size_t nChars = 0;
size_t i;
if (buffer == NULL) {
/*
* This means that we should flush internal buffers. Since we
* don't we just return. (Remember, "handle" == -1 means that all
* handles should be flushed.)
*/
return 0;
}
/* This template only writes to "standard out" and "standard err",
* for all other file handles it returns failure. */
if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR) {
return _LLIO_ERROR;
}
for (i = 0; i < size; i++) {
if (DDL_ConsoleOutputChar((char)buffer[i]) < 0) {
return _LLIO_ERROR;
}
++nChars;
}
return nChars;
}
#elif defined ( __GNUC__ ) && !defined (__CC_ARM)
/**
* @brief Re-target _write function.
* @param [in] fd
* @param [in] data
* @param [in] size
* @retval int32_t
*/
int32_t _write(int fd, char data[], int32_t size)
{
int32_t i = -1;
if (NULL != data) {
(void)fd; /* Prevent unused argument compilation warning */
for (i = 0; i < size; i++) {
if (LL_OK != DDL_ConsoleOutputChar(data[i])) {
break;
}
}
}
return i ? i : -1;
}
#endif
/**
* @brief Initialize printf function
* @param [in] vpDevice Pointer to print device
* @param [in] u32Param Print device parameter
* @param [in] pfnPreinit The function pointer for initializing clock, port, print device etc.
* @retval int32_t:
* - LL_OK: Initialize successfully.
* - LL_ERR: The callback function pfnPreinit occurs error.
* - LL_ERR_INVD_PARAM: The pointer pfnPreinit is NULL.
*/
int32_t LL_PrintfInit(void *vpDevice, uint32_t u32Param, int32_t (*pfnPreinit)(void *vpDevice, uint32_t u32Param))
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
if (NULL != pfnPreinit) {
i32Ret = pfnPreinit(vpDevice, u32Param); /* The callback function initialize clock, port, print device etc */
if (LL_OK == i32Ret) {
LL_SetPrintDevice(vpDevice);
LL_SetPrintTimeout((u32Param == 0UL) ? 0UL : (HCLK_VALUE / u32Param));
} else {
i32Ret = LL_ERR;
DDL_ASSERT(i32Ret == LL_OK); /* Initialize unsuccessfully */
}
}
return i32Ret;
}
/**
* @brief Transmit character.
* @param [in] cData The character for transmitting
* @retval int32_t:
* - LL_OK: Transmit successfully.
* - LL_ERR_TIMEOUT: Transmit timeout.
* - LL_ERR_INVD_PARAM: The print device is invalid.
*/
__WEAKDEF int32_t DDL_ConsoleOutputChar(char cData)
{
uint32_t u32TxEmpty = 0UL;
__IO uint32_t u32TmpCount = 0UL;
int32_t i32Ret = LL_ERR_INVD_PARAM;
uint32_t u32Timeout = LL_GetPrintTimeout();
CM_USART_TypeDef *USARTx = (CM_USART_TypeDef *)LL_GetPrintDevice();
if (NULL != USARTx) {
/* Wait TX data register empty */
while ((u32TmpCount <= u32Timeout) && (0UL == u32TxEmpty)) {
u32TxEmpty = READ_REG32_BIT(USARTx->SR, USART_SR_TXE);
u32TmpCount++;
}
if (0UL != u32TxEmpty) {
WRITE_REG16(USARTx->TDR, (uint16_t)cData);
i32Ret = LL_OK;
} else {
i32Ret = LL_ERR_TIMEOUT;
}
}
return i32Ret;
}
#endif /* LL_PRINT_ENABLE */
/**
* @}
*/
#endif /* LL_UTILITY_ENABLE */
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/
+257
View File
@@ -0,0 +1,257 @@
/**
*******************************************************************************
* @file hc32_ll_wdt.c
* @brief This file provides firmware functions to manage the General Watch Dog
* Timer(WDT).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2023-09-30 CDT Optimize WDT_ClearStatus function timeout
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_wdt.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_WDT WDT
* @brief General Watch Dog Timer
* @{
*/
#if (LL_WDT_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup WDT_Local_Macros WDT Local Macros
* @{
*/
/* WDT Refresh Key */
#define WDT_REFRESH_KEY_START (0x0123UL)
#define WDT_REFRESH_KEY_END (0x3210UL)
/* WDT clear flag timeout(ms) */
#define WDT_CLR_FLAG_TIMEOUT (60000UL)
/* WDT Registers Clear Mask */
#define WDT_CR_CLR_MASK (WDT_CR_PERI | WDT_CR_CKS | WDT_CR_WDPT | \
WDT_CR_SLPOFF | WDT_CR_ITS)
/**
* @defgroup WDT_Check_Parameters_Validity WDT Check Parameters Validity
* @{
*/
#define IS_WDT_CNT_PERIOD(x) \
( ((x) == WDT_CNT_PERIOD256) || \
((x) == WDT_CNT_PERIOD4096) || \
((x) == WDT_CNT_PERIOD16384) || \
((x) == WDT_CNT_PERIOD65536))
#define IS_WDT_CLK_DIV(x) \
( ((x) == WDT_CLK_DIV4) || \
((x) == WDT_CLK_DIV64) || \
((x) == WDT_CLK_DIV128) || \
((x) == WDT_CLK_DIV256) || \
((x) == WDT_CLK_DIV512) || \
((x) == WDT_CLK_DIV1024) || \
((x) == WDT_CLK_DIV2048) || \
((x) == WDT_CLK_DIV8192))
#define IS_WDT_REFRESH_RANGE(x) \
( ((x) == WDT_RANGE_0TO100PCT) || \
((x) == WDT_RANGE_0TO25PCT) || \
((x) == WDT_RANGE_25TO50PCT) || \
((x) == WDT_RANGE_0TO50PCT) || \
((x) == WDT_RANGE_50TO75PCT) || \
((x) == WDT_RANGE_0TO25PCT_50TO75PCT) || \
((x) == WDT_RANGE_25TO75PCT) || \
((x) == WDT_RANGE_0TO75PCT) || \
((x) == WDT_RANGE_75TO100PCT) || \
((x) == WDT_RANGE_0TO25PCT_75TO100PCT) || \
((x) == WDT_RANGE_25TO50PCT_75TO100PCT) || \
((x) == WDT_RANGE_0TO50PCT_75TO100PCT) || \
((x) == WDT_RANGE_50TO100PCT) || \
((x) == WDT_RANGE_0TO25PCT_50TO100PCT) || \
((x) == WDT_RANGE_25TO100PCT))
#define IS_WDT_LPM_CNT(x) \
( ((x) == WDT_LPM_CNT_CONTINUE) || \
((x) == WDT_LPM_CNT_STOP))
#define IS_WDT_EXP_TYPE(x) \
( ((x) == WDT_EXP_TYPE_INT) || \
((x) == WDT_EXP_TYPE_RST))
#define IS_WDT_FLAG(x) \
( ((x) != 0UL) && \
(((x) | WDT_FLAG_ALL) == WDT_FLAG_ALL))
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup WDT_Global_Functions WDT Global Functions
* @{
*/
/**
* @brief Initializes WDT.
* @param [in] pstcWdtInit Pointer to a @ref stc_wdt_init_t structure
* @retval int32_t:
* - LL_OK: Initializes success
* - LL_ERR_INVD_PARAM: pstcWdtInit == NULL
*/
int32_t WDT_Init(const stc_wdt_init_t *pstcWdtInit)
{
int32_t i32Ret = LL_OK;
if (NULL == pstcWdtInit) {
i32Ret = LL_ERR_INVD_PARAM;
} else {
/* Check parameters */
DDL_ASSERT(IS_WDT_CNT_PERIOD(pstcWdtInit->u32CountPeriod));
DDL_ASSERT(IS_WDT_CLK_DIV(pstcWdtInit->u32ClockDiv));
DDL_ASSERT(IS_WDT_REFRESH_RANGE(pstcWdtInit->u32RefreshRange));
DDL_ASSERT(IS_WDT_LPM_CNT(pstcWdtInit->u32LPMCount));
DDL_ASSERT(IS_WDT_EXP_TYPE(pstcWdtInit->u32ExceptionType));
/* WDT CR Configuration(Software Start Mode) */
MODIFY_REG32(CM_WDT->CR, WDT_CR_CLR_MASK,
(pstcWdtInit->u32CountPeriod | pstcWdtInit->u32ClockDiv |
pstcWdtInit->u32RefreshRange | pstcWdtInit->u32LPMCount |
pstcWdtInit->u32ExceptionType));
}
return i32Ret;
}
/**
* @brief WDT feed dog.
* @note In software startup mode, Start counter when refreshing for the first time.
* @param None
* @retval None
*/
void WDT_FeedDog(void)
{
WRITE_REG32(CM_WDT->RR, WDT_REFRESH_KEY_START);
WRITE_REG32(CM_WDT->RR, WDT_REFRESH_KEY_END);
}
/**
* @brief Get WDT flag status.
* @param [in] u32Flag WDT flag type
* This parameter can be one or any combination of the following values:
* @arg WDT_FLAG_UDF: Count underflow flag
* @arg WDT_FLAG_REFRESH: Refresh error flag
* @arg WDT_FLAG_ALL: All of the above
* @retval An @ref en_flag_status_t enumeration type value.
*/
en_flag_status_t WDT_GetStatus(uint32_t u32Flag)
{
en_flag_status_t enFlagSta = RESET;
/* Check parameters */
DDL_ASSERT(IS_WDT_FLAG(u32Flag));
if (0UL != (READ_REG32_BIT(CM_WDT->SR, u32Flag))) {
enFlagSta = SET;
}
return enFlagSta;
}
/**
* @brief Clear WDT flag.
* @param [in] u32Flag WDT flag type
* This parameter can be one or any combination of the following values:
* @arg WDT_FLAG_UDF: Count underflow flag
* @arg WDT_FLAG_REFRESH: Refresh error flag
* @arg WDT_FLAG_ALL: All of the above
* @retval int32_t:
* - LL_OK: Clear flag success
* - LL_ERR_TIMEOUT: Clear flag timeout
*/
int32_t WDT_ClearStatus(uint32_t u32Flag)
{
__IO uint32_t u32Count;
int32_t i32Ret = LL_OK;
/* Check parameters */
DDL_ASSERT(IS_WDT_FLAG(u32Flag));
/* Waiting for FLAG bit clear */
u32Count = WDT_CLR_FLAG_TIMEOUT * (HCLK_VALUE / 25000UL);
while (0UL != READ_REG32_BIT(CM_WDT->SR, u32Flag)) {
CLR_REG32_BIT(CM_WDT->SR, u32Flag);
if (0UL == u32Count) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
u32Count--;
}
return i32Ret;
}
/**
* @}
*/
#endif /* LL_WDT_ENABLE */
/**
* @}
*/
/**
* @}
*/
/******************************************************************************
* EOF (not truncated)
*****************************************************************************/
File diff suppressed because it is too large Load Diff