This commit is contained in:
sc committed 2026-02-14 19:03:02 +08:00
commit da43152a7e
3380 files changed
+1128754

No files matched your search

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,659 @@
/*!
\file gd32h75e_cmp.c
\brief CMP driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_cmp.h"
/*!
\brief CMP deinit
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_deinit(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS &= ((uint32_t)0x00000000U);
CMP_IFC &= ((uint32_t)0xFFFEFFFFU);
CMP_STAT &= ((uint32_t)0xFFFEFFFEU);
CMP_SR &= ((uint32_t)0x00000000U);
}else if(CMP1 == cmp_periph){
CMP1_CS &= ((uint32_t)0x00000000U);
CMP_IFC &= ((uint32_t)0xFFFDFFFFU);
CMP_STAT &= ((uint32_t)0xFFFDFFFDU);
CMP_SR &= ((uint32_t)0x00000000U);
}else{
}
}
/*!
\brief CMP mode init
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] operating_mode
\arg CMP_MODE_HIGHSPEED: high speed mode
\arg CMP_MODE_MIDDLESPEED: medium speed mode
\arg CMP_MODE_VERYLOWSPEED: very-low speed mode
\param[in] inverting_input
\arg CMP_INVERTING_INPUT_1_4VREFINT: VREFINT *1/4 input
\arg CMP_INVERTING_INPUT_1_2VREFINT: VREFINT *1/2 input
\arg CMP_INVERTING_INPUT_3_4VREFINT: VREFINT *3/4 input
\arg CMP_INVERTING_INPUT_VREFINT: VREFINT input
\arg CMP_INVERTING_INPUT_DAC0_OUT0: CMP inverting input DAC0_OUT0
\arg CMP_INVERTING_INPUT_DAC0_OUT1: CMP inverting input DAC0_OUT1
\arg CMP_INVERTING_INPUT_PB1_PE10: PB1 for CMP0 or PE10 for CMP1 as inverting input
\arg CMP_INVERTING_INPUT_PC4_PE7: PC4 for CMP0 or PE7 for CMP1 as inverting input
\param[in] hysteresis
\arg CMP_HYSTERESIS_NO: output no hysteresis
\arg CMP_HYSTERESIS_LOW: output low hysteresis
\arg CMP_HYSTERESIS_MIDDLE: output middle hysteresis
\arg CMP_HYSTERESIS_HIGH: output high hysteresis
\param[out] none
\retval none
*/
void cmp_mode_init(cmp_enum cmp_periph, uint32_t operating_mode, uint32_t inverting_input, uint32_t output_hysteresis)
{
uint32_t temp = 0U;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CMP_OPERATING_MODE(operating_mode)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
}else if(NOT_CMP_INVERTING_INPUT(inverting_input)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
}else if(NOT_CMP_OUTPUT_HYSTERESIS(output_hysteresis)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
/* initialize comparator 0 mode */
temp = CMP0_CS;
temp &= ~(uint32_t)(CMP_CS_CMPXM | CMP_CS_CMPXMISEL | CMP_CS_CMPXHST);
temp |= (uint32_t)(operating_mode | inverting_input | output_hysteresis);
CMP0_CS = temp;
}else if(CMP1 == cmp_periph){
/* initialize comparator 1 mode */
temp = CMP1_CS;
temp &= ~(uint32_t)(CMP_CS_CMPXM | CMP_CS_CMPXMISEL | CMP_CS_CMPXHST);
temp |= (uint32_t)(operating_mode | inverting_input | output_hysteresis);
CMP1_CS = temp;
}else{
}
}
}
/*!
\brief CMP noninverting input select
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] noninverting_input
\arg CMP_NONINVERTING_INPUT_PB0_PE9: CMP noninverting input PB0 for CMP0 or PE9 for CMP1
\arg CMP_NONINVERTING_INPUT_PB2_PE11: CMP noninverting input PB2 for CMP0 or PE12 for CMP1
\param[out] none
\retval none
*/
void cmp_noninverting_input_select(cmp_enum cmp_periph, uint32_t noninverting_input)
{
uint32_t temp = 0U;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CMP_NONINVERTING_INPUT(noninverting_input)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0003U), ERR_PARAM_INVALID);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
temp = CMP0_CS;
temp &= ~(uint32_t)CMP_CS_CMPXPSEL;
temp |= (uint32_t)noninverting_input;
CMP0_CS = temp;
}else if(CMP1 == cmp_periph){
temp = CMP1_CS;
temp &= ~(uint32_t)CMP_CS_CMPXPSEL;
temp |= (uint32_t)noninverting_input;
CMP1_CS = temp;
}else{
}
}
}
/*!
\brief CMP output init
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] output_polarity
\arg CMP_OUTPUT_POLARITY_INVERTED: output is inverted
\arg CMP_OUTPUT_POLARITY_NONINVERTED: output is not inverted
\param[out] none
\retval none
*/
void cmp_output_init(cmp_enum cmp_periph, uint32_t output_polarity)
{
uint32_t temp = 0U;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CMP_OUTPUT_POLARITY(output_polarity)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0004U), ERR_PARAM_INVALID);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
/* initialize comparator 0 output */
temp = CMP0_CS;
/* output polarity */
if(CMP_OUTPUT_POLARITY_INVERTED == output_polarity){
temp |= (uint32_t)CMP_CS_CMPXPL;
}else{
temp &= ~(uint32_t)CMP_CS_CMPXPL;
}
CMP0_CS = temp;
}else if(CMP1 == cmp_periph){
/* initialize comparator 1 output */
temp = CMP1_CS;
/* output polarity */
if(CMP_OUTPUT_POLARITY_INVERTED == output_polarity){
temp |= (uint32_t)CMP_CS_CMPXPL;
}else{
temp &= ~(uint32_t)CMP_CS_CMPXPL;
}
CMP1_CS = temp;
}else{
}
}
}
/*!
\brief config comparator output port
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] cmp_output_sel
\arg CMP_AFSE_GPIO_PA6: CMP alternate GPIO PA6
\arg CMP_AFSE_GPIO_PA8: CMP alternate GPIO PA8
\arg CMP_AFSE_GPIO_PB12: CMP alternate GPIO PB12
\arg CMP_AFSE_GPIO_PE6: CMP alternate GPIO PE6
\arg CMP_AFSE_GPIO_PE15: CMP alternate GPIO PE15
\arg CMP_AFSE_GPIO_PG2: CMP alternate GPIO PG2
\arg CMP_AFSE_GPIO_PG3: CMP alternate GPIO PG3
\arg CMP_AFSE_GPIO_PG4: CMP alternate GPIO PG4
\arg CMP_AFSE_GPIO_PK0: CMP alternate GPIO PK0
\arg CMP_AFSE_GPIO_PK1: CMP alternate GPIO PK1
\arg CMP_AFSE_GPIO_PK2: CMP alternate GPIO PK2
\param[out] none
\retval none
*/
void cmp_output_mux_config(cmp_enum cmp_periph, uint32_t cmp_output_sel)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CMP_AFSE_GPIO_PIN(cmp_output_sel)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0005U), ERR_PARAM_INVALID);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
CMP_SR &= ~(uint32_t)cmp_output_sel;
}else if(CMP1 == cmp_periph){
CMP_SR |= cmp_output_sel;
}else{
}
}
}
/*!
\brief CMP output blanking function init
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] blanking_source_selection
\arg CMP_BLANKING_NONE: CMP no blanking source
\arg CMP_BLANKING_TIMER0_OC0: CMP TIMER0_CH0 output compare signal selected as blanking source
\arg CMP_BLANKING_TIMER1_OC2: CMP TIMER1_CH2 output compare signal selected as blanking source
\arg CMP_BLANKING_TIMER2_OC2: CMP TIMER2_CH2 output compare signal selected as blanking source
\arg CMP_BLANKING_TIMER2_OC3: CMP TIMER2_CH3 output compare signal selected as blanking source
\arg CMP_BLANKING_TIMER7_OC0: CMP TIMER7_CH0 output compare signal selected as blanking source
\arg CMP_BLANKING_TIMER14_OC0: CMP TIMER14_CH0 output compare signal selected as blanking source
\param[out] none
\retval none
*/
void cmp_blanking_init(cmp_enum cmp_periph, uint32_t blanking_source_selection)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CMP_BLK_SOURCE_SEL(blanking_source_selection)){
fw_debug_report_err(CMP_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t temp = 0U;
if(CMP0 == cmp_periph){
temp = CMP0_CS;
temp &= ~(uint32_t)CMP_CS_CMPXBLK;
temp |= (uint32_t)blanking_source_selection;
CMP0_CS = temp;
}else if(CMP1 == cmp_periph){
temp = CMP1_CS;
temp &= ~(uint32_t)CMP_CS_CMPXBLK;
temp |= (uint32_t)blanking_source_selection;
CMP1_CS = temp;
}else{
}
}
}
/*!
\brief enable CMP
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_enable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS |= (uint32_t)CMP_CS_CMPXEN;
}else if(CMP1 == cmp_periph){
CMP1_CS |= (uint32_t)CMP_CS_CMPXEN;
}else{
}
}
/*!
\brief disable CMP
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_disable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS &= ~(uint32_t)CMP_CS_CMPXEN;
}else if(CMP1 == cmp_periph){
CMP1_CS &= ~(uint32_t)CMP_CS_CMPXEN;
}else{
}
}
/*!
\brief enable the window mode
\param[in] none
\param[out] none
\retval none
*/
void cmp_window_enable(void)
{
CMP1_CS |= (uint32_t)CMP_CS_WNDEN;
}
/*!
\brief disable the window mode
\param[in] none
\param[out] none
\retval none
*/
void cmp_window_disable(void)
{
CMP1_CS &= ~(uint32_t)CMP_CS_WNDEN;
}
/*!
\brief lock the comparator
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_lock_enable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
/* lock CMP0 */
CMP0_CS |= (uint32_t)CMP_CS_CMPXLK;
}else if(CMP1 == cmp_periph){
/* lock CMP1 */
CMP1_CS |= (uint32_t)CMP_CS_CMPXLK;
}else{
}
}
/*!
\brief enable the voltage scaler
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_voltage_scaler_enable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS |= (uint32_t)CMP_CS_CMPXSEN;
}else if(CMP1 == cmp_periph){
CMP1_CS |= (uint32_t)CMP_CS_CMPXSEN;
}else{
}
}
/*!
\brief disable the voltage scaler
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_voltage_scaler_disable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS &= ~(uint32_t)CMP_CS_CMPXSEN;
}else if(CMP1 == cmp_periph){
CMP1_CS &= ~(uint32_t)CMP_CS_CMPXSEN;
}else{
}
}
/*!
\brief enable the scaler bridge
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_scaler_bridge_enable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS |= (uint32_t)CMP_CS_CMPXBEN;
}else if(CMP1 == cmp_periph){
CMP1_CS |= (uint32_t)CMP_CS_CMPXBEN;
}else{
}
}
/*!
\brief disable the scaler bridge
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval none
*/
void cmp_scaler_bridge_disable(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
CMP0_CS &= ~(uint32_t)CMP_CS_CMPXBEN;
}else if(CMP1 == cmp_periph){
CMP1_CS &= ~(uint32_t)CMP_CS_CMPXBEN;
}else{
}
}
/*!
\brief get output level
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[out] none
\retval the output level
*/
uint32_t cmp_output_level_get(cmp_enum cmp_periph)
{
if(CMP0 == cmp_periph){
/* get output level of CMP0 */
if((uint32_t)RESET != (CMP_STAT & CMP_STAT_CMP0O)) {
return CMP_OUTPUTLEVEL_HIGH;
}else{
return CMP_OUTPUTLEVEL_LOW;
}
}else{
/* get output level of CMP1 */
if((uint32_t)RESET != (CMP_STAT & CMP_STAT_CMP1O)) {
return CMP_OUTPUTLEVEL_HIGH;
}else{
return CMP_OUTPUTLEVEL_LOW;
}
}
}
/*!
\brief get CMP flag
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] flag: CMP flags
\arg CMP_FLAG_COMPARE: CMP compare flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus cmp_flag_get(cmp_enum cmp_periph, uint32_t flag)
{
FlagStatus reval = RESET;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0011U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
if(CMP_FLAG_COMPARE == flag){
if(0U != (CMP_STAT & CMP_STAT_CMP0IF)){
reval = SET;
}
}
}else if(CMP1 == cmp_periph){
if(CMP_FLAG_COMPARE == flag){
if(0U != (CMP_STAT & CMP_STAT_CMP1IF)){
reval = SET;
}
}
}else{
}
}
return reval;
}
/*!
\brief clear CMP flag
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] flag: CMP flags
\arg CMP_FLAG_COMPARE: CMP compare flag
\param[out] none
\retval none
*/
void cmp_flag_clear(cmp_enum cmp_periph, uint32_t flag)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
if(CMP_FLAG_COMPARE == flag){
CMP_IFC |= (uint32_t)CMP_IFC_CMP0IC;
}
}else if(CMP1 == cmp_periph){
if(CMP_FLAG_COMPARE == flag){
CMP_IFC |= (uint32_t)CMP_IFC_CMP1IC;
}
}else{
}
}
}
/*!
\brief enable CMP interrupt
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] interrupt: CMP interrupt enable source
only one parameter can be selected which is shown as below:
\arg CMP_INT_COMPARE: CMP compare interrupt
\param[out] none
\retval none
*/
void cmp_interrupt_enable(cmp_enum cmp_periph, uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_INTERRUPT(interrupt)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0013U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
/* enable CMP0 interrupt */
CMP0_CS |= (uint32_t)interrupt;
}else if(CMP1 == cmp_periph){
/* enable CMP1 interrupt */
CMP1_CS |= (uint32_t)interrupt;
}else{
}
}
}
/*!
\brief disable CMP interrupt
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] interrupt: CMP interrupt enable source
only one parameter can be selected which is shown as below:
\arg CMP_INT_COMPARE: CMP compare interrupt
\param[out] none
\retval none
*/
void cmp_interrupt_disable(cmp_enum cmp_periph, uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_INTERRUPT(interrupt)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0014U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
/* disable CMP0 interrupt */
CMP0_CS &= ~(uint32_t)interrupt;
}else if(CMP1 == cmp_periph){
/* disable CMP1 interrupt */
CMP1_CS &= ~(uint32_t)interrupt;
}else{
}
}
}
/*!
\brief get CMP interrupt flag
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] flag: CMP interrupt flags
\arg CMP_INT_FLAG_COMPARE: CMP compare interrupt flag
\param[out] none
\retval none
*/
FlagStatus cmp_interrupt_flag_get(cmp_enum cmp_periph, uint32_t flag)
{
uint32_t intstatus = 0U, flagstatus = 0U;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_INTERRUPT_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0015U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(CMP0 == cmp_periph){
if(CMP_INT_FLAG_COMPARE == flag){
/* get the corresponding flag bit status */
flagstatus = CMP_STAT & CMP_STAT_CMP0IF;
/* get the interrupt enable bit status */
intstatus = CMP0_CS & CMP_CS_CMPXINTEN;
}
}else if(CMP1 == cmp_periph){
if(CMP_INT_FLAG_COMPARE == flag){
/* get the corresponding flag bit status */
flagstatus = CMP_STAT & CMP_STAT_CMP1IF;
/* get the interrupt enable bit status */
intstatus = CMP1_CS & CMP_CS_CMPXINTEN;
}
}else{
}
}
if((0U != flagstatus) && (0U != intstatus)){
return SET;
}else{
return RESET;
}
}
/*!
\brief clear CMP interrupt flag
\param[in] cmp_periph
\arg CMP0: comparator 0
\arg CMP1: comparator 1
\param[in] flag: CMP interrupt flags
\arg CMP_INT_FLAG_COMPARE: CMP compare interrupt flag
\param[out] none
\retval none
*/
void cmp_interrupt_flag_clear(cmp_enum cmp_periph, uint32_t flag)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_CMP_INTERRUPT_FLAG(flag)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0016U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* clear CMP interrupt flag */
if(CMP0 == cmp_periph){
if(CMP_INT_FLAG_COMPARE == flag){
CMP_IFC |= (uint32_t)CMP_IFC_CMP0IC;
}
}else if(CMP1 == cmp_periph){
if(CMP_INT_FLAG_COMPARE == flag){
CMP_IFC |= (uint32_t)CMP_IFC_CMP1IC;
}
}else{
}
}
}
@@ -0,0 +1,283 @@
/*!
\file gd32h75e_crc.c
\brief CRC driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_crc.h"
#define CRC_IDATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU)
#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU)
#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U)
#define CRC_POLY_RESET_VALUE ((uint32_t)0x04C11DB7U)
/*!
\brief deinit CRC calculation unit
\param[in] none
\param[out] none
\retval none
*/
void crc_deinit(void)
{
CRC_IDATA = CRC_IDATA_RESET_VALUE;
CRC_DATA = CRC_DATA_RESET_VALUE;
CRC_FDATA = CRC_FDATA_RESET_VALUE;
CRC_POLY = CRC_POLY_RESET_VALUE;
CRC_CTL = (uint32_t)CRC_CTL_RST;
}
/*!
\brief write the initialization data register
\param[in] init_data:specify 32-bit data
\param[out] none
\retval none
*/
void crc_init_data_register_write(uint32_t init_data)
{
CRC_IDATA = (uint32_t)init_data;
}
/*!
\brief read the data register
\param[in] none
\param[out] none
\retval 32-bit value of the data register
*/
uint32_t crc_data_register_read(void)
{
uint32_t data;
data = CRC_DATA;
return (data);
}
/*!
\brief read the free data register
\param[in] none
\param[out] none
\retval 8-bit value of the free data register
*/
uint8_t crc_free_data_register_read(void)
{
uint8_t fdata;
fdata = (uint8_t)CRC_FDATA;
return (fdata);
}
/*!
\brief write the free data register
\param[in] free_data: specify 8-bit data
\param[out] none
\retval none
*/
void crc_free_data_register_write(uint8_t free_data)
{
CRC_FDATA = (uint32_t)free_data;
}
/*!
\brief disable the reverse operation of output data
\param[in] none
\param[out] none
\retval none
*/
void crc_reverse_output_data_disable(void)
{
CRC_CTL &= (uint32_t)(~CRC_CTL_REV_O);
}
/*!
\brief enable the reverse operation of output data
\param[in] none
\param[out] none
\retval none
*/
void crc_reverse_output_data_enable(void)
{
CRC_CTL &= (uint32_t)(~CRC_CTL_REV_O);
CRC_CTL |= (uint32_t)CRC_CTL_REV_O;
}
/*!
\brief configure the CRC input data function
\param[in] data_reverse: specify input data reverse function
only one parameter can be selected which is shown as below:
\arg CRC_INPUT_DATA_NOT: input data is not reversed
\arg CRC_INPUT_DATA_BYTE: input data is reversed on 8 bits
\arg CRC_INPUT_DATA_HALFWORD: input data is reversed on 16 bits
\arg CRC_INPUT_DATA_WORD: input data is reversed on 32 bits
\param[out] none
\retval none
*/
void crc_input_data_reverse_config(uint32_t data_reverse)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CRC_INPUT_DATA_REV(data_reverse)) {
fw_debug_report_err(CRC_MODULE_ID, API_ID(0x0008U), ERR_PARAM_INVALID);
} else
#endif
{
CRC_CTL &= (uint32_t)(~CRC_CTL_REV_I);
CRC_CTL |= (uint32_t)data_reverse;
}
}
/*!
\brief reset data register to the value of initialization data register
\param[in] none
\param[out] none
\retval none
*/
void crc_data_register_reset(void)
{
CRC_CTL |= (uint32_t)CRC_CTL_RST;
}
/*!
\brief configure the CRC size of polynomial function
\param[in] poly_size: size of polynomial
only one parameter can be selected which is shown as below:
\arg CRC_CTL_PS_32: 32-bit polynomial for CRC calculation
\arg CRC_CTL_PS_16: 16-bit polynomial for CRC calculation
\arg CRC_CTL_PS_8: 8-bit polynomial for CRC calculation
\arg CRC_CTL_PS_7: 7-bit polynomial for CRC calculation
\param[out] none
\retval none
*/
void crc_polynomial_size_set(uint32_t poly_size)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CRC_POLY_SIZE(poly_size)) {
fw_debug_report_err(CRC_MODULE_ID, API_ID(0x000AU), ERR_PARAM_INVALID);
} else
#endif
{
CRC_CTL &= (uint32_t)(~CRC_CTL_PS);
CRC_CTL |= (uint32_t)poly_size;
}
}
/*!
\brief configure the CRC polynomial value function
\param[in] poly: configurable polynomial value
\param[out] none
\retval none
*/
void crc_polynomial_set(uint32_t poly)
{
CRC_POLY &= (uint32_t)(~CRC_POLY_POLY);
CRC_POLY = poly;
}
/*!
\brief CRC calculate single data
\param[in] sdata: specify input data
\param[in] data_format: input data format
only one parameter can be selected which is shown as below:
\arg INPUT_FORMAT_WORD: input data in word format
\arg INPUT_FORMAT_HALFWORD: input data in half-word format
\arg INPUT_FORMAT_BYTE: input data in byte format
\param[out] none
\retval CRC calculate value
*/
uint32_t crc_single_data_calculate(uint32_t sdata, uint8_t data_format)
{
uint32_t data_calcul = 0xFFFFFFFFU;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CRC_INPUT_DATA_FORMAT(data_format)) {
fw_debug_report_err(CRC_MODULE_ID, API_ID(0x000CU), ERR_PARAM_INVALID);
} else
#endif
{
if(INPUT_FORMAT_WORD == data_format) {
REG32(CRC) = sdata;
} else if(INPUT_FORMAT_HALFWORD == data_format) {
REG16(CRC) = (uint16_t)sdata;
} else {
REG8(CRC) = (uint8_t)sdata;
}
data_calcul = CRC_DATA;
}
return data_calcul;
}
/*!
\brief CRC calculate a data array
\param[in] array: pointer to the input data array
\param[in] size: size of the array
\param[in] data_format: input data format
only one parameter can be selected which is shown as below:
\arg INPUT_FORMAT_WORD: input data in word format
\arg INPUT_FORMAT_HALFWORD: input data in half-word format
\arg INPUT_FORMAT_BYTE: input data in byte format
\param[out] none
\retval CRC calculate value
*/
uint32_t crc_block_data_calculate(void *array, uint32_t size, uint8_t data_format)
{
uint32_t index;
uint32_t data;
uint32_t data_calcul = 0xFFFFFFFFU;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(array)) {
fw_debug_report_err(CRC_MODULE_ID, API_ID(0x000DU), ERR_PARAM_POINTER);
} else if(NOT_CRC_INPUT_DATA_FORMAT(data_format)) {
fw_debug_report_err(CRC_MODULE_ID, API_ID(0x000DU), ERR_PARAM_INVALID);
} else
#endif
{
data = (uint32_t)array;
if(INPUT_FORMAT_WORD == data_format) {
for(index = 0U; index < size; index++) {
REG32(CRC) = *(uint32_t *)data;
data += 4U;
}
} else if(INPUT_FORMAT_HALFWORD == data_format) {
for(index = 0U; index < size; index++) {
REG16(CRC) = *(uint16_t *)data;
data += 2U;
}
} else {
for(index = 0U; index < size; index++) {
REG8(CRC) = *(uint8_t *)data;
data += 1U;
}
}
data_calcul = CRC_DATA;
}
return data_calcul;
}
@@ -0,0 +1,484 @@
/*!
\file gd32h75e_ctc.c
\brief CTC driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_ctc.h"
#define CTC_FLAG_MASK ((uint32_t)0x00000700U)
/* CTC register bit offset */
#define CTC_TRIMVALUE_OFFSET ((uint32_t)8U)
#define CTC_TRIM_VALUE_OFFSET ((uint32_t)8U)
#define CTC_REFCAP_OFFSET ((uint32_t)16U)
#define CTC_LIMIT_VALUE_OFFSET ((uint32_t)16U)
/*!
\brief reset CTC clock trim controller
\param[in] none
\param[out] none
\retval none
*/
void ctc_deinit(void)
{
/* reset CTC */
rcu_periph_reset_enable(RCU_CTCRST);
rcu_periph_reset_disable(RCU_CTCRST);
}
/*!
\brief enable CTC trim counter
\param[in] none
\param[out] none
\retval none
*/
void ctc_counter_enable(void)
{
CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN;
}
/*!
\brief disable CTC trim counter
\param[in] none
\param[out] none
\retval none
*/
void ctc_counter_disable(void)
{
CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN);
}
/*!
\brief configure the IRC48M trim value
\param[in] trim_value: 8-bit IRC48M trim value
\arg 0x00 - 0x3F
\param[out] none
\retval none
*/
void ctc_irc48m_trim_value_config(uint8_t trim_value)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CTC_TRIM_VALUE(trim_value)) {
fw_debug_report_err(CTC_MODULE_ID, API_ID(0x0004U), ERR_PARAM_INVALID);
} else
#endif
{
/* clear TRIMVALUE bits */
CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE);
/* set TRIMVALUE bits */
CTC_CTL0 |= ((uint32_t)trim_value << CTC_TRIM_VALUE_OFFSET);
}
}
/*!
\brief generate software reference source sync pulse
\param[in] none
\param[out] none
\retval none
*/
void ctc_software_refsource_pulse_generate(void)
{
CTC_CTL0 |= (uint32_t)CTC_CTL0_SWREFPUL;
}
/*!
\brief configure hardware automatically trim mode
\param[in] hardmode:
only one parameter can be selected which is shown as below:
\arg CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable
\arg CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable
\param[out] none
\retval none
*/
void ctc_hardware_trim_mode_config(uint32_t hardmode)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CTC_HARD_MODE(hardmode)) {
fw_debug_report_err(CTC_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else
#endif
{
CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM);
CTC_CTL0 |= (uint32_t)hardmode;
}
}
/*!
\brief configure reference signal source polarity
\param[in] polarity: reference signal source edge
only one parameter can be selected which is shown as below:
\arg CTC_REFSOURCE_POLARITY_FALLING: reference signal source polarity is falling edge
\arg CTC_REFSOURCE_POLARITY_RISING: reference signal source polarity is rising edge
\param[out] none
\retval none
*/
void ctc_refsource_polarity_config(uint32_t polarity)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CTC_REFSOURCE_POLARITY(polarity)) {
fw_debug_report_err(CTC_MODULE_ID, API_ID(0x0007U), ERR_PARAM_INVALID);
} else
#endif
{
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL);
CTC_CTL1 |= (uint32_t)polarity;
}
}
/*!
\brief select reference signal source
\param[in] refs: reference signal source
only one parameter can be selected which is shown as below:
\arg CTC_REFSOURCE_GPIO: GPIO is selected
\arg CTC_REFSOURCE_LXTAL: LXTAL is selected
\param[out] none
\retval none
*/
void ctc_refsource_signal_select(uint32_t refs)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CTC_REFSOURCE(refs)) {
fw_debug_report_err(CTC_MODULE_ID, API_ID(0x0008U), ERR_PARAM_INVALID);
} else
#endif
{
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL);
CTC_CTL1 |= (uint32_t)refs;
}
}
/*!
\brief configure reference signal source prescaler
\param[in] prescaler: reference signal source prescaler
only one parameter can be selected which is shown as below:
\arg CTC_REFSOURCE_PSC_OFF: reference signal not divided
\arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2
\arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4
\arg CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8
\arg CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16
\arg CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32
\arg CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64
\arg CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128
\param[out] none
\retval none
*/
void ctc_refsource_prescaler_config(uint32_t prescaler)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CTC_REFSOURCE_PSC(prescaler)) {
fw_debug_report_err(CTC_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else
#endif
{
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC);
CTC_CTL1 |= (uint32_t)prescaler;
}
}
/*!
\brief configure clock trim base limit value
\param[in] limit_value: 8-bit clock trim base limit value
\arg 0x00 - 0xFF
\param[out] none
\retval none
*/
void ctc_clock_limit_value_config(uint8_t limit_value)
{
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM);
CTC_CTL1 |= (uint32_t)((uint32_t)limit_value << CTC_LIMIT_VALUE_OFFSET);
}
/*!
\brief configure CTC counter reload value
\param[in] reload_value: 16-bit CTC counter reload value
\arg 0x0000 - 0xFFFF
\param[out] none
\retval none
*/
void ctc_counter_reload_value_config(uint16_t reload_value)
{
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE);
CTC_CTL1 |= (uint32_t)reload_value;
}
/*!
\brief read CTC counter capture value when reference sync pulse occurred
\param[in] none
\param[out] none
\retval the 16-bit CTC counter capture value
*/
uint16_t ctc_counter_capture_value_read(void)
{
uint16_t capture_value = 0U;
capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP) >> CTC_REFCAP_OFFSET);
return (capture_value);
}
/*!
\brief read CTC trim counter direction when reference sync pulse occurred
\param[in] none
\param[out] none
\retval FlagStatus: SET or RESET
\arg SET: CTC trim counter direction is down-counting
\arg RESET: CTC trim counter direction is up-counting
*/
FlagStatus ctc_counter_direction_read(void)
{
if(RESET != (CTC_STAT & CTC_STAT_REFDIR)) {
return SET;
} else {
return RESET;
}
}
/*!
\brief read CTC counter reload value
\param[in] none
\param[out] none
\retval the 16-bit CTC counter reload value
*/
uint16_t ctc_counter_reload_value_read(void)
{
uint16_t reload_value = 0U;
reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE);
return (reload_value);
}
/*!
\brief read the IRC48M trim value
\param[in] none
\param[out] none
\retval the 8-bit IRC48M trim value
*/
uint8_t ctc_irc48m_trim_value_read(void)
{
uint8_t trim_value = 0U;
trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> CTC_TRIMVALUE_OFFSET);
return (trim_value);
}
/*!
\brief get CTC flag
\param[in] flag: the CTC flag
only one parameter can be selected which is shown as below:
\arg CTC_FLAG_CKOK: clock trim OK flag
\arg CTC_FLAG_CKWARN: clock trim warning flag
\arg CTC_FLAG_ERR: error flag
\arg CTC_FLAG_EREF: expect reference flag
\arg CTC_FLAG_CKERR: clock trim error flag
\arg CTC_FLAG_REFMISS: reference sync pulse miss flag
\arg CTC_FLAG_TRIMERR: trim value error flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus ctc_flag_get(uint32_t flag)
{
FlagStatus status = SET;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CTC_FLAG(flag)) {
fw_debug_report_err(CTC_MODULE_ID, API_ID(0x0010U), ERR_PARAM_INVALID);
} else
#endif
{
if(RESET != (CTC_STAT & flag)) {
status = SET;
} else {
status = RESET;
}
}
return status;
}
/*!
\brief clear CTC flag
\param[in] flag: the CTC flag
only one parameter can be selected which is shown as below:
\arg CTC_FLAG_CKOK: clock trim OK flag
\arg CTC_FLAG_CKWARN: clock trim warning flag
\arg CTC_FLAG_ERR: error flag
\arg CTC_FLAG_EREF: expect reference flag
\arg CTC_FLAG_CKERR: clock trim error flag
\arg CTC_FLAG_REFMISS: reference sync pulse miss flag
\arg CTC_FLAG_TRIMERR: trim value error flag
\param[out] none
\retval none
*/
void ctc_flag_clear(uint32_t flag)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CTC_FLAG(flag)) {
fw_debug_report_err(CTC_MODULE_ID, API_ID(0x0011U), ERR_PARAM_INVALID);
} else
#endif
{
if(RESET != (flag & CTC_FLAG_MASK)) {
CTC_INTC |= CTC_INTC_ERRIC;
} else {
CTC_INTC |= flag;
}
}
}
/*!
\brief enable the CTC interrupt
\param[in] interrupt: CTC interrupt enable source
one or more parameters can be selected which are shown as below:
\arg CTC_INT_CKOK: clock trim OK interrupt
\arg CTC_INT_CKWARN: clock trim warning interrupt
\arg CTC_INT_ERR: error interrupt
\arg CTC_INT_EREF: expect reference interrupt
\param[out] none
\retval none
*/
void ctc_interrupt_enable(uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CTC_INTERRUPT_SOURCE(interrupt)) {
fw_debug_report_err(CTC_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
} else
#endif
{
CTC_CTL0 |= (uint32_t)interrupt;
}
}
/*!
\brief disable the CTC interrupt
\param[in] interrupt: CTC interrupt disable source
one or more parameters can be selected which are shown as below:
\arg CTC_INT_CKOK: clock trim OK interrupt
\arg CTC_INT_CKWARN: clock trim warning interrupt
\arg CTC_INT_ERR: error interrupt
\arg CTC_INT_EREF: expect reference interrupt
\param[out] none
\retval none
*/
void ctc_interrupt_disable(uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CTC_INTERRUPT_SOURCE(interrupt)) {
fw_debug_report_err(CTC_MODULE_ID, API_ID(0x0013U), ERR_PARAM_INVALID);
} else
#endif
{
CTC_CTL0 &= (uint32_t)(~interrupt);
}
}
/*!
\brief get CTC interrupt flag
\param[in] int_flag: the CTC interrupt flag
only one parameter can be selected which is shown as below:
\arg CTC_INT_FLAG_CKOK: clock trim OK interrupt flag
\arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt flag
\arg CTC_INT_FLAG_ERR: error interrupt flag
\arg CTC_INT_FLAG_EREF: expect reference interrupt flag
\arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt flag
\arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt flag
\arg CTC_INT_FLAG_TRIMERR: trim value error interrupt flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus ctc_interrupt_flag_get(uint32_t int_flag)
{
FlagStatus status = SET;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CTC_FLAG(int_flag)) {
fw_debug_report_err(CTC_MODULE_ID, API_ID(0x0014U), ERR_PARAM_INVALID);
} else
#endif
{
uint32_t interrupt_flag = 0U, intenable = 0U;
/* check whether the interrupt is enabled */
if(RESET != (int_flag & CTC_FLAG_MASK)) {
intenable = CTC_CTL0 & CTC_CTL0_ERRIE;
} else {
intenable = CTC_CTL0 & int_flag;
}
/* get interrupt flag status */
interrupt_flag = CTC_STAT & int_flag;
if(interrupt_flag && intenable) {
status = SET;
} else {
status = RESET;
}
}
return status;
}
/*!
\brief clear CTC interrupt flag
\param[in] int_flag: the CTC interrupt flag
only one parameter can be selected which is shown as below:
\arg CTC_INT_FLAG_CKOK: clock trim OK interrupt flag
\arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt flag
\arg CTC_INT_FLAG_ERR: error interrupt flag
\arg CTC_INT_FLAG_EREF: expect reference interrupt flag
\arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt flag
\arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt flag
\arg CTC_INT_FLAG_TRIMERR: trim value error interrupt flag
\param[out] none
\retval none
*/
void ctc_interrupt_flag_clear(uint32_t int_flag)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_CTC_FLAG(int_flag)) {
fw_debug_report_err(CTC_MODULE_ID, API_ID(0x0015U), ERR_PARAM_INVALID);
} else
#endif
{
if(RESET != (int_flag & CTC_FLAG_MASK)) {
CTC_INTC |= CTC_INTC_ERRIC;
} else {
CTC_INTC |= int_flag;
}
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,192 @@
/*!
\file gd32h75e_dbg.c
\brief DBG driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_dbg.h"
#define DBG_RESET_VAL ((uint32_t)0x00000000U) /*!< DBG reset value */
/*!
\brief deinitialize the DBG
\param[in] none
\param[out] none
\retval none
*/
void dbg_deinit(void)
{
DBG_CTL0 = DBG_RESET_VAL;
DBG_CTL1 = DBG_RESET_VAL;
DBG_CTL2 = DBG_RESET_VAL;
DBG_CTL3 = DBG_RESET_VAL;
DBG_CTL4 = DBG_RESET_VAL;
}
/*!
\brief read DBG_ID code register
\param[in] none
\param[out] none
\retval DBG_ID code
*/
uint32_t dbg_id_get(void)
{
return DBG_ID;
}
/*!
\brief enable low power behavior when the mcu is in debug mode
\param[in] dbg_low_power:
only one parameter can be selected which is shown as below:
\arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode
\arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode
\arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode
\param[out] none
\retval none
*/
void dbg_low_power_enable(uint32_t dbg_low_power)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_DBG_LOW_POWER_PARAMETER(dbg_low_power)) {
fw_debug_report_err(DBG_MODULE_ID, API_ID(0x0003U), ERR_PARAM_INVALID);
} else
#endif
{
DBG_CTL0 |= dbg_low_power;
}
}
/*!
\brief disable low power behavior when the mcu is in debug mode
\param[in] dbg_low_power:
only one parameter can be selected which is shown as below:
\arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode
\arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode
\arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode
\param[out] none
\retval none
*/
void dbg_low_power_disable(uint32_t dbg_low_power)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_DBG_LOW_POWER_PARAMETER(dbg_low_power)) {
fw_debug_report_err(DBG_MODULE_ID, API_ID(0x0004U), ERR_PARAM_INVALID);
} else
#endif
{
DBG_CTL0 &= ~dbg_low_power;
}
}
/*!
\brief enable trace pin assignment
\param[in] none
\param[out] none
\retval none
*/
void dbg_trace_pin_enable(void)
{
DBG_CTL0 |= DBG_CTL0_TRACECLKEN;
}
/*!
\brief disable trace pin assignment
\param[in] none
\param[out] none
\retval none
*/
void dbg_trace_pin_disable(void)
{
DBG_CTL0 &= ~DBG_CTL0_TRACECLKEN;
}
/*!
\brief trace pin mode selection
\param[in] trace_mode:
\arg TRACE_MODE_ASYNC: trace pin used for async mode
\arg TRACE_MODE_SYNC_DATASIZE_1: trace pin used for sync mode and data size is 1
\arg TRACE_MODE_SYNC_DATASIZE_2: trace pin used for sync mode and data size is 2
\arg TRACE_MODE_SYNC_DATASIZE_4: trace pin used for sync mode and data size is 4
\param[out] none
\retval none
*/
void dbg_trace_pin_mode_set(uint32_t trace_mode)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_DBG_TRACE_MODE_PARAMETER(trace_mode)) {
fw_debug_report_err(DBG_MODULE_ID, API_ID(0x0007U), ERR_PARAM_INVALID);
} else
#endif
{
DBG_CTL0 &= ~DBG_CTL0_TRACE_MODE;
DBG_CTL0 |= trace_mode;
}
}
/*!
\brief enable peripheral behavior when the mcu is in debug mode
\param[in] dbg_periph: refer to dbg_periph_enum
only one parameter can be selected which are shown as below:
\arg DBG_FWDGT_HOLD: debug FWDGT kept when core is halted
\arg DBG_WWDGT_HOLD: debug WWDGT kept when core is halted
\arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,14,15,16,22,23,40,41,42,43,44,50,51): hold TIMERx counter when core is halted
\arg DBG_I2Cx_HOLD (x=0,1,2,3): hold I2Cx smbus when core is halted
\arg DBG_CANx_HOLD (x=0,1,2): hold CANx when core is halted
\arg DBG_RTC_HOLD: hold RTC calendar and wakeup counter when core is halted
\param[out] none
\retval none
*/
void dbg_periph_enable(dbg_periph_enum dbg_periph)
{
DBG_REG_VAL(dbg_periph) |= BIT(DBG_BIT_POS(dbg_periph));
}
/*!
\brief disable peripheral behavior when the mcu is in debug mode
\param[in] dbg_periph: refer to dbg_periph_enum
only one parameter can be selected which are shown as below:
\arg DBG_FWDGT_HOLD: debug FWDGT kept when core is halted
\arg DBG_WWDGT_HOLD: debug WWDGT kept when core is halted
\arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,14,15,16,22,23,40,41,42,43,44,50,51): hold TIMERx counter when core is halted
\arg DBG_I2Cx_HOLD (x=0,1,2,3): hold I2Cx smbus when core is halted
\arg DBG_CANx_HOLD (x=0,1,2): hold CANx when core is halted
\arg DBG_RTC_HOLD: hold RTC calendar and wakeup counter when core is halted
\param[out] none
\retval none
*/
void dbg_periph_disable(dbg_periph_enum dbg_periph)
{
DBG_REG_VAL(dbg_periph) &= ~BIT(DBG_BIT_POS(dbg_periph));
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,262 @@
/*!
\file gd32h75e_edout.c
\brief EDOUT driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_edout.h"
/* EDOUT register bit offset */
#define LOC_LOCMAX_MIN ((uint32_t)0x0000000FU) /*!< LOCMAX fields minimum value */
#define LOC_LOCMAX_STEP ((uint32_t)0x00000004U) /*!< LOCMAX fields step value */
#define OCNT_PDC_OFFSET ((uint32_t)0x00000010U) /*!< bit offset of PDC in EDOUT_OCNT */
#define ZCR_ZOWH_OFFSET ((uint32_t)0x00000010U) /*!< bit offset of ZOWH in EDOUT_ZCR */
/*!
\brief deinitialize EDOUT
\param[in] none
\param[out] none
\retval none
*/
void edout_deinit(void)
{
/* reset EDOUT */
rcu_periph_reset_enable(RCU_EDOUTRST);
rcu_periph_reset_disable(RCU_EDOUTRST);
}
/*!
\brief initialize EDOUT
\param[in] pol: the active polarity of the B-phase output signal selection
only one parameter can be selected which is shown as below:
\arg EDOUT_POL_POSITIVE: active polarity is positive
\arg EDOUT_POL_NEGATIVE: active polarity is negative
\param[in] max_loc: (max_loc+1) must be a multiple of four between 16~65536 (e.g. 0x000F: The maximum location value is 16 (16=4*4))
\param[in] cur_loc: current location value, 0~locmax (locmax is the LOCMAX bit fields value of EDOUT_LOC register)
\param[out] none
\retval none
*/
void edout_init(uint32_t pol, uint32_t max_loc, uint32_t cur_loc)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_EDOUT_B_PHASE_ACTIVE_POL(pol)) {
fw_debug_report_err(EDOUT_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
} else if(NOT_EDOUT_MAX_LOCATION_VAL(max_loc)) {
fw_debug_report_err(EDOUT_MODULE_ID, API_ID(0x0002U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_EDOUT_CUR_LOCATION_VAL(cur_loc)) {
fw_debug_report_err(EDOUT_MODULE_ID, API_ID(0x0002U), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* reset polarity of the B-phase */
EDOUT_CTL &= ~EDOUT_CTL_POL;
/* set polarity of the B-phase */
EDOUT_CTL = pol;
/* reset the maximum location value */
EDOUT_LOC &= ~EDOUT_LOC_LOCMAX;
/* check the maximum location value */
if(LOC_LOCMAX_MIN > max_loc) {
max_loc = LOC_LOCMAX_MIN;
}
while(0U != ((max_loc + 1U) % LOC_LOCMAX_STEP)) {
max_loc++;
}
/* set the maximum location value */
EDOUT_LOC = max_loc & EDOUT_LOC_LOCMAX;
/* reset the current location value */
EDOUT_LCNT &= ~EDOUT_LCNT_LOCCNT;
/* set the current location value */
EDOUT_LCNT = cur_loc & EDOUT_LCNT_LOCCNT;
}
}
/*!
\brief enable EDOUT
\param[in] none
\param[out] none
\retval none
*/
void edout_enable(void)
{
EDOUT_ENABLE |= EDOUT_ENABLE_EDOUTEN;
}
/*!
\brief disable EDOUT
\param[in] none
\param[out] none
\retval none
*/
void edout_disable(void)
{
EDOUT_ENABLE &= ~EDOUT_ENABLE_EDOUTEN;
}
/*!
\brief set B-phase active polarity
\param[in] pol: the active polarity of the B-phase output signal selection
only one parameter can be selected which is shown as below:
\arg EDOUT_POL_POSITIVE: active polarity is positive
\arg EDOUT_POL_NEGATIVE: active polarity is negative
\param[out] none
\retval none
*/
void edout_polarity_config(uint32_t pol)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_EDOUT_B_PHASE_ACTIVE_POL(pol)) {
fw_debug_report_err(EDOUT_MODULE_ID, API_ID(0x0005U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
EDOUT_CTL = pol;
}
}
/*!
\brief set the maximum location value for one rotation
\param[in] max_loc: (max_loc+1) must be a multiple of four between 16~65536, e.g. 0x000F: The maximum location value is 16
\param[out] none
\retval none
*/
void edout_max_location_value_config(uint32_t max_loc)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_EDOUT_MAX_LOCATION_VAL(max_loc)) {
fw_debug_report_err(EDOUT_MODULE_ID, API_ID(0x0006U), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
EDOUT_LOC = max_loc & EDOUT_LOC_LOCMAX;
}
}
/*!
\brief update the output counter, used to set the phase difference and the number of edges for the next update period
\param[in] num_edges: edge count, value range is -32768~32767, positive means clockwise rotation, negative means counter-clockwise rotation
\param[in] phase_diff: phase difference, value range is 2~65535, in units of PCLK
\param[out] none
\retval none
*/
void edout_output_counter_update(int16_t num_edges, uint16_t phase_diff)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_EDOUT_PHASE_DIFF_VAL(phase_diff)) {
fw_debug_report_err(EDOUT_MODULE_ID, API_ID(0x0007U), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
EDOUT_OCNT = ((uint32_t)num_edges & EDOUT_OCNT_EDGC) | ((uint32_t)phase_diff << OCNT_PDC_OFFSET);
}
}
/*!
\brief set the current location value
\param[in] cur_loc: current location value, 0~locmax (locmax is the LOCMAX bit fields value of EDOUT_LOC register)
\param[out] none
\retval none
*/
void edout_current_location_config(uint32_t cur_loc)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_EDOUT_CUR_LOCATION_VAL(cur_loc)) {
fw_debug_report_err(EDOUT_MODULE_ID, API_ID(0x0008U), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
EDOUT_LCNT = cur_loc & EDOUT_LCNT_LOCCNT;
}
}
/*!
\brief get the current location value
\param[in] none
\param[out] none
\retval current location value, 0~locmax (locmax is the LOCMAX bit fields value of EDOUT_LOC register)
*/
uint16_t edout_current_location_get(void)
{
return (uint16_t)EDOUT_LCNT;
}
/*!
\brief configure Z-phase output mode
\param[in] mode: Z-phase output mode
only one parameter can be selected which is shown as below:
\arg EDOUT_Z_OUTPUT_MODE0: output according to the current location
\arg EDOUT_Z_OUTPUT_MODE1: output according to the number of edges
\param[out] none
\retval none
*/
void edout_z_output_mode_config(uint32_t mode)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_EDOUT_Z_PHASE_OUTPUT_MODE(mode)) {
fw_debug_report_err(EDOUT_MODULE_ID, API_ID(0x000AU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* reset the Z-phase output mode */
EDOUT_ZCR &= ~EDOUT_ZCR_ZOMD;
/* set the Z-phase output mode */
EDOUT_ZCR |= mode;
}
}
/*!
\brief configure Z-phase output start location and width
\param[in] start_loc: Z-phase output start location,
when Z-phase output mode select EDOUT_Z_OUTPUT_MODE0: 0~locmax (locmax is the LOCMAX bit fields value of EDOUT_LOC register)
when Z-phase output mode select EDOUT_Z_OUTPUT_MODE1: 0~edges (edges is the EDGC bit fields value of EDOUT_OCNT register)
\param[in] width: Z-phase output width
when Z-phase output mode select EDOUT_Z_OUTPUT_MODE0: 0~(locmax - start_loc) (locmax is the LOCMAX bit fields value of EDOUT_LOC register)
when Z-phase output mode select EDOUT_Z_OUTPUT_MODE1: 0~(edges - start_loc) (edges is the EDGC bit fields value of EDOUT_OCNT register)
\param[out] none
\retval none
*/
void edout_z_output_start_loc_and_width_config(uint32_t start_loc, uint32_t width)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_EDOUT_Z_PHASE_START_LOCATION_VAL(start_loc)) {
fw_debug_report_err(EDOUT_MODULE_ID, API_ID(0x000BU), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_EDOUT_Z_PHASE_WIDTH_VAL(width)) {
fw_debug_report_err(EDOUT_MODULE_ID, API_ID(0x000BU), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* reset the Z-phase output start location and output width */
EDOUT_ZCR &= ~(EDOUT_ZCR_ZOSP | EDOUT_ZCR_ZOWH);
/* set the Z-phase output start location and output width */
EDOUT_ZCR |= (start_loc & EDOUT_ZCR_ZOSP) | ((width << ZCR_ZOWH_OFFSET) & EDOUT_ZCR_ZOWH);
}
}
@@ -0,0 +1,630 @@
/*!
\file gd32h75e_efuse.c
\brief EFUSE driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_efuse.h"
/* FMC register bit offset */
#define EFUSE_CTL_AES_KEY_CRC_OFFSET ((uint32_t)0x00000018U) /*!< bit offset of AES_KEY_CRC in EFUSE_CTL register*/
#define EFUSE_CTL_MPVEN_OFFSET ((uint32_t)0x0000000FU) /*!< bit offset of MPVEN in EFUSE_CTL register*/
#define EFUSE_STAT_LDO_RDY_OFFSET ((uint32_t)0x00000004U) /*!< bit offset of LDO_RDY in EFUSE_STAT register*/
#define EFUSE_ADDR_EFSIZE_OFFSET ((uint32_t)0x0000000AU) /*!< EFSIZE OFFSET in register EFUSE_ADDR */
#define EFUSE_TIMEOUT ((uint32_t)0x0000FFFFU) /*!< EFUSE operation timeout value */
#define USER_CTL_NDBG0 BIT(8) /*!< debug mode setting bit0 in register EFUSE_USER_CTL */
static uint32_t para_start_efaddr[EFUSE_PARA_CNT] = {USER_CTL_EFADDR, MCU_RESERVED_EFADDR, DP_EFADDR, AES_KEY_EFADDR, USER_DATA_EFADDR};
static uint32_t para_reg_start_addr[EFUSE_PARA_CNT] = {EFUSE_USER_CTL_REG_ADDR, EFUSE_MCU_RSV_REG_ADDR, EFUSE_DP_REG_ADDR, EFUSE_AES_KEY_REG_ADDR, EFUSE_USER_DATA_REG_ADDR};
static efuse_state_enum efuse_ready_wait(uint32_t efuse_flag, uint32_t timeout);
/*!
\brief read system parameters from EFUSE macro to registers (API_ID(0x0001U))
\param[in] ef_addr: start address of the system parameters to be read
only one parameter can be selected which is shown as below:
\arg USER_CTL_EFADDR: user control parameter start address
\arg MCU_RESERVED_EFADDR: MCU reserved parameter start address
\arg DP_EFADDR: debug password parameter start address
\arg USER_DATA_EFADDR: user data parameter start address
\param[in] size: size of the system parameters to be read
only one parameter can be selected which is shown as below:
\arg USER_CTL_MCU_RESERVED_SIZE: user control parameter size,MCU reserved parameter size
\arg DP_SIZE: debug password parameter size
\arg USER_DATA_SIZE: user data parameter size
\param[out] buf: the buffer for data read from EFUSE macro
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus efuse_read(uint32_t ef_addr, uint32_t size, uint32_t buf[])
{
ErrStatus status = SUCCESS;
uint32_t timeout = EFUSE_TIMEOUT;
efuse_state_enum efuse_state;
uint32_t reg_addr = 0U;
uint32_t i = 0U;
uint32_t number = 0U;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_EFUSE_ADDR(ef_addr)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0001U), ERR_PARAM_INVALID);
} else if(NOT_EFUSE_SIZE(size)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0001U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
switch(ef_addr) {
case USER_CTL_EFADDR:
status = ERROR;
break;
case MCU_RESERVED_EFADDR:
/* read MCU reserved data */
reg_addr = EFUSE_MCU_RSV_REG_ADDR;
number = 1U;
break;
case DP_EFADDR:
/* read debug password */
if(RESET != (EFUSE_USER_CTL & EFUSE_USER_CTL_DPLK)) {
if(RESET != (EFUSE_USER_CTL & EFUSE_USER_CTL_JTAGNSW)) {
if((RESET != (EFUSE_USER_CTL & USER_CTL_NDBG0))) {
status = ERROR;
}
}
}
if(SUCCESS == status) {
reg_addr = EFUSE_DP_REG_ADDR;
number = 2U;
}
break;
case USER_DATA_EFADDR:
/* read user data */
reg_addr = EFUSE_USER_DATA_REG_ADDR;
number = 4U;
break;
default:
status = ERROR;
break;
}
if(ERROR == status) {
return status;
}
/* clear the RDIF bit if it is SET */
efuse_flag_clear(EFUSE_FLAG_READ_COMPLETE_CLR);
/* reset the EFRW bit in EFUSE_CTL */
EFUSE_CTL &= ~EFUSE_CTL_EFRW;
/* write the desired efuse address and size to the EFUSE_ADDR register */
EFUSE_ADDR = (uint32_t)((size << EFUSE_ADDR_EFSIZE_OFFSET) | ef_addr);
/* start array read EFUSE operation */
EFUSE_CTL |= EFUSE_CTL_EFSTR;
/* wait for the operation to complete */
efuse_state = efuse_ready_wait(EFUSE_FLAG_READ_COMPLETE, timeout);
if(EFUSE_READY != efuse_state) {
status = ERROR;
}
/* read EFUSE register */
for(i = 0U; i < number; i++) {
buf[i] = REG32(reg_addr + (4U * i));
}
}
return status;
}
/*!
\brief program register values to EFUSE macro system parameters (API_ID(0x0002U))
\param[in] ef_addr: the EFUSE address to be programmed, pgm_addr cannot exceed 384, and must be an integral multiple of 8
\param[in] size: byte count to program, (1~16)
\param[in] buf: the buffer for data written to EFUSE macro
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus efuse_write(uint32_t ef_addr, uint32_t size, uint8_t *buf)
{
uint32_t i;
uint32_t reg_addr;
uint32_t byte_offset_in_reg;
uint32_t cnt;
ErrStatus status = SUCCESS;
uint32_t para_index;
uint32_t tmp_buf_8;
uint32_t buf_addr;
uint32_t timeout = EFUSE_TIMEOUT;
efuse_state_enum efuse_state;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_EFUSE_VALID_SIZE(size)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
} else if(NOT_EFUSE_VALID_ADDR(ef_addr)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
} else if(NOT_EFUSE_VALID_ADDR_CONFIG5(ef_addr, size)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
} else if(NOT_EFUSE_VALID_ADDR_CONFIG4(ef_addr, size)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
} else if(NOT_EFUSE_VALID_ADDR_CONFIG3(ef_addr, size)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
} else if(NOT_EFUSE_VALID_ADDR_CONFIG2(ef_addr, size)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
} else if(NOT_EFUSE_VALID_ADDR_CONFIG1(ef_addr, size)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
} else if(NOT_EFUSE_VALID_ADDR_CONFIG0(ef_addr, size)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
} else if(NOT_VALID_POINTER(buf)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0002U), ERR_PARAM_POINTER);
} else
#endif
{
for(i = EFUSE_PARA_CNT; i > 0U; i--) {
if(ef_addr >= para_start_efaddr[i - 1U]) {
break;
}
}
/* get the index of parameter to be programmed */
para_index = i - 1U;
reg_addr = (unsigned int)para_reg_start_addr[para_index] + (ef_addr - para_start_efaddr[para_index]) / 32U * 4U;
byte_offset_in_reg = ((ef_addr - para_start_efaddr[para_index]) / 8U) % 4U;
/* clear the PGIF bit if it is SET */
efuse_flag_clear(EFUSE_FLAG_PROGRAM_COMPLETE_CLR);
/* set the EFRW bit in EFUSE_CTL */
EFUSE_CTL |= EFUSE_CTL_EFRW;
/* write the desired efuse address and size to the EFUSE_ADDR register */
EFUSE_ADDR = (uint32_t)((size << EFUSE_ADDR_EFSIZE_OFFSET) | ef_addr);
buf_addr = (uint32_t)buf;
while(size) {
if((0U != byte_offset_in_reg) || ((0U == byte_offset_in_reg) && (size < 4U))) {
cnt = size < (4U - byte_offset_in_reg) ? size : 4U - byte_offset_in_reg;
for(i = 0U; i < cnt; i++) {
tmp_buf_8 = buf_addr;
/* write the data to the corresponding register */
tmp_buf_8 += i;
REG32(reg_addr) |= (((uint32_t)(*(uint8_t *)(tmp_buf_8))) << ((byte_offset_in_reg + i) * 8U));
}
size -= cnt;
reg_addr += 4U;
byte_offset_in_reg = 0U;
buf_addr += cnt;
} else {
cnt = size / 4U;
for(i = 0U; i < cnt; i++) {
tmp_buf_8 = buf_addr;
/* write the data to the corresponding register */
tmp_buf_8 += (i * 4U);
REG32(reg_addr) = (uint32_t)(*(uint32_t *)(tmp_buf_8));
reg_addr += 4U;
}
size -= cnt * 4U;
buf_addr += cnt * 4U;
}
}
/* start EFUSE program operation */
EFUSE_CTL |= EFUSE_CTL_EFSTR;
/* wait for the operation to complete */
efuse_state = efuse_ready_wait(EFUSE_FLAG_PROGRAM_COMPLETE, timeout);
if(EFUSE_READY != efuse_state) {
status = ERROR;
}
}
return status;
}
/*!
\brief program all user control parameters (API_ID(0x0003U))
\param[in] buf: the buffer of data written to efuse
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus efuse_user_control_write(uint8_t *buf)
{
ErrStatus status = SUCCESS;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(buf)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0003U), ERR_PARAM_POINTER);
} else
#endif
{
status = efuse_write(USER_CTL_EFADDR, USER_CTL_MCU_RESERVED_SIZE, buf);
}
return status;
}
/*!
\brief program all MCU reserved parameters (API_ID(0x0004U))
\param[in] buf: the buffer of data written to efuse
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus efuse_mcu_reserved_write(uint8_t *buf)
{
ErrStatus status = SUCCESS;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(buf)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0004U), ERR_PARAM_POINTER);
} else
#endif
{
status = efuse_write(MCU_RESERVED_EFADDR, USER_CTL_MCU_RESERVED_SIZE, buf);
}
return status;
}
/*!
\brief program all debug password parameters (API_ID(0x0005U))
\param[in] buf: the buffer of data written to efuse
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus efuse_dp_write(uint8_t *buf)
{
ErrStatus status = SUCCESS;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(buf)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0005U), ERR_PARAM_POINTER);
} else
#endif
{
status = efuse_write(DP_EFADDR, DP_SIZE, buf);
}
return status;
}
/*!
\brief program all AES key parameters (API_ID(0x0006U))
\param[in] buf: the buffer of data written to efuse
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus efuse_aes_key_write(uint8_t *buf)
{
ErrStatus status = SUCCESS;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(buf)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0006U), ERR_PARAM_POINTER);
} else
#endif
{
status = efuse_write(AES_KEY_EFADDR, AES_KEY_SIZE, buf);
}
return status;
}
/*!
\brief program all user data parameters (API_ID(0x0007U))
\param[in] buf: the buffer of data written to efuse
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus efuse_user_data_write(uint8_t *buf)
{
ErrStatus status = SUCCESS;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(buf)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0007U), ERR_PARAM_POINTER);
} else
#endif
{
status = efuse_write(USER_DATA_EFADDR, USER_DATA_SIZE, buf);
}
return status;
}
/*!
\brief get 8-bits CRC calculation result value of AES key (API_ID(0x0008U))
\param[in] none
\param[out] none
\retval 8-bits CRC calculation result value of AES key
*/
uint8_t efuse_aes_key_crc_get(void)
{
return (uint8_t)((EFUSE_CTL & EFUSE_CTL_AES_KEY_CRC) >> EFUSE_CTL_AES_KEY_CRC_OFFSET);
}
/*!
\brief enable monitor program voltage function (API_ID(0x0009U))
\param[in] none
\param[out] none
\retval none
*/
void efuse_monitor_program_voltage_enable(void)
{
uint32_t ctl_reg;
ctl_reg = EFUSE_CTL;
/* enable monitor program voltage function */
ctl_reg |= EFUSE_CTL_MPVEN;
EFUSE_CTL = ctl_reg;
}
/*!
\brief disable monitor program voltage function (API_ID(0x000AU))
\param[in] none
\param[out] none
\retval none
*/
void efuse_monitor_program_voltage_disable(void)
{
uint32_t ctl_reg;
ctl_reg = EFUSE_CTL;
/* disable monitor program voltage function */
ctl_reg &= ~EFUSE_CTL_MPVEN;
EFUSE_CTL = ctl_reg;
}
/*!
\brief get monitor program voltage function (API_ID(0x000BU))
\param[in] none
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus efuse_monitor_program_voltage_get(void)
{
FlagStatus mpven_state = RESET;
if(EFUSE_CTL_MPVEN == (uint32_t)(EFUSE_CTL & EFUSE_CTL_MPVEN)) {
mpven_state = SET;
} else {
mpven_state = RESET;
}
return mpven_state;
}
/*!
\brief get ldo ready signal (API_ID(0x000CU))
\param[in] none
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus efuse_ldo_ready_get(void)
{
FlagStatus ldo_ready_state = RESET;
if(EFUSE_STAT_LDO_RDY == (uint32_t)(EFUSE_STAT & EFUSE_STAT_LDO_RDY)) {
ldo_ready_state = SET;
} else {
ldo_ready_state = RESET;
}
return ldo_ready_state;
}
/*!
\brief check EFUSE flag is set or not (API_ID(0x000DU))
\param[in] flag: specifies to get a flag
only one parameter can be selected which is shown as below:
\arg EFUSE_FLAG_ILLEGAL_ACCESS_ERR: illegal access error flag
\arg EFUSE_FLAG_PROGRAM_COMPLETE: programming operation completion flag
\arg EFUSE_FLAG_READ_COMPLETE: read operation completion flag
\arg EFUSE_FLAG_PROGRAM_VOLTAGE_ERR: program voltage setting error flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus efuse_flag_get(uint32_t flag)
{
FlagStatus flag_temp = RESET;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_EFUSE_FLAG(flag)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x000DU), ERR_PARAM_INVALID);
} else
#endif
{
if(EFUSE_STAT & (uint32_t)flag) {
flag_temp = SET;
} else {
flag_temp = RESET;
}
}
return flag_temp;
}
/*!
\brief clear EFUSE pending flag (API_ID(0x000EU))
\param[in] flag: specifies to clear a flag
only one parameter can be selected which is shown as below:
\arg EFUSE_FLAG_ILLEGAL_ACCESS_ERR_CLR: clear illegal access error flag
\arg EFUSE_FLAG_PROGRAM_COMPLETE_CLR: clear programming operation completion flag
\arg EFUSE_FLAG_READ_COMPLETE_CLR: clear read operation completion flag
\arg EFUSE_FLAG_PROGRAM_VOLTAGE_ERR_CLR: clear program voltage setting error interrupt flag
\param[out] none
\retval none
*/
void efuse_flag_clear(uint32_t flag)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_EFUSE_FLAG_CLR(flag)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x000EU), ERR_PARAM_INVALID);
} else
#endif
{
EFUSE_STATC |= (uint32_t)flag;
}
}
/*!
\brief enable EFUSE interrupt (API_ID(0x000FU))
\param[in] interrupt: specifies an interrupt to enbale
only one parameter can be selected which is shown as below:
\arg EFUSE_INT_ILLEGAL_ACCESS_ERR: illegal access error interrupt
\arg EFUSE_INT_PROGRAM_COMPLETE: programming operation completion interrupt
\arg EFUSE_INT_READ_COMPLETE: read operation completion interrupt
\arg EFUSE_INT_PROGRAM_VOLTAGE_ERR: program voltage setting error interrupt
\param[out] none
\retval none
*/
void efuse_interrupt_enable(uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_EFUSE_INT(interrupt)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x000FU), ERR_PARAM_INVALID);
} else
#endif
{
EFUSE_CTL = (uint32_t)interrupt;
}
}
/*!
\brief disable EFUSE interrupt (API_ID(0x0010U))
\param[in] interrupt: specifies an interrupt to disbale
only one parameter can be selected which is shown as below:
\arg EFUSE_INT_ILLEGAL_ACCESS_ERR: illegal access error interrupt
\arg EFUSE_INT_PROGRAM_COMPLETE: programming operation completion interrupt
\arg EFUSE_INT_READ_COMPLETE: read operation completion interrupt
\arg EFUSE_INT_PROGRAM_VOLTAGE_ERR: program voltage setting error interrupt
\param[out] none
\retval none
*/
void efuse_interrupt_disable(uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_EFUSE_INT(interrupt)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0010U), ERR_PARAM_INVALID);
} else
#endif
{
EFUSE_CTL &= ~(uint32_t)interrupt;
}
}
/*!
\brief check EFUSE interrupt flag is set or not (API_ID(0x0011U))
\param[in] int_flag: specifies to get a flag
only one parameter can be selected which is shown as below:
\arg EFUSE_INT_FLAG_ILLEGAL_ACCESS_ERR: illegal access error interrupt
\arg EFUSE_INT_FLAG_PROGRAM_COMPLETE: programming operation completion interrupt
\arg EFUSE_INT_FLAG_READ_COMPLETE: read operation completion interrupt
\arg EFUSE_INT_FLAG_PROGRAM_VOLTAGE_ERR: program voltage setting error interrupt
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus efuse_interrupt_flag_get(efuse_interrupt_flag_enum int_flag)
{
uint32_t intenable = 0U, flagstatus = 0U;
/* get the interrupt enable bit status */
intenable = (EFUSE_REG_VAL(int_flag) & BIT(EFUSE_BIT_POS(int_flag)));
/* get the corresponding flag bit status */
flagstatus = (EFUSE_REG_VAL2(int_flag) & BIT(EFUSE_BIT_POS2(int_flag)));
if(flagstatus && intenable) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear EFUSE pending interrupt flag (API_ID(0x0012U))
\param[in] int_flag: specifies to clear a flag
only one parameter can be selected which is shown as below:
\arg EFUSE_INT_FLAG_ILLEGAL_ACCESS_ERR_CLR: clear illegal access error interrupt flag
\arg EFUSE_INT_FLAG_PROGRAM_COMPLETE_CLR: clear programming operation completion interrupt flag
\arg EFUSE_INT_FLAG_READ_COMPLETE_CLR: clear operation completion interrupt flag
\arg EFUSE_INT_FLAG_PROGRAM_VOLTAGE_ERR_CLR: clear program voltage setting error interrupt flag
\param[out] none
\retval none
*/
void efuse_interrupt_flag_clear(uint32_t int_flag)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_EFUSE_INT_FLAG_CLR(int_flag)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
EFUSE_STATC |= (uint32_t)int_flag;
}
}
/*!
\brief check whether EFUSE is ready or not (API_ID(0x0013U))
\param[in] flag:
only one parameter can be selected which is shown as below:
\arg EFUSE_FLAG_ILLEGAL_ACCESS_ERR: illegal access error flag
\arg EFUSE_FLAG_PROGRAM_COMPLETE: programming operation completion flag
\arg EFUSE_FLAG_READ_COMPLETE: read operation completion flag
\arg EFUSE_FLAG_PROGRAM_VOLTAGE_ERR: program voltage setting error flag
\param[out] none
\retval state of EFUSE
\arg EFUSE_READY: EFUSE operation has been completed
\arg EFUSE_BUSY: EFUSE operation is in progress
\arg EFUSE_IAERR: illegal access error
\arg EFUSE_PVERR: program voltage setting error
\arg EFUSE_TOERR: EFUSE timeout error
*/
static efuse_state_enum efuse_ready_wait(uint32_t efuse_flag, uint32_t timeout)
{
efuse_state_enum efuse_state = EFUSE_BUSY;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_EFUSE_FLAG(efuse_flag)) {
fw_debug_report_err(EFUSE_MODULE_ID, API_ID(0x0013U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* wait for EFUSE ready */
do {
/* get EFUSE flag set or not */
if(EFUSE_STAT & (uint32_t)efuse_flag) {
efuse_state = EFUSE_READY;
} else if(EFUSE_STAT & EFUSE_STAT_IAERRIF) {
efuse_state = EFUSE_IAERR;
} else if(EFUSE_STAT & EFUSE_STAT_PVIF) {
efuse_state = EFUSE_PVERR;
} else {
/* illegal parameters */
}
timeout--;
} while((EFUSE_BUSY == efuse_state) && (0U != timeout));
if(EFUSE_BUSY == efuse_state) {
efuse_state = EFUSE_TOERR;
}
}
/* return the EFUSE state */
return efuse_state;
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,254 @@
/*!
\file gd32h75e_exti.c
\brief EXTI driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_exti.h"
#define EXTI_REG_RESET_VALUE ((uint32_t)0x00000000U)
/*!
\brief deinitialize the EXTI
\param[in] none
\param[out] none
\retval none
*/
void exti_deinit(void)
{
/* reset the value of all the EXTI registers */
EXTI_INTEN0 = EXTI_REG_RESET_VALUE;
EXTI_EVEN0 = EXTI_REG_RESET_VALUE;
EXTI_RTEN0 = EXTI_REG_RESET_VALUE;
EXTI_FTEN0 = EXTI_REG_RESET_VALUE;
EXTI_SWIEV0 = EXTI_REG_RESET_VALUE;
EXTI_INTEN1 = EXTI_REG_RESET_VALUE;
EXTI_EVEN1 = EXTI_REG_RESET_VALUE;
EXTI_RTEN1 = EXTI_REG_RESET_VALUE;
EXTI_FTEN1 = EXTI_REG_RESET_VALUE;
EXTI_SWIEV1 = EXTI_REG_RESET_VALUE;
}
/*!
\brief initialize the EXTI line x
\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\arg EXTI_x (x=0..37): EXTI line x
\param[in] mode: interrupt or event mode, refer to exti_mode_enum
only one parameter can be selected which is shown as below:
\arg EXTI_INTERRUPT: interrupt mode
\arg EXTI_EVENT: event mode
\param[in] trig_type: interrupt and event trigger type, refer to exti_trig_type_enum
only one parameter can be selected which is shown as below:
\arg EXTI_TRIG_RISING: rising edge trigger
\arg EXTI_TRIG_FALLING: falling trigger
\arg EXTI_TRIG_BOTH: rising and falling trigger
\arg EXTI_TRIG_NONE: without rising edge or falling edge trigger
\param[out] none
\retval none
*/
void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type)
{
/* reset the EXTI line x */
EXTI_INTEN(EXTI_REG_VAL(linex)) &= ~EXTI_BIT_POS(linex);
EXTI_EVEN(EXTI_REG_VAL(linex)) &= ~EXTI_BIT_POS(linex);
EXTI_RTEN(EXTI_REG_VAL(linex)) &= ~EXTI_BIT_POS(linex);
EXTI_FTEN(EXTI_REG_VAL(linex)) &= ~EXTI_BIT_POS(linex);
/* set the EXTI mode and enable the interrupts or events from EXTI line x */
switch(mode) {
case EXTI_INTERRUPT:
EXTI_INTEN(EXTI_REG_VAL(linex)) |= EXTI_BIT_POS(linex);
break;
case EXTI_EVENT:
EXTI_EVEN(EXTI_REG_VAL(linex)) |= EXTI_BIT_POS(linex);
break;
default:
break;
}
/* set the EXTI trigger type */
switch(trig_type) {
case EXTI_TRIG_RISING:
EXTI_RTEN(EXTI_REG_VAL(linex)) |= EXTI_BIT_POS(linex);
EXTI_FTEN(EXTI_REG_VAL(linex)) &= ~EXTI_BIT_POS(linex);
break;
case EXTI_TRIG_FALLING:
EXTI_RTEN(EXTI_REG_VAL(linex)) &= ~EXTI_BIT_POS(linex);
EXTI_FTEN(EXTI_REG_VAL(linex)) |= EXTI_BIT_POS(linex);
break;
case EXTI_TRIG_BOTH:
EXTI_RTEN(EXTI_REG_VAL(linex)) |= EXTI_BIT_POS(linex);
EXTI_FTEN(EXTI_REG_VAL(linex)) |= EXTI_BIT_POS(linex);
break;
case EXTI_TRIG_NONE:
default:
break;
}
}
/*!
\brief enable the interrupts from EXTI line x
\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\arg EXTI_x (x=0..37): EXTI line x
\param[out] none
\retval none
*/
void exti_interrupt_enable(exti_line_enum linex)
{
EXTI_INTEN(EXTI_REG_VAL(linex)) |= EXTI_BIT_POS(linex);
}
/*!
\brief disable the interrupts from EXTI line x
\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\arg EXTI_x (x=0..37): EXTI line x
\param[out] none
\retval none
*/
void exti_interrupt_disable(exti_line_enum linex)
{
EXTI_INTEN(EXTI_REG_VAL(linex)) &= ~EXTI_BIT_POS(linex);
}
/*!
\brief enable the events from EXTI line x
\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\arg EXTI_x (x=0..37): EXTI line x
\param[out] none
\retval none
*/
void exti_event_enable(exti_line_enum linex)
{
EXTI_EVEN(EXTI_REG_VAL(linex)) |= EXTI_BIT_POS(linex);
}
/*!
\brief disable the events from EXTI line x
\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\arg EXTI_x (x=0..37): EXTI line x
\param[out] none
\retval none
*/
void exti_event_disable(exti_line_enum linex)
{
EXTI_EVEN(EXTI_REG_VAL(linex)) &= ~EXTI_BIT_POS(linex);
}
/*!
\brief enable the software interrupt event from EXTI line x
\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\arg EXTI_x (x=0..37): EXTI line x
\param[out] none
\retval none
*/
void exti_software_interrupt_enable(exti_line_enum linex)
{
EXTI_SWIEV(EXTI_REG_VAL(linex)) |= EXTI_BIT_POS(linex);
}
/*!
\brief disable the software interrupt event from EXTI line x
\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\arg EXTI_x (x=0..37): EXTI line x
\param[out] none
\retval none
*/
void exti_software_interrupt_disable(exti_line_enum linex)
{
EXTI_SWIEV(EXTI_REG_VAL(linex)) &= ~EXTI_BIT_POS(linex);
}
/*!
\brief get EXTI line x interrupt pending flag
\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\arg EXTI_x (x=0..37): EXTI line x
\param[out] none
\retval FlagStatus: status of flag (RESET or SET)
*/
FlagStatus exti_flag_get(exti_line_enum linex)
{
if(RESET != (EXTI_PD(EXTI_REG_VAL(linex)) & EXTI_BIT_POS(linex))) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear EXTI line x interrupt pending flag
\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\arg EXTI_x (x=0..37): EXTI line x
\param[out] none
\retval none
*/
void exti_flag_clear(exti_line_enum linex)
{
EXTI_PD(EXTI_REG_VAL(linex)) = EXTI_BIT_POS(linex);
}
/*!
\brief get EXTI line x interrupt pending flag
\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\arg EXTI_x (x=0..37): EXTI line x
\param[out] none
\retval FlagStatus: status of flag (RESET or SET)
*/
FlagStatus exti_interrupt_flag_get(exti_line_enum linex)
{
if(RESET != (EXTI_PD(EXTI_REG_VAL(linex)) & EXTI_BIT_POS(linex))) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear EXTI line x interrupt pending flag
\param[in] linex: EXTI line number, refer to exti_line_enum
only one parameter can be selected which is shown as below:
\arg EXTI_x (x=0..37): EXTI line x
\param[out] none
\retval none
*/
void exti_interrupt_flag_clear(exti_line_enum linex)
{
EXTI_PD(EXTI_REG_VAL(linex)) = EXTI_BIT_POS(linex);
}
@@ -0,0 +1,772 @@
/*!
\file gd32h75e_fac.c
\brief FAC driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_fac.h"
#include <stdio.h>
/*!
\brief reset FAC peripheral
\param[in] none
\param[out] none
\retval none
*/
void fac_deinit(void)
{
rcu_periph_reset_enable(RCU_FACRST);
rcu_periph_reset_disable(RCU_FACRST);
}
/*!
\brief initialize the FAC filter parameter struct with the default values
\param[in] fac_parameter: fac parameter struct
\param[out] none
\retval none
*/
void fac_struct_para_init(fac_parameter_struct *fac_parameter)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_VALID_POINTER(fac_parameter)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x0002U), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
fac_parameter->input_addr = 0U;
fac_parameter->input_size = 0U;
fac_parameter->input_threshold = 0U;
fac_parameter->coeff_addr = 0U;
fac_parameter->coeff_size = 0U;
fac_parameter->output_addr = 0U;
fac_parameter->output_size = 0U;
fac_parameter->output_threshold = 0U;
fac_parameter->clip = 0U;
fac_parameter->func = 0U;
fac_parameter->ipp = 0U;
fac_parameter->ipq = 0U;
fac_parameter->ipr = 0U;
}
}
/*!
\brief initialize the FAC fixed data preload parameter struct with the default values
\param[in] fac_parameter: fac parameter struct
\param[out] none
\retval none
*/
void fac_fixed_data_preload_init(fac_fixed_data_preload_struct *init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_VALID_POINTER(init_struct)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x0003U), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
init_struct->coeffa_size = 0U;
init_struct->coeffa_ctx = 0U;
init_struct->coeffb_size = 0U;
init_struct->coeffb_ctx = 0U;
init_struct->input_size = 0U;
init_struct->input_ctx = 0U;
init_struct->output_size = 0U;
init_struct->output_ctx = 0U;
}
}
/*!
\brief initialize the FAC float data preload parameter struct with the default values
\param[in] fac_parameter: fac parameter struct
\param[out] none
\retval none
*/
void fac_float_data_preload_init(fac_float_data_preload_struct *init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_VALID_POINTER(init_struct)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x0004U), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
init_struct->coeffa_size = 0U;
init_struct->coeffa_ctx = 0U;
init_struct->coeffb_size = 0U;
init_struct->coeffb_ctx = 0U;
init_struct->input_size = 0U;
init_struct->input_ctx = 0U;
init_struct->output_size = 0U;
init_struct->output_ctx = 0U;
}
}
/*!
\brief initialize the FAC peripheral
\param[in] init_struct: the data needed to initialize FAC
input_addr: x0 buffer base address, 0..255
input_size: x0 buffer size, 0..255
input_threshold: FAC_THRESHOLD_1, FAC_THRESHOLD_2,
FAC_THRESHOLD_4, FAC_THRESHOLD_8
coeff_addr: x1 buffer base address, 0..255
coeff_size: x1 buffer size, 0..255
output_addr: Y buffer base address, 0..255
output_size: Y buffer size, 0..255
output_threshold: FAC_THRESHOLD_1, FAC_THRESHOLD_2,
FAC_THRESHOLD_4, FAC_THRESHOLD_8
clip: enable or disable the clipping feature
ipp: value IPP (vector length, number of filter taps, etc.)
ipq: value IPQ (vector length, etc.)
ipr: value IPR (gain, etc.)
\param[out] none
\retval none
*/
void fac_init(fac_parameter_struct *fac_parameter)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_VALID_POINTER(fac_parameter)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x0005U), ERR_PARAM_POINTER);
} else if(NOT_FAC_THRESHOLD(fac_parameter->output_threshold)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x0005U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* FAC_X0BCFG: configure the input X0 buffer */
FAC_X0BCFG = ((((uint32_t)fac_parameter->input_addr) & FAC_X0BCFG_X0B_ADDR) | \
((((uint32_t)fac_parameter->input_size) << 8U) & FAC_X0BCFG_X0B_SIZE));
/* FAC_X0BCFG: configure the input X0 threshold */
FAC_X0BCFG |= (((uint32_t)fac_parameter->input_threshold) & FAC_X0BCFG_X0_WBFF);
/* FAC_X1BCFG: configure the coefficient X1 buffer */
FAC_X1BCFG = ((((uint32_t)fac_parameter->coeff_addr) & FAC_X1BCFG_X1B_ADDR) | \
((((uint32_t)fac_parameter->coeff_size) << 8U) & FAC_X1BCFG_X1B_SIZE));
/* FAC_YBCFG: configure the output Y buffer */
FAC_YBCFG = ((((uint32_t)fac_parameter->output_addr) & FAC_YBCFG_YB_ADDR) | \
((((uint32_t)fac_parameter->output_size) << 8U) & FAC_YBCFG_YB_SIZE));
/* FAC_YBCFG: configure the output Y threshold */
FAC_YBCFG |= (((uint32_t)fac_parameter->output_threshold) & FAC_YBCFG_Y_WBEF);
/* FAC_CTL: configure the state of clip */
FAC_CTL |= ((((uint32_t)fac_parameter->clip) << 15U) & FAC_CTL_CPEN);
}
}
/*!
\brief FAC preload X0 X1 Y fixed buffer
\param[in] init_struct: FAC preload init struct
coeffa_size: size of the coefficient vector A,0~255
coeffa_ctx: [IIR only] content of the coefficient vector A
coeffb_size: size of the coefficient vector B
coeffb_ctx: size of the coefficient vector B
input_size: size of the input data,0~255
input_ctx: content of the input data
output_size: size of the output data,0~255
output_ctx: content of the output data
only one parameter can be selected which is shown as below:
\param[out] none
\retval none
*/
void fac_fixed_buffer_preload(fac_fixed_data_preload_struct *init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_VALID_POINTER(init_struct)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x0006U), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* FAC_PARACFG: configure parameter of filter preload */
FAC_PARACFG = ((uint32_t)init_struct->input_size & FAC_PARACFG_IPP) | \
FUNC_LOAD_X0 | FAC_PARACFG_EXE;
/* load the X0 buffer for input data */
fac_fixed_data_preload(init_struct->input_size, init_struct->input_ctx);
/* configure dma for X0 preload */
/* FAC_PARACFG: configure parameter of filter preload */
FAC_PARACFG = (((uint32_t)init_struct->coeffb_size) & FAC_PARACFG_IPP) | \
((((uint32_t)init_struct->coeffa_size) << 8) & FAC_PARACFG_IPQ) | \
FUNC_LOAD_X1 | FAC_PARACFG_EXE;
/* load the x1 buffer for cofficientB */
fac_fixed_data_preload(init_struct->coeffb_size, (init_struct->coeffb_ctx));
/* load the x1 buffer for cofficientA */
if((NULL != init_struct->coeffa_ctx) && (0U != init_struct->coeffa_size)) {
/* Load the buffer into the internal memory */
fac_fixed_data_preload(init_struct->coeffa_size, (init_struct->coeffa_ctx));
}
/* if need configure to preload output buffer */
if((NULL != init_struct->output_ctx) && (0U != init_struct->output_size)) {
FAC_PARACFG = ((uint32_t)init_struct->output_size & FAC_PARACFG_IPP) | \
FUNC_LOAD_Y | FAC_PARACFG_EXE;
/* load the Y buffer for input data */
fac_fixed_data_preload(init_struct->output_size, init_struct->output_ctx);
}
}
}
/*!
\brief FAC preload X0 X1 Y float buffer
\param[in] init_struct: FAC preload init struct
coeffa_size: size of the coefficient vector A,0~255
coeffa_ctx: [IIR only] content of the coefficient vector A
coeffb_size: size of the coefficient vector B
coeffb_ctx: size of the coefficient vector B
input_size: size of the input data,0~255
input_ctx: content of the input data
output_size: size of the output data,0~255
output_ctx: content of the output data
only one parameter can be selected which is shown as below:
\param[out] none
\retval none
*/
void fac_float_buffer_preload(fac_float_data_preload_struct *init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_VALID_POINTER(init_struct)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x0007U), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* FAC_PARACFG: Config parameter of filter preload */
FAC_PARACFG = ((uint32_t)init_struct->input_size & FAC_PARACFG_IPP) | \
FUNC_LOAD_X0 | FAC_PARACFG_EXE;
/* load the x0 buffer for input data */
fac_float_data_preload(init_struct->input_size, init_struct->input_ctx);
/* configure dma for x0 preload */
/* FAC_PARACFG: Config parameter of filter preload */
FAC_PARACFG = (((uint32_t)init_struct->coeffb_size) & FAC_PARACFG_IPP) | \
((((uint32_t)init_struct->coeffa_size) << 8) & FAC_PARACFG_IPQ) | \
FUNC_LOAD_X1 | FAC_PARACFG_EXE;
/* load the x1 buffer for cofficientB */
fac_float_data_preload(init_struct->coeffb_size, (init_struct->coeffb_ctx));
/* load the x1 buffer for cofficientA */
if((NULL != init_struct->coeffa_ctx) && (0U != init_struct->coeffa_size)) {
/* load the buffer into the internal memory */
fac_float_data_preload(init_struct->coeffa_size, (init_struct->coeffa_ctx));
}
/* if need configure to preload output buffer */
if((NULL != init_struct->output_ctx) && (0U != init_struct->output_size)) {
FAC_PARACFG = ((uint32_t)init_struct->output_size & FAC_PARACFG_IPP) | \
FUNC_LOAD_Y | FAC_PARACFG_EXE;
/* load the Y buffer for input data */
fac_float_data_preload(init_struct->output_size, init_struct->output_ctx);
}
}
}
/*!
\brief FAC preload fixed data pointer
\param[in] array: 16-bit data
\param[in] size: size of data
\param[out] none
\retval none
*/
void fac_fixed_data_preload(uint8_t size, int16_t array[])
{
uint8_t i;
for(i = 0U; i < size; i++) {
FAC_WDATA = ((*((uint16_t*)&array[i])) & FAC_WDATA_WDATA);
}
}
/*!
\brief FAC preload float data pointer
\param[in] data: 32-bit data
\param[in] size: size of data
\param[out] none
\retval none
*/
void fac_float_data_preload(uint8_t size, float array[])
{
uint8_t i;
for(i = 0U; i < size; i++) {
FAC_WDATA = ((*((uint32_t*) & array[i])));
}
}
/*!
\brief FAC reset write and read pointers. the internal control logic,FAC_STAT register and the FAC_PARACFG register is reset
\param[in] none
\param[out] none
\retval none
*/
void fac_reset(void)
{
FAC_CTL |= FAC_CTL_RST;
}
/*!
\brief configure the FAC clip feature
\param[in] cpmod: the state of clip
only one parameter can be selected which is shown as below:
\arg FAC_CP_ENABLE: ENABLE CLIP
\arg FAC_CP_DISABLE: DISABLE CLIP
\param[out] none
\retval none
*/
void fac_clip_config(uint8_t cpmod)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_FAC_CPMODE(cpmod)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x000BU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(FAC_CP_ENABLE == cpmod) {
FAC_CTL |= FAC_CTL_CPEN;
} else {
FAC_CTL &= ~(FAC_CTL_CPEN);
}
}
}
/*!
\brief enable FAC float point format
\param[in] none
\param[out] none
\retval none
*/
void fac_float_enable(void)
{
FAC_CTL |= FAC_CTL_FLTEN;
}
/*!
\brief disable FAC float point format
\param[in] none
\param[out] none
\retval none
*/
void fac_float_disable(void)
{
FAC_CTL &= ~FAC_CTL_FLTEN;
}
/*!
\brief enable the FAC DMA
\param[in] dma_req: dma transfer type
only one parameter can be selected which is shown as below:
\arg FAC_DMA_READ: read buffer dma
\arg FAC_DMA_WRITE: write buffer dma
\param[out] none
\retval none
*/
void fac_dma_enable(uint32_t dma_req)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_FAC_DMA_REQ(dma_req)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x000EU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
FAC_CTL |= dma_req;
}
}
/*!
\brief disable the FAC DMA
\param[in] dma_req: dma transfer type
only one parameter can be selected which is shown as below:
\arg FAC_DMA_READ: read buffer dma
\arg FAC_DMA_WRITE: write buffer dma
\param[out] none
\retval none
*/
void fac_dma_disable(uint32_t dma_req)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_FAC_DMA_REQ(dma_req)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x000FU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
FAC_CTL &= ~dma_req;
}
}
/*!
\brief FAC configure input buffer
\param[in] watermark: threshold of input buffer
FAC_THRESHOLD_1, FAC_THRESHOLD_2,
FAC_THRESHOLD_4, FAC_THRESHOLD_8
\param[in] baseaddr: base address of input buffer, 0..255
\param[in] bufsize: buffer size of input buffer, 0..255
\param[out] none
\retval none
*/
void fac_x0_config(uint32_t watermark, uint8_t baseaddr, uint8_t bufsize)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_FAC_THRESHOLD(watermark)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x0010U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* set base address */
FAC_X0BCFG &= ~FAC_X0BCFG_X0B_ADDR;
FAC_X0BCFG |= ((uint32_t)baseaddr);
/* set buffer size */
FAC_X0BCFG &= ~FAC_X0BCFG_X0B_SIZE;
FAC_X0BCFG |= (((uint32_t)bufsize) << 8U);
/* set watermark */
FAC_X0BCFG &= ~FAC_X0BCFG_X0_WBFF;
FAC_X0BCFG |= watermark;
}
}
/*!
\brief FAC configure coefficient buffer
\param[in] baseaddr: base address of coefficient buffer, 0..255
\param[in] bufsize: buffer size of coefficient buffer, 0..255
\param[out] none
\retval none
*/
void fac_x1_config(uint8_t baseaddr, uint8_t bufsize)
{
/* set base address */
FAC_X1BCFG &= ~FAC_X1BCFG_X1B_ADDR;
FAC_X1BCFG |= ((uint32_t)baseaddr);
/* set buffer size */
FAC_X1BCFG &= ~FAC_X1BCFG_X1B_SIZE;
FAC_X1BCFG |= (((uint32_t)bufsize) << 8U);
}
/*!
\brief FAC configure output buffer
\param[in] watermark: threshold of output buffer
FAC_THRESHOLD_1, FAC_THRESHOLD_2,
FAC_THRESHOLD_4, FAC_THRESHOLD_8
\param[in] baseaddr: base address of output buffer, 0..255
\param[in] bufsize: buffer size of output buffer, 0..255
\param[out] none
\retval none
*/
void fac_y_config(uint32_t watermark, uint8_t baseaddr, uint8_t bufsize)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_FAC_THRESHOLD(watermark)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* set base address */
FAC_YBCFG &= ~FAC_YBCFG_YB_ADDR;
FAC_YBCFG |= ((uint32_t)baseaddr);
/* set buffer size */
FAC_YBCFG &= ~FAC_YBCFG_YB_SIZE;
FAC_YBCFG |= (((uint32_t)bufsize) << 8U);
/* set watermark */
FAC_YBCFG &= ~FAC_YBCFG_Y_WBEF;
FAC_YBCFG |= watermark;
}
}
/*!
\brief FAC configure execute function
\param[in] func: select function to excute
FUNC_CONVO_FIR, FUNC_IIR_DIRECT_FORM_1
\param[in] ipp: parameter of forward coefficient
\param[in] ipq: parameter of backward coefficient
\param[in] ipr: parameter of gain
\param[out] none
\retval none
*/
void fac_function_config(fac_parameter_struct *fac_parameter)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_FAC_FUNC(fac_parameter->func)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x0013U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* set function */
FAC_PARACFG &= ~FAC_PARACFG_FUN;
FAC_PARACFG |= fac_parameter->func;
/* set filter parameter */
FAC_PARACFG &= ~(FAC_PARACFG_IPP | FAC_PARACFG_IPQ | FAC_PARACFG_IPR);
FAC_PARACFG |= ((uint32_t)fac_parameter->ipp) | (((uint32_t)fac_parameter->ipq) << 8U) | (((uint32_t)fac_parameter->ipr) << 16U);
}
}
/*!
\brief start the fac
\param[in] none
\param[out] none
\retval none
*/
void fac_start(void)
{
/* set start */
FAC_PARACFG |= FAC_PARACFG_EXE;
}
/*!
\brief stop the fac
\param[in] none
\param[out] none
\retval none
*/
void fac_stop(void)
{
/* set start */
FAC_PARACFG &= ~FAC_PARACFG_EXE;
}
/*!
\brief finish the filter calculate
\param[in] none
\param[out] none
\retval none
*/
void fac_finish_calculate(void)
{
/* clear execute */
FAC_PARACFG &= ~FAC_PARACFG_EXE;
/* disable read and write interrupt */
fac_interrupt_disable(FAC_CTL_RIE);
fac_interrupt_disable(FAC_CTL_WIE);
/* disable read and write dma */
fac_dma_disable(FAC_DMA_READ);
fac_dma_disable(FAC_DMA_WRITE);
/* reset register and pointer */
FAC_CTL |= FAC_CTL_RST;
}
/*!
\brief FAC write data with fixed ponit format
\param[in] data: 16-bit data
\param[out] none
\retval none
*/
void fac_fixed_data_write(int16_t data)
{
FAC_WDATA_INT = (int16_t)data;
}
/*!
\brief FAC read data with fixed point format
\param[in] none
\param[out] none
\retval 16-bit data
*/
int16_t fac_fixed_data_read(void)
{ int16_t value;
value = (int16_t)FAC_RDATA_INT;
return value;
}
/*!
\brief FAC write data with float ponit format
\param[in] data: 16-bit data
\param[out] none
\retval none
*/
void fac_float_data_write(float data)
{
FAC_WDATA_FLOAT = (float)data;
}
/*!
\brief FAC read data with fixed point format
\param[in] none
\param[out] none
\retval 16-bit data
*/
float fac_float_data_read(void)
{
float value;
value = (float)FAC_RDATA_FLOAT;
return value;
}
/*!
\brief enable the FAC Interrupt
\param[in] interrupt: FAC Interrupt
only one parameter can be selected which is shown as below:
\arg FAC_CTL_RIE: Read buffer interrupt
\arg FAC_CTL_WIE: Write buffer interrupt
\arg FAC_CTL_OFEIE: Overflow error interrupt
\arg FAC_CTL_UFEIE: Underflow error interrupt
\arg FAC_CTL_STEIE: Saturation error interrupt
\arg FAC_CTL_GSTEIE: gain saturation error interrupt
\param[out] none
\retval none
*/
void fac_interrupt_enable(uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_FAC_INTERRUPT(interrupt)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x001BU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
FAC_CTL |= interrupt;
}
}
/*!
\brief disable the FAC Interrupt
\param[in] interrupt: FAC Interrupt
only one parameter can be selected which is shown as below:
\arg FAC_CTL_RIE: Read buffer interrupt
\arg FAC_CTL_WIE: Write buffer interrupt
\arg FAC_CTL_OFEIE: Overflow error interrupt
\arg FAC_CTL_UFEIE: Underflow error interrupt
\arg FAC_CTL_STEIE: Saturation error interrupt
\arg FAC_CTL_GSTEIE: gain saturation error interrupt
\param[out] none
\retval none
*/
void fac_interrupt_disable(uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_FAC_INTERRUPT(interrupt)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x001CU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
FAC_CTL &= ~interrupt;
}
}
/*!
\brief get FAC interrupt flag status
\param[in] interrupt: FAC interrupt flag status
only one parameter can be selected which is shown as below:
\arg FAC_INT_FLAG_YBEF: Y buffer read interrupt flag
\arg FAC_INT_FLAG_X0BFF: X0 buffer write interrupt flag
\arg FAC_INT_FLAG_OFEF: overflow error interrupt flag
\arg FAC_INT_FLAG_UFEF: underflow error interrupt flag
\arg FAC_INT_FLAG_STEF: saturation error interrupt flag
\arg FAC_INT_FLAG_GSTEF: gain saturation error interrupt flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus fac_interrupt_flag_get(uint8_t interrupt)
{
uint32_t reg1 = FAC_CTL;
uint32_t reg2 = FAC_STAT;
FlagStatus interrupt_flag;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_FAC_INTERRUPT_FLAG(interrupt)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x001DU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
switch(interrupt) {
/* Y buffer read interrupt */
case FAC_INT_FLAG_YBEF:
reg1 = reg1 & FAC_CTL_RIE;
reg2 = (((reg2 & FAC_STAT_YBEF) == 0U)?FAC_STAT_YBEF:0U);
break;
/* X0 buffer write interrupt */
case FAC_INT_FLAG_X0BFF:
reg1 = reg1 & FAC_CTL_WIE;
reg2 = (((reg2 & FAC_STAT_X0BFF) == 0U)?FAC_STAT_X0BFF:0U);
break;
/* overflow error interrupt */
case FAC_INT_FLAG_OFEF:
reg1 = reg1 & FAC_CTL_OFEIE;
reg2 = reg2 & FAC_STAT_OFEF;
break;
/* underflow error interrupt */
case FAC_INT_FLAG_UFEF:
reg1 = reg1 & FAC_CTL_UFEIE;
reg2 = reg2 & FAC_STAT_UFEF;
break;
/* saturation error interrupt */
case FAC_INT_FLAG_STEF:
reg1 = reg1 & FAC_CTL_STEIE;
reg2 = reg2 & FAC_STAT_STEF;
break;
/* saturation error interrupt */
case FAC_INT_FLAG_GSTEF:
reg1 = reg1 & FAC_CTL_GSTEIE;
reg2 = reg2 & FAC_STAT_GSTEF;
break;
default :
break;
}
/*get FAC interrupt flag status */
if(reg1 && reg2) {
interrupt_flag = SET;
} else {
interrupt_flag = RESET;
}
}
return interrupt_flag;
}
/*!
\brief get FAC flag status
\param[in] flag: FAC flag status
only one parameter can be selected which is shown as below:
\arg FAC_FLAG_YBEF: Y buffer empty flag
\arg FAC_FLAG_X0BFF: X0 buffer full flag
\arg FAC_FLAG_OFEF: overflow error flag
\arg FAC_FLAG_UFEF: underflow error flag
\arg FAC_FLAG_STEF: saturation error flag
\arg FAC_FLAG_GSTEF: gain saturation error flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus fac_flag_get(uint32_t flag)
{
FlagStatus flag_state;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_FAC_FLAG(flag)) {
fw_debug_report_err(FAC_MODULE_ID, API_ID(0x001EU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(FAC_STAT & flag) {
flag_state = SET;
} else {
flag_state = RESET;
}
}
return flag_state;
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,301 @@
/*!
\file gd32h75e_fwdgt.c
\brief FWDGT driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_fwdgt.h"
/* write value to FWDGT_CTL_CMD bit field */
#define CTL_CMD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0U))
/* write value to FWDGT_RLD_RLD bit field */
#define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0U))
/* write value to FWDGT_WND_WND bit field */
#define WND_WND(regval) (BITS(0,11) & ((uint32_t)(regval) << 0U))
/*!
\brief enable write access to FWDGT_PSC, FWDGT_RLD and FWDGT_WND
\param[in] none
\param[out] none
\retval none
*/
void fwdgt_write_enable(void)
{
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
}
/*!
\brief disable write access to FWDGT_PSC, FWDGT_RLD and FWDGT_WND
\param[in] none
\param[out] none
\retval none
*/
void fwdgt_write_disable(void)
{
FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE;
}
/*!
\brief start the FWDGT counter
\param[in] none
\param[out] none
\retval none
*/
void fwdgt_enable(void)
{
FWDGT_CTL = FWDGT_KEY_ENABLE;
}
/*!
\brief configure the FWDGT counter prescaler value
\param[in] prescaler_value: specify prescaler value
only one parameter can be selected which is shown as below:
\arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4
\arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8
\arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16
\arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32
\arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64
\arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128
\arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value)
{
ErrStatus status = SUCCESS;
uint32_t timeout = FWDGT_PSC_TIMEOUT;
uint32_t flag_status = RESET;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_FWDGT_PSC_DIV(prescaler_value)) {
fw_debug_report_err(FWDGT_MODULE_ID, API_ID(0x0004U), ERR_PARAM_INVALID);
} else
#endif
{
/* enable write access to FWDGT_PSC */
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
/* wait until the PUD flag to be reset */
do{
flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
} while((--timeout > (uint32_t)0x00000000U) && (RESET != flag_status));
if(RESET != flag_status){
status = ERROR;
}
/* configure FWDGT */
FWDGT_PSC = (uint32_t)prescaler_value;
}
return status;
}
/*!
\brief configure the FWDGT counter reload value
\param[in] reload_value: specify reload value(0x0000 - 0x0FFF)
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_reload_value_config(uint16_t reload_value)
{
uint32_t timeout = FWDGT_RLD_TIMEOUT;
uint32_t flag_status = RESET;
ErrStatus status = SUCCESS;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_FWDGT_RELOAD_VALUE(reload_value)) {
fw_debug_report_err(FWDGT_MODULE_ID, API_ID(0x0005U), ERR_PARAM_INVALID);
} else
#endif
{
/* enable write access to FWDGT_RLD */
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
/* wait until the RUD flag to be reset */
do{
flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
}while((--timeout > (uint32_t)0x00000000U) && ((uint32_t)RESET != flag_status));
if ((uint32_t)RESET != flag_status){
status = ERROR;
}
FWDGT_RLD = RLD_RLD(reload_value);
}
return status;
}
/*!
\brief configure the FWDGT counter window value
\param[in] window_value: specify window value(0x0000 - 0x0FFF)
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_window_value_config(uint16_t window_value)
{
uint32_t time_index = FWDGT_WND_TIMEOUT;
uint32_t flag_status = RESET;
ErrStatus status = SUCCESS;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_FWDGT_WINDOW_VALUE(window_value)) {
fw_debug_report_err(FWDGT_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else
#endif
{
/* enable write access to FWDGT_WND */
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
/* wait until the WUD flag to be reset */
do{
flag_status = FWDGT_STAT & FWDGT_STAT_WUD;
}while((--time_index > (uint32_t)0x00000000U) && ((uint32_t)RESET != flag_status));
if ((uint32_t)RESET != flag_status){
status = ERROR;
}
FWDGT_WND = WND_WND(window_value);
}
return status;
}
/*!
\brief reload the counter of FWDGT
\param[in] none
\param[out] none
\retval none
*/
void fwdgt_counter_reload(void)
{
FWDGT_CTL = FWDGT_KEY_RELOAD;
}
/*!
\brief configure counter reload value, and prescaler divider value
\param[in] reload_value: specify reload value(0x0000 - 0x0FFF)
\param[in] prescaler_div: FWDGT prescaler value
only one parameter can be selected which is shown as below:
\arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4
\arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8
\arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16
\arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32
\arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64
\arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128
\arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div)
{
uint32_t timeout = FWDGT_PSC_TIMEOUT;
uint32_t flag_status = RESET;
ErrStatus status = SUCCESS;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
/* check parameter */
if(NOT_FWDGT_RELOAD_VALUE(reload_value)) {
fw_debug_report_err(FWDGT_MODULE_ID, API_ID(0x0008U), ERR_PARAM_INVALID);
} else if(NOT_FWDGT_PSC_DIV(prescaler_div)) {
fw_debug_report_err(FWDGT_MODULE_ID, API_ID(0x0008U), ERR_PARAM_INVALID);
} else
#endif
{
/* enable write access to FWDGT_PSC,and FWDGT_RLD */
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
/* wait until the PUD flag to be reset */
do{
flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
}while((--timeout > (uint32_t)0x00000000U) && ((uint32_t)RESET != flag_status));
if ((uint32_t)RESET != flag_status){
status = ERROR;
}
/* configure FWDGT */
FWDGT_PSC = (uint32_t)prescaler_div;
timeout = FWDGT_RLD_TIMEOUT;
/* wait until the RUD flag to be reset */
do{
flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
}while((--timeout > (uint32_t)0x00000000U) && ((uint32_t)RESET != flag_status));
if ((uint32_t)RESET != flag_status){
status = ERROR;
}
FWDGT_RLD = RLD_RLD(reload_value);
/* reload the counter */
FWDGT_CTL = FWDGT_KEY_RELOAD;
}
return status;
}
/*!
\brief get flag state of FWDGT
\param[in] flag: flag to get
only one parameter can be selected which is shown as below:
\arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going
\arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going
\arg FWDGT_FLAG_WUD: a write operation to FWDGT_WND register is on going
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus fwdgt_flag_get(uint16_t flag)
{
FlagStatus status = RESET;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_FWDGT_FLAG(flag)) {
fw_debug_report_err(FWDGT_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else
#endif
{
if (RESET != (FWDGT_STAT & flag)){
status = SET;
}
}
return status;
}
@@ -0,0 +1,672 @@
/*!
\file gd32h75e_gpio.c
\brief GPIO driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_gpio.h"
/*!
\brief reset GPIO port
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[out] none
\retval none
*/
void gpio_deinit(uint32_t gpio_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
switch(gpio_periph){
case GPIOA:
/* reset GPIOA */
rcu_periph_reset_enable(RCU_GPIOARST);
rcu_periph_reset_disable(RCU_GPIOARST);
break;
case GPIOB:
/* reset GPIOB */
rcu_periph_reset_enable(RCU_GPIOBRST);
rcu_periph_reset_disable(RCU_GPIOBRST);
break;
case GPIOC:
/* reset GPIOC */
rcu_periph_reset_enable(RCU_GPIOCRST);
rcu_periph_reset_disable(RCU_GPIOCRST);
break;
case GPIOD:
/* reset GPIOD */
rcu_periph_reset_enable(RCU_GPIODRST);
rcu_periph_reset_disable(RCU_GPIODRST);
break;
case GPIOE:
/* reset GPIOE */
rcu_periph_reset_enable(RCU_GPIOERST);
rcu_periph_reset_disable(RCU_GPIOERST);
break;
case GPIOF:
/* reset GPIOF */
rcu_periph_reset_enable(RCU_GPIOFRST);
rcu_periph_reset_disable(RCU_GPIOFRST);
break;
case GPIOG:
/* reset GPIOG */
rcu_periph_reset_enable(RCU_GPIOGRST);
rcu_periph_reset_disable(RCU_GPIOGRST);
break;
case GPIOH:
/* reset GPIOH */
rcu_periph_reset_enable(RCU_GPIOHRST);
rcu_periph_reset_disable(RCU_GPIOHRST);
break;
case GPIOJ:
/* reset GPIOJ */
rcu_periph_reset_enable(RCU_GPIOJRST);
rcu_periph_reset_disable(RCU_GPIOJRST);
break;
case GPIOK:
/* reset GPIOK */
rcu_periph_reset_enable(RCU_GPIOKRST);
rcu_periph_reset_disable(RCU_GPIOKRST);
break;
default:
break;
}
}
}
/*!
\brief set GPIO mode
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[in] mode: gpio pin mode
only one parameter can be selected which is shown as below:
\arg GPIO_MODE_INPUT: input mode
\arg GPIO_MODE_OUTPUT: output mode
\arg GPIO_MODE_AF: alternate function mode
\arg GPIO_MODE_ANALOG: analog mode
\param[in] pull_up_down: gpio pin with pull-up or pull-down resistor
only one parameter can be selected which is shown as below:
\arg GPIO_PUPD_NONE: floating mode, no pull-up and pull-down resistors
\arg GPIO_PUPD_PULLUP: with pull-up resistor
\arg GPIO_PUPD_PULLDOWN:with pull-down resistor
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[out] none
\retval none
*/
void gpio_mode_set(uint32_t gpio_periph, uint32_t mode, uint32_t pull_up_down, uint32_t pin)
{
uint16_t i;
uint32_t ctl, pupd;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0002U), ERR_PERIPH);
}else if(NOT_GPIO_MODE(mode)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
}else if(NOT_GPIO_PULL_MODE(pull_up_down)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
}else if(NOT_GPIO_PIN(pin)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0002U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
ctl = GPIO_CTL(gpio_periph);
pupd = GPIO_PUD(gpio_periph);
for(i = 0U;i < 16U;i++){
if((1U << i) & pin){
/* clear the specified pin mode bits */
ctl &= ~GPIO_MODE_MASK(i);
/* set the specified pin mode bits */
ctl |= GPIO_MODE_SET(i, mode);
/* clear the specified pin pupd bits */
pupd &= ~GPIO_PUPD_MASK(i);
/* set the specified pin pupd bits */
pupd |= GPIO_PUPD_SET(i, pull_up_down);
}
}
GPIO_CTL(gpio_periph) = ctl;
GPIO_PUD(gpio_periph) = pupd;
}
}
/*!
\brief set GPIO output type and speed
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[in] otype: gpio pin output mode
only one parameter can be selected which is shown as below:
\arg GPIO_OTYPE_PP: push pull mode
\arg GPIO_OTYPE_OD: open drain mode
\param[in] speed: gpio pin output max speed
only one parameter can be selected which is shown as below:
\arg GPIO_OSPEED_12MHZ: output max speed 12MHz
\arg GPIO_OSPEED_60MHZ: output max speed 60MHz
\arg GPIO_OSPEED_85MHZ: output max speed 85MHz
\arg GPIO_OSPEED_100_220MHZ: output max speed 100/220MHz
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[out] none
\retval none
*/
void gpio_output_options_set(uint32_t gpio_periph, uint8_t otype, uint32_t speed, uint32_t pin)
{
uint16_t i;
uint32_t ospeed;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0003U), ERR_PERIPH);
}else if(NOT_GPIO_OTYPE(otype)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0003U), ERR_PARAM_INVALID);
}else if(NOT_GPIO_SPEED(speed)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0003U), ERR_PARAM_INVALID);
}else if(NOT_GPIO_PIN(pin)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0003U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(GPIO_OTYPE_OD == otype){
GPIO_OMODE(gpio_periph) |= (uint32_t)pin;
}else{
GPIO_OMODE(gpio_periph) &= (uint32_t)(~pin);
}
/* get the specified pin output speed bits value */
ospeed = GPIO_OSPD(gpio_periph);
for(i = 0U;i < 16U;i++){
if((1U << i) & pin){
/* clear the specified pin output speed bits */
ospeed &= ~GPIO_OSPEED_MASK(i);
/* set the specified pin output speed bits */
ospeed |= GPIO_OSPEED_SET(i,speed);
}
}
GPIO_OSPD(gpio_periph) = ospeed;
}
}
/*!
\brief set GPIO pin bit
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[out] none
\retval none
*/
void gpio_bit_set(uint32_t gpio_periph, uint32_t pin)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0004U), ERR_PERIPH);
}else if(NOT_GPIO_PIN(pin)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0004U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
GPIO_BOP(gpio_periph) = (uint32_t)pin;
}
}
/*!
\brief reset GPIO pin bit
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,F)
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[out] none
\retval none
*/
void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0005U), ERR_PERIPH);
}else if(NOT_GPIO_PIN(pin)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0005U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
GPIO_BC(gpio_periph) = (uint32_t)pin;
}
}
/*!
\brief write data to the specified GPIO pin
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[in] bit_value: SET or RESET
only one parameter can be selected which is shown as below:
\arg RESET: clear the port pin
\arg SET: set the port pin
\param[out] none
\retval none
*/
void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0006U), ERR_PERIPH);
}else if(NOT_GPIO_PIN(pin)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0006U), ERR_PARAM_OUT_OF_RANGE);
}else if(NOT_RESET_SET(bit_value)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(RESET != bit_value){
GPIO_BOP(gpio_periph) = (uint32_t)pin;
}else{
GPIO_BC(gpio_periph) = (uint32_t)pin;
}
}
}
/*!
\brief write data to the specified GPIO port
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[in] data: specify the value to be written to the port output control register
\param[out] none
\retval none
*/
void gpio_port_write(uint32_t gpio_periph, uint16_t data)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0007U), ERR_PERIPH);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
GPIO_OCTL(gpio_periph) = (uint32_t)data;
}
}
/*!
\brief set GPIO input filter
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[in] speriod: gpio pin input sample period
only one parameter can be selected which is shown as below:
\arg GPIO_ISPERIOD(x): x = 0 ~ 255
\param[in] iftype: gpio pin input filtering type
only one parameter can be selected which is shown as below:
\arg GPIO_IFTYPE_SYNC: input filter type synchronization
\arg GPIO_IFTYPE_3_SAMPLE: input filter type filter 3 samples
\arg GPIO_IFTYPE_6_SAMPLE: input filter type filter 6 samples
\arg GPIO_IFTYPE_ASYNC: input filter type asynchronous
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[out] none
\retval none
*/
void gpio_input_filter_set(uint32_t gpio_periph, uint8_t speriod, uint32_t iftype, uint32_t pin)
{
uint16_t i;
uint32_t isperiod;
uint32_t iftp;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0008U), ERR_PERIPH);
}else if(NOT_FLITER_TYPE(iftype)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0008U), ERR_PARAM_INVALID);
}else if(NOT_GPIO_PIN(pin)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0008U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
isperiod = GPIO_IFL(gpio_periph);
if(pin & 0x000000FFU){
isperiod &= ~GPIO_IFL_FLPRD0;
isperiod |= (uint32_t)speriod;
}
if(pin & 0x0000FF00U){
isperiod &= ~GPIO_IFL_FLPRD1;
isperiod |= ((uint32_t)speriod << 8U);
}
GPIO_IFL(gpio_periph) = isperiod;
/* get the specified pin output speed bits value */
iftp = GPIO_IFTP(gpio_periph);
for(i = 0U;i < 16U;i++){
if((1U << i) & pin){
/* clear the specified pin output speed bits */
iftp &= ~GPIO_IFTYPE_MASK(i);
/* set the specified pin output speed bits */
iftp |= GPIO_IFTYPE_SET(i,iftype);
}
}
GPIO_IFTP(gpio_periph) = iftp;
}
}
/*!
\brief get GPIO pin input status
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[out] none
\retval SET or RESET
*/
FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin)
{
FlagStatus reval = RESET;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0009U), ERR_PERIPH);
}else if(NOT_GPIO_PIN(pin)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0009U), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){
reval = SET;
}else{
reval = RESET;
}
}
return reval;
}
/*!
\brief get GPIO port input status
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[out] none
\retval state of GPIO all pins
*/
uint16_t gpio_input_port_get(uint32_t gpio_periph)
{
uint16_t reval = 0U;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x000AU), ERR_PERIPH);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
reval = ((uint16_t)GPIO_ISTAT(gpio_periph));
}
return reval;
}
/*!
\brief get GPIO pin output status
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[out] none
\retval SET or RESET
*/
FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin)
{
FlagStatus reval = RESET;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x000BU), ERR_PERIPH);
}else if(NOT_GPIO_PIN(pin)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x000BU), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
if((uint32_t)RESET != (GPIO_OCTL(gpio_periph)&(pin))){
reval = SET;
}else{
reval = RESET;
}
}
return reval;
}
/*!
\brief get GPIO port output status
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[out] none
\retval state of GPIO all pins
*/
uint16_t gpio_output_port_get(uint32_t gpio_periph)
{
uint16_t reval = 0U;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x000CU), ERR_PERIPH);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
reval = ((uint16_t)GPIO_OCTL(gpio_periph));
}
return reval;
}
/*!
\brief set GPIO alternate function
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[in] alt_func_num: GPIO pin af function, please refer to specific device datasheet
only one parameter can be selected which is shown as below:
\arg GPIO_AF_0: SYSTEM, TIMER40, TIMER41, TIMER42, TIMER43, TIMER44
\arg GPIO_AF_1: TIMER0, TIMER1, TIMER15, TIMER16, EXMC
\arg GPIO_AF_2: TIMER2, TIMER3, TIMER4, TIMER7, TIMER14, CAN2, EXMC
\arg GPIO_AF_3: TIMER7, TIMER9, EDOUT, EXMC, HPDF, OSPIM
\arg GPIO_AF_4: TIMER14, I2C0, I2C1, I2C2, I2C3, USART0, HPDF, OSPIM
\arg GPIO_AF_5: SPI0, SPI1, SPI2, SPI3, SPI4, SPI5, CAN2
\arg GPIO_AF_6: UART3, SPI2, I2C3, HPDF, EDOUT, OSPIM
\arg GPIO_AF_7: USART0, USART1, USART2, USART5, UART6, TIMER40, TIMER41, TIMER42, TIMER43,
SPI1, SPI2, SPI5, USBHS1
\arg GPIO_AF_8: UART3, UART4, UART7, SPI5, TIMER44, USBHS1
\arg GPIO_AF_9: TRGSEL, CAN0, CAN1, OPSIM, EXMC
\arg GPIO_AF_10: CMP, USBHS0, OPSIM, EXMC
\arg GPIO_AF_11: CMP, UART6, EXMC, HPDF, I2C3, OPSIM
\arg GPIO_AF_12: TIMER0, EXMC, OPSIM, CMP, USBHS1
\arg GPIO_AF_13: TRGSEL, COMP0, CMP, TIMER22
\arg GPIO_AF_14: UART4, TIMER23
\arg GPIO_AF_15: EVENTOUT
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[out] none
\retval none
*/
void gpio_af_set(uint32_t gpio_periph, uint32_t alt_func_num, uint32_t pin)
{
uint16_t i;
uint32_t afrl, afrh;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x000DU), ERR_PERIPH);
}else if(NOT_GPIO_AF(alt_func_num)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x000DU), ERR_PARAM_INVALID);
}else if(NOT_GPIO_PIN(pin)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x000DU), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
afrl = GPIO_AFSEL0(gpio_periph);
afrh = GPIO_AFSEL1(gpio_periph);
for(i = 0U;i < 8U;i++){
if((1U << i) & pin){
/* clear the specified pin alternate function bits */
afrl &= ~GPIO_AFR_MASK(i);
afrl |= GPIO_AFR_SET(i,alt_func_num);
}
}
for(i = 8U;i < 16U;i++){
if((1U << i) & pin){
/* clear the specified pin alternate function bits */
afrh &= ~GPIO_AFR_MASK(i - 8U);
afrh |= GPIO_AFR_SET(i - 8U,alt_func_num);
}
}
GPIO_AFSEL0(gpio_periph) = afrl;
GPIO_AFSEL1(gpio_periph) = afrh;
}
}
/*!
\brief lock GPIO pin bit
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[out] none
\retval none
*/
void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin)
{
uint32_t lock = 0x00010000U;
lock |= pin;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x000EU), ERR_PERIPH);
}else if(NOT_GPIO_PIN(pin)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x000EU), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* lock key writing sequence: write 1->write 0->write 1->read 0->read 1 */
GPIO_LOCK(gpio_periph) = (uint32_t)lock;
GPIO_LOCK(gpio_periph) = (uint32_t)pin;
GPIO_LOCK(gpio_periph) = (uint32_t)lock;
lock = GPIO_LOCK(gpio_periph);
lock = GPIO_LOCK(gpio_periph);
}
}
/*!
\brief toggle GPIO pin status
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[in] pin: GPIO pin
one or more parameters can be selected which are shown as below:
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
\param[out] none
\retval none
*/
void gpio_bit_toggle(uint32_t gpio_periph, uint32_t pin)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x000FU), ERR_PERIPH);
}else if(NOT_GPIO_PIN(pin)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x000FU), ERR_PARAM_OUT_OF_RANGE);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
GPIO_TG(gpio_periph) = (uint32_t)pin;
}
}
/*!
\brief toggle GPIO port status
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,J,K)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,J,K)
\param[out] none
\retval none
*/
void gpio_port_toggle(uint32_t gpio_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_GPIO_PERIPH(gpio_periph)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0010U), ERR_PERIPH);
}else
#endif /* FW_DEBUG_ERR_REPORT */
{
GPIO_TG(gpio_periph) = 0x0000FFFFU;
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,394 @@
/*!
\file gd32h75e_lpdts.c
\brief LPDTS driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_lpdts.h"
/* LPDTS high threshold value offset macro */
#define LPDTS_IT_INTHT_OFFSET ((uint32_t)16U)
/* sampling time offset macro */
#define LPDTS_CFG_SPT_OFFSET ((uint32_t)16U)
/* engineering value offset macro */
#define LPDTS_SDATA_VAL_OFFSET ((uint32_t)16U)
/* the T0 temperature macro */
#define LPDTS_T0_TMP_VAL ((uint32_t)25U)
/*!
\brief reset the LPDTS registers
\param[in] none
\param[out] none
\retval none
*/
void lpdts_deinit(void)
{
rcu_periph_reset_enable(RCU_LPDTSRST);
rcu_periph_reset_disable(RCU_LPDTSRST);
}
/*!
\brief initialize the parameters of LPDTS struct with the default values
\param[in] none
\param[out] init_struct: the initialization data needed to initialize LPDTS
\retval none
*/
void lpdts_struct_para_init(lpdts_parameter_struct *init_struct)
{
/* set the struct with the default values */
init_struct->ref_clock = REF_PCLK;
init_struct->trigger_input = NO_HARDWARE_TRIGGER;
init_struct->sampling_time = SPT_CLOCK_15;
}
/*!
\brief initialize the LPDTS
\param[in] init_struct: the initialization data needed to initialize LPDTS_CFG
ref_clock: REF_PCLK, REF_LXTAL
trigger_input: NO_HARDWARE_TRIGGER, LPDTS_TRG
sampling_time: SPT_CLOCK_x(x=1..15)
\param[out] none
\retval none
*/
void lpdts_init(lpdts_parameter_struct *init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_LPDTS_INITIALIZATION_DATA(init_struct)) {
fw_debug_report_err(LPDTS_MODULE_ID, API_ID(0x0003U), ERR_PARAM_INVALID);
} else /* FW_DEBUG_ERR_REPORT */
#endif
{
uint32_t reg;
/* configure the LPDTS_CFG */
reg = LPDTS_CFG;
reg &= ~(LPDTS_CFG_REFSEL | LPDTS_CFG_ITSEL | LPDTS_CFG_SPT);
reg |= (init_struct->ref_clock | init_struct->trigger_input | init_struct->sampling_time);
LPDTS_CFG = reg;
}
}
/*!
\brief enable LPDTS temperature sensor
\param[in] none
\param[out] none
\retval none
*/
void lpdts_enable(void)
{
LPDTS_CFG |= LPDTS_CFG_TSEN;
}
/*!
\brief disable LPDTS temperature sensor
\param[in] none
\param[out] none
\retval none
*/
void lpdts_disable(void)
{
LPDTS_CFG &= ~LPDTS_CFG_TSEN;
}
/*!
\brief enable LPDTS software trigger
\param[in] none
\param[out] none
\retval none
*/
void lpdts_soft_trigger_enable(void)
{
LPDTS_CFG |= LPDTS_CFG_TRGS;
}
/*!
\brief disable LPDTS software trigger
\param[in] none
\param[out] none
\retval none
*/
void lpdts_soft_trigger_disable(void)
{
LPDTS_CFG &= ~LPDTS_CFG_TRGS;
}
/*!
\brief configure LPDTS high threshold value
\param[in] value: high threshold value(0~65535)
\param[out] none
\retval none
*/
void lpdts_high_threshold_set(int32_t value)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_LPDTS_HIGH_THRESHOLD(value)) {
fw_debug_report_err(LPDTS_MODULE_ID, API_ID(0x0008U), ERR_PARAM_INVALID);
} else /* FW_DEBUG_ERR_REPORT */
#endif
{
uint32_t reg;
/* configure the LPDTS_IT */
reg = LPDTS_IT;
reg &= ~LPDTS_IT_INTHT;
reg |= (uint32_t)value << LPDTS_IT_INTHT_OFFSET;
LPDTS_IT = reg;
}
}
/*!
\brief configure LPDTS low threshold value
\param[in] value: low threshold value(0~65535)
\param[out] none
\retval none
*/
void lpdts_low_threshold_set(int32_t value)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_LPDTS_LOW_THRESHOLD(value)) {
fw_debug_report_err(LPDTS_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else /* FW_DEBUG_ERR_REPORT */
#endif
{
uint32_t reg;
/* configure the LPDTS_IT */
reg = LPDTS_IT;
reg &= ~LPDTS_IT_INTLT;
reg |= (uint32_t)value;
LPDTS_IT = reg;
}
}
/*!
\brief configure LPDTS reference clock selection
\param[in] source: reference clock source
only one parameter can be selected which is shown as below:
\arg REF_PCLK: high speed reference clock (PCLK)
\arg REF_LXTAL: low speed reference clock (LXTAL)
\param[out] none
\retval none
*/
void lpdts_ref_clock_source_config(uint32_t source)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_LPDTS_REF_CLOCK_SOURCE(source)) {
fw_debug_report_err(LPDTS_MODULE_ID, API_ID(0x0010U), ERR_PARAM_INVALID);
} else /* FW_DEBUG_ERR_REPORT */
#endif
{
uint32_t reg;
/* configure the LPDTS_CFG */
reg = LPDTS_CFG;
reg &= ~LPDTS_CFG_REFSEL;
reg |= source;
LPDTS_CFG = reg;
}
}
/*!
\brief get temperature from LPDTS
\param[in] none
\param[out] none
\retval temperature: temperature in deg C
*/
int32_t lpdts_temperature_get(void)
{
uint32_t freq;
uint32_t count;
uint32_t t0;
uint32_t t0_freq;
uint32_t ramp_coeff;
uint32_t reg_cfg;
int32_t temperature;
/* get the total number of samples */
count = (LPDTS_DATA & LPDTS_DATA_COVAL);
/* get LPDTS_CFG configuration */
reg_cfg = LPDTS_CFG;
/* get the module frequency on Hz */
if((reg_cfg & LPDTS_CFG_REFSEL) == LPDTS_CFG_REFSEL) {
freq = (LXTAL_VALUE * count) / (2U * ((reg_cfg & LPDTS_CFG_SPT) >> LPDTS_CFG_SPT_OFFSET));
} else {
freq = (2U * rcu_clock_freq_get(CK_APB1) / count) * ((reg_cfg & LPDTS_CFG_SPT) >> LPDTS_CFG_SPT_OFFSET);
}
/* read factory settings */
t0 = (LPDTS_SDATA & LPDTS_SDATA_VAL) >> LPDTS_SDATA_VAL_OFFSET;
if(t0 == 0U) {
t0 = LPDTS_T0_TMP_VAL;
}
/* get the T0 frequency on Hz */
t0_freq = (LPDTS_SDATA & LPDTS_SDATA_FREQ) * 100U;
/* get the ramp coefficient for the temperature sensor on deg C/Hz */
ramp_coeff = LPDTS_RDATA & LPDTS_RDATA_RCVAL;
/* figure out the temperature deg C */
temperature = (int32_t)t0 + (((int32_t)freq - (int32_t)t0_freq) / (int32_t)ramp_coeff);
return temperature;
}
/*!
\brief get LPDTS flag
\param[in] flag: LPDTS ready flag
only one parameter can be selected which is shown as below:
\arg LPDTS_FLAG_TSR
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus lpdts_flag_get(uint32_t flag)
{
FlagStatus status = RESET;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_LPDTS_FLAG(flag)) {
fw_debug_report_err(LPDTS_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
} else /* FW_DEBUG_ERR_REPORT */
#endif
{
if(LPDTS_STAT & flag) {
status = SET;
}
}
/* return the state of corresponding LPDTS flag */
return status;
}
/*!
\brief enable LPDTS interrupt
\param[in] interrupt: the LPDTS interrupt
one or more parameters can be selected which is shown as below:
\arg LPDTS_INT_EM
\arg LPDTS_INT_LT
\arg LPDTS_INT_HT
\arg LPDTS_INT_EMA
\arg LPDTS_INT_LTA
\arg LPDTS_INT_HTA
\param[out] none
\retval none
*/
void lpdts_interrupt_enable(uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_LPDTS_INTERRUPT(interrupt)) {
fw_debug_report_err(LPDTS_MODULE_ID, API_ID(0x0013U), ERR_PARAM_INVALID);
} else /* FW_DEBUG_ERR_REPORT */
#endif
{
LPDTS_INTEN |= interrupt;
}
}
/*!
\brief disable LPDTS interrupt
\param[in] interrupt: the LPDTS interrupt
one or more parameters can be selected which is shown as below:
\arg LPDTS_INT_EM
\arg LPDTS_INT_LT
\arg LPDTS_INT_HT
\arg LPDTS_INT_EMA
\arg LPDTS_INT_LTA
\arg LPDTS_INT_HTA
\param[out] none
\retval none
*/
void lpdts_interrupt_disable(uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_LPDTS_INTERRUPT(interrupt)) {
fw_debug_report_err(LPDTS_MODULE_ID, API_ID(0x0014U), ERR_PARAM_INVALID);
} else /* FW_DEBUG_ERR_REPORT */
#endif
{
LPDTS_INTEN &= ~interrupt;
}
}
/*!
\brief get LPDTS interrupt flag
\param[in] flag: LPDTS interrupt flag
only one parameter can be selected which is shown as below:
\arg LPDTS_INT_FLAG_EM
\arg LPDTS_INT_FLAG_LT
\arg LPDTS_INT_FLAG_HT
\arg LPDTS_INT_FLAG_EMA
\arg LPDTS_INT_FLAG_LTA
\arg LPDTS_INT_FLAG_HTA
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus lpdts_interrupt_flag_get(uint32_t flag)
{
FlagStatus status = RESET;
uint32_t state;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_LPDTS_INTERRUPT_FLAG(flag)) {
fw_debug_report_err(LPDTS_MODULE_ID, API_ID(0x0015U), ERR_PARAM_INVALID);
} else /* FW_DEBUG_ERR_REPORT */
#endif
{
state = LPDTS_STAT;
if(state & flag) {
state = LPDTS_INTEN;
if(state & flag) {
status = SET;
}
}
}
/* return the state of corresponding LPDTS flag */
return status;
}
/*!
\brief clear the LPDTS interrupt flag
\param[in] flag: LPDTS flag
one or more parameter can be selected which is shown as below:
\arg LPDTS_INT_FLAG_EM
\arg LPDTS_INT_FLAG_LT
\arg LPDTS_INT_FLAG_HT
\arg LPDTS_INT_FLAG_EMA
\arg LPDTS_INT_FLAG_LTA
\arg LPDTS_INT_FLAG_HTA
\param[out] none
\retval none
*/
void lpdts_interrupt_flag_clear(uint32_t flag)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_LPDTS_INTERRUPT_FLAG(flag)) {
fw_debug_report_err(LPDTS_MODULE_ID, API_ID(0x0016U), ERR_PARAM_INVALID);
} else /* FW_DEBUG_ERR_REPORT */
#endif
{
/* clear the flags */
LPDTS_INTC = flag;
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,298 @@
/*!
\file gd32h75e_misc.c
\brief MISC driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_misc.h"
/*!
\brief set the priority group
\param[in] nvic_prigroup: the NVIC priority group
\arg NVIC_PRIGROUP_PRE0_SUB4: 0 bits for pre-emption priority, 4 bits for subpriority
\arg NVIC_PRIGROUP_PRE1_SUB3: 1 bits for pre-emption priority, 3 bits for subpriority
\arg NVIC_PRIGROUP_PRE2_SUB2: 2 bits for pre-emption priority, 2 bits for subpriority
\arg NVIC_PRIGROUP_PRE3_SUB1: 3 bits for pre-emption priority, 1 bits for subpriority
\arg NVIC_PRIGROUP_PRE4_SUB0: 4 bits for pre-emption priority, 0 bits for subpriority
\param[out] none
\retval none
*/
void nvic_priority_group_set(uint32_t nvic_prigroup)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_NVIC_PRIORITY_GROUP(nvic_prigroup)) {
fw_debug_report_err(MISC_MODULE_ID, API_ID(0x0001U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* set the priority group value */
SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup;
}
}
/*!
\brief enable NVIC interrupt request
\param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type
\param[in] nvic_irq_pre_priority: the pre-emption priority needed to set
\param[in] nvic_irq_sub_priority: the subpriority needed to set
\param[out] none
\retval none
*/
void nvic_irq_enable(IRQn_Type nvic_irq, uint8_t nvic_irq_pre_priority,
uint8_t nvic_irq_sub_priority)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_NVIC_IRQ_PRIORITY(nvic_irq_pre_priority)) {
fw_debug_report_err(MISC_MODULE_ID, API_ID(0x0002U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_NVIC_IRQ_PRIORITY(nvic_irq_sub_priority)) {
fw_debug_report_err(MISC_MODULE_ID, API_ID(0x0002U), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t temp_priority, temp_pre, temp_sub;
/* use the priority group value to get the temp_pre and the temp_sub */
if(((SCB->AIRCR) & (uint32_t)0x700U) == NVIC_PRIGROUP_PRE0_SUB4) {
temp_pre = 0U;
temp_sub = 0x4U;
} else if(((SCB->AIRCR) & (uint32_t)0x700U) == NVIC_PRIGROUP_PRE1_SUB3) {
temp_pre = 1U;
temp_sub = 0x3U;
} else if(((SCB->AIRCR) & (uint32_t)0x700U) == NVIC_PRIGROUP_PRE2_SUB2) {
temp_pre = 2U;
temp_sub = 0x2U;
} else if(((SCB->AIRCR) & (uint32_t)0x700U) == NVIC_PRIGROUP_PRE3_SUB1) {
temp_pre = 3U;
temp_sub = 0x1U;
} else if(((SCB->AIRCR) & (uint32_t)0x700U) == NVIC_PRIGROUP_PRE4_SUB0) {
temp_pre = 4U;
temp_sub = 0x0U;
} else {
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
temp_pre = 2U;
temp_sub = 0x2U;
}
/* get the temp_priority to fill the NVIC->IP register */
temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre);
temp_priority |= (uint32_t)nvic_irq_sub_priority & ((uint32_t)0x0FU >> (0x4U - temp_sub));
__NVIC_SetPriority((IRQn_Type)nvic_irq, temp_priority);
/* enable the selected IRQ */
NVIC->ISER[(uint8_t)nvic_irq >> 0x05U] = (uint32_t)0x01U << ((uint8_t)nvic_irq & (uint8_t)0x1FU);
}
}
/*!
\brief disable NVIC interrupt request
\param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type
\param[out] none
\retval none
*/
void nvic_irq_disable(IRQn_Type nvic_irq)
{
/* disable the selected IRQ.*/
NVIC_DisableIRQ(nvic_irq);
}
/*!
\brief set the NVIC vector table base address
\param[in] nvic_vect_tab: the RAM or FLASH base address
\arg NVIC_VECTTAB_RAM: RAM base address
\arg NVIC_VECTTAB_FLASH: Flash base address
\param[in] offset: vector table offset
\param[out] none
\retval none
*/
void nvic_vector_table_set(uint32_t nvic_vect_tab, uint32_t offset)
{
SCB->VTOR = nvic_vect_tab | (offset & NVIC_VECTTAB_OFFSET_MASK);
__DSB();
}
/*!
\brief set the state of the low power mode
\param[in] lowpower_mode: the low power mode state
\arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power
mode by exiting from ISR
\arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode
\arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the low power mode can be woke up
by all the enable and disable interrupts
\param[out] none
\retval none
*/
void system_lowpower_set(uint8_t lowpower_mode)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYS_LOW_POWER_MODE(lowpower_mode)) {
fw_debug_report_err(MISC_MODULE_ID, API_ID(0x0005U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
SCB->SCR |= (uint32_t)lowpower_mode;
}
}
/*!
\brief reset the state of the low power mode
\param[in] lowpower_mode: the low power mode state
\arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power
mode by exiting from ISR
\arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode
\arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the low power mode only can be
woke up by the enable interrupts
\param[out] none
\retval none
*/
void system_lowpower_reset(uint8_t lowpower_mode)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYS_LOW_POWER_MODE(lowpower_mode)) {
fw_debug_report_err(MISC_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
SCB->SCR &= (~(uint32_t)lowpower_mode);
}
}
/*!
\brief set the systick clock source
\param[in] systick_clksource: the systick clock source needed to choose
\arg SYSTICK_CLKSOURCE_CKSYS: systick clock source is from CK_SYS
\arg SYSTICK_CLKSOURCE_CKSYS_DIV8: systick clock source is from CK_SYS/8
\param[out] none
\retval none
*/
void systick_clksource_set(uint32_t systick_clksource)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSTICK_CLK_SRC(systick_clksource)) {
fw_debug_report_err(MISC_MODULE_ID, API_ID(0x0007U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(SYSTICK_CLKSOURCE_CKSYS == systick_clksource) {
/* set the systick clock source from CK_SYS */
SysTick->CTRL |= SYSTICK_CLKSOURCE_CKSYS;
} else {
/* set the systick clock source from CK_SYS/8 */
SysTick->CTRL &= SYSTICK_CLKSOURCE_CKSYS_DIV8;
}
}
}
#if (__MPU_PRESENT == 1)
/*!
\brief initialize mpu_region_init_struct with the default values
\param[in] mpu_init_struct: pointer to a mpu_region_init_struct structure
\param[out] none
\retval none
*/
void mpu_region_struct_para_init(mpu_region_init_struct *mpu_init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(mpu_init_struct)) {
fw_debug_report_err(MISC_MODULE_ID, API_ID(0x0008U), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
mpu_init_struct->region_number = MPU_REGION_NUMBER0;
mpu_init_struct->region_base_address = 0x00000000U;
mpu_init_struct->instruction_exec = MPU_INSTRUCTION_EXEC_PERMIT;
mpu_init_struct->access_permission = MPU_AP_NO_ACCESS;
mpu_init_struct->tex_type = MPU_TEX_TYPE0;
mpu_init_struct->access_shareable = MPU_ACCESS_SHAREABLE;
mpu_init_struct->access_cacheable = MPU_ACCESS_CACHEABLE;
mpu_init_struct->access_bufferable = MPU_ACCESS_BUFFERABLE;
mpu_init_struct->subregion_disable = MPU_SUBREGION_ENABLE;
mpu_init_struct->region_size = MPU_REGION_SIZE_32B;
}
}
/*!
\brief configure the MPU region
It is highly recommended to use MPU to prevent Speculative Prefetching of external memory,
which may cause CPU read locks and even system errors.
\param[in] mpu_init_struct: MPU initialization structure
region_number: region number
MPU_REGION_NUMBERn (n=0,..,15)
region_base_address: region base address
region_size: MPU_REGION_SIZE_32B, MPU_REGION_SIZE_64B, MPU_REGION_SIZE_128B, MPU_REGION_SIZE_256B, MPU_REGION_SIZE_512B,
MPU_REGION_SIZE_1KB, MPU_REGION_SIZE_2KB, MPU_REGION_SIZE_4KB, MPU_REGION_SIZE_8KB, MPU_REGION_SIZE_16KB,
MPU_REGION_SIZE_32KB, MPU_REGION_SIZE_64KB, MPU_REGION_SIZE_128KB, MPU_REGION_SIZE_256KB, MPU_REGION_SIZE_512KB,
MPU_REGION_SIZE_1MB, MPU_REGION_SIZE_2MB, MPU_REGION_SIZE_4MB, MPU_REGION_SIZE_8MB, MPU_REGION_SIZE_16MB,
MPU_REGION_SIZE_32MB, MPU_REGION_SIZE_64MB, MPU_REGION_SIZE_128MB, MPU_REGION_SIZE_256MB, MPU_REGION_SIZE_512MB,
MPU_REGION_SIZE_1GB, MPU_REGION_SIZE_2GB, MPU_REGION_SIZE_4GB
subregion_disable: MPU_SUBREGION_ENABLE, MPU_SUBREGION_DISABLE or 0x00~0xFF
tex_type: MPU_TEX_TYPE0, MPU_TEX_TYPE1, MPU_TEX_TYPE2 or 0x00~0x07
access_permission: MPU_AP_NO_ACCESS, MPU_AP_PRIV_RW, MPU_AP_PRIV_RW_UNPRIV_RO, MPU_AP_FULL_ACCESS, MPU_AP_PRIV_RO,
MPU_AP_PRIV_UNPRIV_RO
access_shareable: MPU_ACCESS_SHAREABLE, MPU_ACCESS_NON_SHAREABLE
access_cacheable: MPU_ACCESS_CACHEABLE, MPU_ACCESS_NON_CACHEABLE
access_bufferable: MPU_ACCESS_BUFFERABLE, MPU_ACCESS_NON_BUFFERABLE
instruction_exec: MPU_INSTRUCTION_EXEC_PERMIT, MPU_INSTRUCTION_EXEC_NOT_PERMIT
\param[out] none
\retval none
*/
void mpu_region_config(mpu_region_init_struct *mpu_init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(mpu_init_struct)) {
fw_debug_report_err(MISC_MODULE_ID, API_ID(0x00009U), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
MPU->RNR = mpu_init_struct->region_number;
MPU->RBAR = mpu_init_struct->region_base_address;
MPU->RASR = ((uint32_t)mpu_init_struct->instruction_exec << MPU_RASR_XN_Pos) |
((uint32_t)mpu_init_struct->access_permission << MPU_RASR_AP_Pos) |
((uint32_t)mpu_init_struct->tex_type << MPU_RASR_TEX_Pos) |
((uint32_t)mpu_init_struct->access_shareable << MPU_RASR_S_Pos) |
((uint32_t)mpu_init_struct->access_cacheable << MPU_RASR_C_Pos) |
((uint32_t)mpu_init_struct->access_bufferable << MPU_RASR_B_Pos) |
((uint32_t)mpu_init_struct->subregion_disable << MPU_RASR_SRD_Pos) |
((uint32_t)mpu_init_struct->region_size << MPU_RASR_SIZE_Pos);
}
}
/*!
\brief enable the MPU region
\param[in] none
\param[out] none
\retval none
*/
void mpu_region_enable(void)
{
MPU->RASR |= MPU_RASR_ENABLE_Msk;
}
#endif /* __MPU_PRESENT */
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,285 @@
/*!
\file gd32h75e_ospim.c
\brief OSPIM driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_ospim.h"
#include "gd32h75e_ospi.h"
/*!
\brief reset the OSPIM peripheral
\param[in] none
\param[out] none
\retval none
*/
void ospim_deinit(void)
{
/* reset OSPIM */
rcu_periph_reset_enable(RCU_OSPIMRST);
rcu_periph_reset_disable(RCU_OSPIMRST);
}
/*!
\brief configurate SCK for port
\param[in] port: number of port
only one parameter can be selected which is shown as below:
\arg OSPIM_PORT0: port 0
\arg OSPIM_PORT1: port 1, only for internal ESC
\param[in] sckconfg: enable or disable SCK
only one parameter can be selected which is shown as below:
\arg OSPIM_PORT_SCK_DISABLE: disable SCK
\arg OSPIM_PORT_SCK_ENABLE: enable SCK
\param[out] none
\retval none
*/
void ospim_port_sck_config(uint8_t port, uint32_t sckconfg)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_OSPIM_PORT(port)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else if(NOT_OSPIM_PORT_SCK(sckconfg)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else
#endif
{
OSPIM_PCFG(port) &= (uint32_t)(~OSPIM_PCFG_SCKEN);
OSPIM_PCFG(port) |= (uint32_t)sckconfg;
}
}
/*!
\brief select source of SCK for port
\param[in] port: number of port
only one parameter can be selected which is shown as below:
\arg OSPIM_PORT0: port 0
\arg OSPIM_PORT1: port 1, only for internal ESC
\param[in] sck_source: source of SCK
only one parameter can be selected which is shown as below:
\arg OSPIM_SCK_SOURCE_OSPI0_SCK: the source of SCK is OSPI0_SCK
\arg OSPIM_SCK_SOURCE_OSPI1_SCK: the source of SCK is OSPI1_SCK
\param[out] none
\retval none
*/
void ospim_port_sck_source_select(uint8_t port, uint32_t sck_source)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_OSPIM_PORT(port)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else if(NOT_OSPIM_PORT_SCK_SOURCE(sck_source)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else
#endif
{
OSPIM_PCFG(port) &= (uint32_t)(~OSPIM_PCFG_SRCPCK);
OSPIM_PCFG(port) |= (uint32_t)sck_source;
}
}
/*!
\brief configurate CSN for port
\param[in] port: number of port
only one parameter can be selected which is shown as below:
\arg OSPIM_PORT0: port 0
\arg OSPIM_PORT1: port 1, only for internal ESC
\param[in] csnconfig: enable or disable CSN
only one parameter can be selected which is shown as below:
\arg OSPIM_PORT_CSN_DISABLE: disable CSN
\arg OSPIM_PORT_CSN_ENABLE: enable CSN
\param[out] none
\retval none
*/
void ospim_port_csn_config(uint8_t port, uint32_t csnconfig)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_OSPIM_PORT(port)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else if(NOT_OSPIM_PORT_CSN(csnconfig)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0002U), ERR_PERIPH);
} else
#endif
{
OSPIM_PCFG(port) &= (uint32_t)(~OSPIM_PCFG_NCSEN);
OSPIM_PCFG(port) |= (uint32_t)csnconfig;
}
}
/*!
\brief select source of CSN for port
\param[in] port: number of port
only one parameter can be selected which is shown as below:
\arg OSPIM_PORT0: port 0
\arg OSPIM_PORT1: port 1, only for internal ESC
\param[in] csn_source: source of CSN
only one parameter can be selected which is shown as below:
\arg OSPIM_CSN_SOURCE_OSPI0_CSN: the source of CSN is OSPI0_CSN
\arg OSPIM_CSN_SOURCE_OSPI1_CSN: the source of CSN is OSPI1_CSN
\param[out] none
\retval none
*/
void ospim_port_csn_source_select(uint8_t port, uint32_t csn_source)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_OSPIM_PORT(port)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else if(NOT_OSPIM_PORT_CSN_SOURCE(csn_source)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0002U), ERR_PERIPH);
} else
#endif
{
OSPIM_PCFG(port) &= (uint32_t)(~OSPIM_PCFG_SRCPCS);
OSPIM_PCFG(port) |= (uint32_t)csn_source;
}
}
/*!
\brief configurate IO[3:0] for port
\param[in] port: number of port
only one parameter can be selected which is shown as below:
\arg OSPIM_PORT0: port 0
\arg OSPIM_PORT1: port 1, only for internal ESC
\param[in] ioconfig: enable or disable IO[3:0]
only one parameter can be selected which is shown as below:
\arg OSPIM_IO_LOW_DISABLE: disable IO[3:0]
\arg OSPIM_IO_LOW_ENABLE: enable IO[3:0]
\param[out] none
\retval none
*/
void ospim_port_io3_0_config(uint8_t port, uint32_t ioconfig)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_OSPIM_PORT(port)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else if(NOT_OSPIM_IO_LOW(ioconfig)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0003U), ERR_PERIPH);
} else
#endif
{
OSPIM_PCFG(port) &= (uint32_t)(~OSPIM_PCFG_POLEN);
OSPIM_PCFG(port) |= (uint32_t)ioconfig;
}
}
/*!
\brief select source of IO[3:0] for port
\param[in] port: number of port
only one parameter can be selected which is shown as below:
\arg OSPIM_PORT0: port 0
\arg OSPIM_PORT1: port 1, only for internal ESC
\param[in] csn_source: source of IO[3:0]
only one parameter can be selected which is shown as below:
\arg OSPIM_SRCPLIO_OSPI0_IO_LOW: select OSPI0_IO[3:0]
\arg OSPIM_SRCPLIO_OSPI0_IO_HIGH: select OSPI0_IO[7:4]
\arg OSPIM_SRCPLIO_OSPI1_IO_LOW: select OSPI1_IO[3:0]
\arg OSPIM_SRCPLIO_OSPI1_IO_HIGH: select OSPI1_IO[7:4]
\param[out] none
\retval none
*/
void ospim_port_io3_0_source_select(uint8_t port, uint32_t io_source)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_OSPIM_PORT(port)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else if(NOT_OSPIM_SRC_LOW(io_source)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0004U), ERR_PERIPH);
} else
#endif
{
OSPIM_PCFG(port) &= (uint32_t)(~OSPIM_PCFG_SRCPLIO);
OSPIM_PCFG(port) |= (uint32_t)io_source;
}
}
/*!
\brief configurate IO[7:4] for port
\param[in] port: number of port
only one parameter can be selected which is shown as below:
\arg OSPIM_PORT0: port 0
\arg OSPIM_PORT1: port 1, only for internal ESC
\param[in] ioconfig: enable or disable IO[7:4]
only one parameter can be selected which is shown as below:
\arg OSPIM_IO_HIGH_DISABLE: disable IO[7:4]
\arg OSPIM_IO_HIGH_ENABLE: enable IO[7:4]
\param[out] none
\retval none
*/
void ospim_port_io7_4_config(uint8_t port, uint32_t ioconfig)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_OSPIM_PORT(port)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else if(NOT_OSPIM_IO_HIGH(ioconfig)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0005U), ERR_PERIPH);
} else
#endif
{
OSPIM_PCFG(port) &= (uint32_t)(~OSPIM_PCFG_POHEN);
OSPIM_PCFG(port) |= (uint32_t)ioconfig;
}
}
/*!
\brief select source of IO[7:4] for port
\param[in] port: number of port
only one parameter can be selected which is shown as below:
\arg OSPIM_PORT0: port 0
\arg OSPIM_PORT1: port 1, only for internal ESC
\param[in] csn_source: source of IO[7:4]
only one parameter can be selected which is shown as below:
\arg OSPIM_SRCPHIO_OSPI0_IO_LOW: select OSPI0_IO[3:0]
\arg OSPIM_SRCPHIO_OSPI0_IO_HIGH: select OSPI0_IO[7:4]
\arg OSPIM_SRCPHIO_OSPI1_IO_LOW: select OSPI1_IO[3:0]
\arg OSPIM_SRCPHIO_OSPI1_IO_HIGH: select OSPI1_IO[7:4]
\param[out] none
\retval none
*/
void ospim_port_io7_4_source_select(uint8_t port, uint32_t io_source)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_OSPIM_PORT(port)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0001U), ERR_PERIPH);
} else if(NOT_OSPIM_SRC_HIGH(io_source)) {
fw_debug_report_err(OSPIM_MODULE_ID, API_ID(0x0006U), ERR_PERIPH);
} else
#endif
{
OSPIM_PCFG(port) &= (uint32_t)(~OSPIM_PCFG_SRCPHIO);
OSPIM_PCFG(port) |= (uint32_t)io_source;
}
}
@@ -0,0 +1,667 @@
/*!
\file gd32h75e_pmu.c
\brief PMU driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_pmu.h"
/* PMU register bit offset */
#define PAR_TSW_IRCCNT_OFFSET ((uint32_t)0x00000010U) /*!< bit offset of PAR_TSW_IRCCNT_OFFSET in PMU_PAR */
/*!
\brief reset PMU register
\param[in] none
\param[out] none
\retval none
*/
void pmu_deinit(void)
{
/* reset PMU */
rcu_periph_reset_enable(RCU_PMURST);
rcu_periph_reset_disable(RCU_PMURST);
}
/*!
\brief select low voltage detector threshold
\param[in] lvdt_n:
only one parameter can be selected which is shown as below:
\arg PMU_LVDT_0: voltage threshold is 1.90V
\arg PMU_LVDT_1: voltage threshold is 2.05V
\arg PMU_LVDT_2: voltage threshold is 2.20V
\arg PMU_LVDT_3: voltage threshold is 2.35V
\arg PMU_LVDT_4: voltage threshold is 2.50V
\arg PMU_LVDT_5: voltage threshold is 2.65V
\arg PMU_LVDT_6: voltage threshold is 2.80V
\arg PMU_LVDT_7: input analog voltage on PB7 (compared with 0.8V)
\param[out] none
\retval none
*/
void pmu_lvd_select(uint32_t lvdt_n)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_LVD(lvdt_n)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x0002U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t temp;
temp = PMU_CTL0;
/* clear LVDT bits */
temp &= ~PMU_CTL0_LVDT;
/* set LVDT bits according to lvdt_n */
temp |= lvdt_n;
PMU_CTL0 = temp;
}
}
/*!
\brief enable PMU lvd
\param[in] none
\param[out] none
\retval none
*/
void pmu_lvd_enable(void)
{
PMU_CTL0 |= PMU_CTL0_LVDEN;
}
/*!
\brief disable PMU lvd
\param[in] none
\param[out] none
\retval none
*/
void pmu_lvd_disable(void)
{
PMU_CTL0 &= ~PMU_CTL0_LVDEN;
}
/*!
\brief select analog voltage detector threshold
\param[in] vavdt_n:
only one parameter can be selected which is shown as below:
\arg PMU_VAVDVC_0: voltage threshold of analog voltage detector is 1.7V
\arg PMU_VAVDVC_1: voltage threshold of analog voltage detector is 2.1V
\arg PMU_VAVDVC_2: voltage threshold of analog voltage detector is 2.5V
\arg PMU_VAVDVC_3: voltage threshold of analog voltage detector is 2.8V
\param[out] none
\retval none
*/
void pmu_vavd_select(uint32_t vavdt_n)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_VAVD(vavdt_n)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x0005U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t temp;
temp = PMU_CTL0;
/* clear VAVDVC bits */
temp &= ~PMU_CTL0_VAVDVC;
/* set VAVDVC bits according to vavdt_n */
temp |= vavdt_n;
PMU_CTL0 = temp;
}
}
/*!
\brief enable PMU analog voltage detector
\param[in] none
\param[out] none
\retval none
*/
void pmu_vavd_enable(void)
{
PMU_CTL0 |= PMU_CTL0_VAVDEN;
}
/*!
\brief disable PMU analog voltage detector
\param[in] none
\param[out] none
\retval none
*/
void pmu_vavd_disable(void)
{
PMU_CTL0 &= ~PMU_CTL0_VAVDEN;
}
/*!
\brief enable PMU V0.9V core voltage detector
\param[in] none
\param[out] none
\retval none
*/
void pmu_vovd_enable(void)
{
PMU_CTL0 |= PMU_CTL0_VOVDEN;
}
/*!
\brief disable PMU V0.9V core voltage detector
\param[in] none
\param[out] none
\retval none
*/
void pmu_vovd_disable(void)
{
PMU_CTL0 &= ~PMU_CTL0_VOVDEN;
}
/*!
\brief control the V0.9V core voltage level
\param[in] ldo_n:
only one parameter can be selected which is shown as below:
\arg PMU_LDOVS_0: LDO output voltage 0.8V mode
\arg PMU_LDOVS_1: LDO output voltage 0.85V mode
\arg PMU_LDOVS_2: LDO output voltage 0.9V mode
\arg PMU_LDOVS_3: LDO output voltage 0.95V mode
\arg PMU_LDOVS_4: LDO output voltage 0.975V mode
\arg PMU_LDOVS_5: LDO output voltage 1V mode
\param[out] none
\retval none
*/
void pmu_ldo_output_select(uint32_t ldo_n)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_LDO(ldo_n)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x000AU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t temp;
temp = PMU_CTL3;
temp &= ~PMU_CTL3_LDOVS;
temp |= ldo_n;
PMU_CTL3 = temp;
}
}
/*!
\brief Deep-sleep mode V0.9V core voltage select
\param[in] sldo:
only one parameter can be selected which is shown as below:
\arg PMU_SLDOVS_0: SLDOVS scale 0.6V
\arg PMU_SLDOVS_1: SLDOVS scale 0.7V
\arg PMU_SLDOVS_2: SLDOVS scale 0.8V
\arg PMU_SLDOVS_3: SLDOVS scale 0.9V
\param[out] none
\retval none
*/
void pmu_sldo_output_select(uint32_t sldo_n)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_SLDO(sldo_n)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x000BU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t temp;
temp = PMU_CTL0;
temp &= ~PMU_CTL0_SLDOVS;
temp |= sldo_n;
PMU_CTL0 = temp;
}
}
/*!
\brief PMU VBAT battery charging resistor selection
\param[in] resistor:
only one parameter can be selected which is shown as below:
\arg PMU_VCRSEL_5K: 5kOhms resistor is selected for charing VBAT battery
\arg PMU_VCRSEL_1P5K: 1.5kOhms resistor is selected for charing VBAT battery
\param[out] none
\retval none
*/
void pmu_vbat_charging_select(uint32_t resistor)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_VBAT(resistor)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x000CU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
PMU_CTL2 &= ~PMU_CTL2_VCRSEL;
PMU_CTL2 |= resistor;
}
}
/*!
\brief enable VBAT battery charging
\param[in] none
\param[out] none
\retval none
*/
void pmu_vbat_charging_enable(void)
{
PMU_CTL2 |= PMU_CTL2_VCEN;
}
/*!
\brief disable VBAT battery charging
\param[in] none
\param[out] none
\retval none
*/
void pmu_vbat_charging_disable(void)
{
PMU_CTL2 &= ~PMU_CTL2_VCEN;
}
/*!
\brief enable VBAT and temperature monitoring
\param[in] none
\param[out] none
\retval none
*/
void pmu_vbat_temp_moniter_enable(void)
{
PMU_CTL1 |= PMU_CTL1_VBTMEN;
}
/*!
\brief disable VBAT and temperature monitoring
\param[in] none
\param[out] none
\retval none
*/
void pmu_vbat_temp_moniter_disable(void)
{
PMU_CTL1 &= ~PMU_CTL1_VBTMEN;
}
/*!
\brief enable USB regulator
\param[in] none
\param[out] none
\retval none
*/
void pmu_usb_regulator_enable(void)
{
PMU_CTL2 |= PMU_CTL2_USBSEN;
}
/*!
\brief disable USB regulator
\param[in] none
\param[out] none
\retval none
*/
void pmu_usb_regulator_disable(void)
{
PMU_CTL2 &= ~PMU_CTL2_USBSEN;
}
/*!
\brief enable VDD33USB voltage level detector
\param[in] none
\param[out] none
\retval none
*/
void pmu_usb_voltage_detector_enable(void)
{
PMU_CTL2 |= PMU_CTL2_VUSB33DEN;
}
/*!
\brief disable VDD33USB voltage level detector
\param[in] none
\param[out] none
\retval none
*/
void pmu_usb_voltage_detector_disable(void)
{
PMU_CTL2 &= ~PMU_CTL2_VUSB33DEN;
}
/*!
\brief power supply configurations
\param[in] smpsmode:
only one parameter can be selected which is shown as below:
\arg PMU_LDO_SUPPLY: V0.9V domains are suppplied from the LDO
\arg PMU_DIRECT_SMPS_SUPPLY: V0.9V domains are suppplied from the SMPS only
\arg PMU_BYPASS: the SMPS disabled and the LDO Bypass. The V0.9V domains are supplied from an external source
\param[out] none
\retval none
*/
void pmu_smps_ldo_supply_config(uint32_t smpsmode)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_SMPS_LDO_SUPPLY(smpsmode)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x0015U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t temp;
temp = PMU_CTL2;
temp &= ~(PMU_CTL2_DVSEN | PMU_CTL2_LDOEN | PMU_CTL2_BYPASS);
temp |= smpsmode;
PMU_CTL2 = temp;
while(0U == (PMU_CTL3 & PMU_CTL3_VOVRF)) {
}
}
}
/*!
\brief enter sleep mode
\param[in] sleepmodecmd:
only one parameter can be selected which is shown as below:
\arg WFI_CMD: use WFI command
\arg WFE_CMD: use WFE command
\param[out] none
\retval none
*/
void pmu_to_sleepmode(uint8_t sleepmodecmd)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_SLEEPMODE(sleepmodecmd)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x0016U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* clear sleepdeep bit of Cortex-M7 system control register */
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
/* select WFI or WFE command to enter sleep mode */
if(WFI_CMD == sleepmodecmd) {
__WFI();
} else {
__SEV();
__WFE();
__WFE();
}
}
}
/*!
\brief enter deepsleep mode
\param[in] deepsleepmodecmd:
only one parameter can be selected which is shown as below:
\arg WFI_CMD: use WFI command
\arg WFE_CMD: use WFE command
\param[out] none
\retval none
*/
void pmu_to_deepsleepmode(uint8_t deepsleepmodecmd)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_DEEPSLEEPMODE(deepsleepmodecmd)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x0017U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* clear standby mode */
PMU_CTL0 &= ~((uint32_t)(PMU_CTL0_STBMOD));
/* set sleepdeep bit of Cortex-M7 system control register */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
/* select WFI or WFE command to enter deepsleep mode */
if(WFI_CMD == deepsleepmodecmd) {
__WFI();
} else {
__SEV();
__WFE();
__WFE();
}
/* reset sleepdeep bit of Cortex-M7 system control register */
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
}
}
/*!
\brief enter standby mode
\param[in] none
\param[out] none
\retval none
*/
void pmu_to_standbymode(void)
{
/* set stbmod bit */
PMU_CTL0 |= PMU_CTL0_STBMOD;
/* reset wakeup flag */
PMU_CTL0 |= PMU_CTL0_WURST;
/* set sleepdeep bit of Cortex-M7 system control register */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
REG32(0xE000E010U) &= 0x00010004U;
REG32(0xE000E180U) = 0xFF87FFFFU;
REG32(0xE000E184U) = 0x1FFDFBFFU;
REG32(0xE000E188U) = 0x907F3FF0U;
REG32(0xE000E18CU) = 0x8473C041U;
REG32(0xE000E190U) = 0x06430200U;
REG32(0xE000E194U) = 0xFFFBFFE6U;
REG32(0xE000E198U) = 0x007FFFFFU;
/* enter standby mode */
__WFI();
}
/*!
\brief enable PMU wakeup pin
\param[in] wakeup_pin:
only one parameter can be selected which is shown as below:
\arg PMU_WAKEUP_PIN0: WKUP Pin 0
\arg PMU_WAKEUP_PIN1: WKUP Pin 1
\arg PMU_WAKEUP_PIN3: WKUP Pin 3
\arg PMU_WAKEUP_PIN5: WKUP Pin 5
\param[out] none
\retval none
*/
void pmu_wakeup_pin_enable(uint32_t wakeup_pin)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_WAKEUP_PIN(wakeup_pin)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x0018U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
PMU_CS |= wakeup_pin;
}
}
/*!
\brief disable PMU wakeup pin
\param[in] wakeup_pin:
only one parameter can be selected which is shown as below:
\arg PMU_WAKEUP_PIN0: WKUP Pin 0
\arg PMU_WAKEUP_PIN1: WKUP Pin 1
\arg PMU_WAKEUP_PIN3: WKUP Pin 3
\arg PMU_WAKEUP_PIN5: WKUP Pin 5
\param[out] none
\retval none
*/
void pmu_wakeup_pin_disable(uint32_t wakeup_pin)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_WAKEUP_PIN(wakeup_pin)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x0019U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
PMU_CS &= ~(wakeup_pin);
}
}
/*!
\brief enable backup domain write
\param[in] none
\param[out] none
\retval none
*/
void pmu_backup_write_enable(void)
{
PMU_CTL0 |= PMU_CTL0_BKPWEN;
}
/*!
\brief disable backup domain write
\param[in] none
\param[out] none
\retval none
*/
void pmu_backup_write_disable(void)
{
PMU_CTL0 &= ~PMU_CTL0_BKPWEN;
}
/*!
\brief enable backup voltage stabilizer
\param[in] none
\param[out] none
\retval none
*/
void pmu_backup_voltage_stabilizer_enable(void)
{
PMU_CTL1 |= PMU_CTL1_BKPVSEN;
while(RESET == (PMU_CTL1 & PMU_CTL1_BKPVSRF)) {
}
}
/*!
\brief disable backup voltage stabilizer
\param[in] none
\param[out] none
\retval none
*/
void pmu_backup_voltage_stabilizer_disable(void)
{
PMU_CTL1 &= ~PMU_CTL1_BKPVSEN;
}
/*!
\brief configure IRC counter before enter Deep-sleep mode
\param[in] wait_time: 0x0~0x1F, IRC counter before enter Deep-sleep mode
\param[out] none
\retval none
*/
void pmu_enter_deepsleep_wait_time_config(int32_t wait_time)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_ENTER_DEEPSLEEP_WAIT_TIME(wait_time)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x0020U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t temp;
temp = PMU_PAR;
temp &= ~PMU_PAR_TSW_IRCCNT;
temp |= ((uint32_t)wait_time << PAR_TSW_IRCCNT_OFFSET);
PMU_PAR = temp;
}
}
/*!
\brief configure IRC counter before exit Deep-sleep mode
\param[in] wait_time: 0x0~0xFFF, IRC counter before exit Deep-sleep mode
\param[out] none
\retval none
*/
void pmu_exit_deepsleep_wait_time_config(int32_t wait_time)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_EXIT_DEEPSLEEP_WAIT_TIME(wait_time)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x0021U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t temp;
temp = PMU_PAR;
temp &= ~PMU_PAR_CNT;
temp |= (uint32_t)(wait_time);
PMU_PAR = temp;
}
}
/*!
\brief get flag state
\param[in] flag:
only one parameter can be selected which is shown as below:
\arg PMU_FLAG_WAKEUP: wakeup flag
\arg PMU_FLAG_STANDBY: standby flag
\arg PMU_FLAG_LVDF: low voltage detector status flag
\arg PMU_FLAG_VAVDF: VDDA analog voltage detector voltage output on VDDA flag
\arg PMU_FLAG_VOVDF: peripheral voltage on VDDA detector flag
\arg PMU_FLAG_VBATLF: VBAT level monitoring versus low threshold
\arg PMU_FLAG_VBATHF: VBAT level monitoring versus high threshold
\arg PMU_FLAG_TEMPLF: temperature level monitoring versus low threshold
\arg PMU_FLAG_TEMPHF: temperature level monitoring versus high threshold
\arg PMU_FLAG_DVSRF: step-down voltage stabilizer ready flag bit
\arg PMU_FLAG_USB33RF: USB supply ready flag bit
\arg PMU_FLAG_PWRRF: power Ready flag bit.
\param[out] none
\retval FlagStatus SET or RESET
*/
FlagStatus pmu_flag_get(uint32_t flag)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_FLAG(flag)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x0022U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(PMU_REG_VAL(flag) & BIT(PMU_BIT_POS(flag))) {
return SET;
}
}
return RESET;
}
/*!
\brief clear flag bit
\param[in] flag_reset:
\arg PMU_FLAG_WAKEUP: wakeup flag
\arg PMU_FLAG_STANDBY: standby flag
\param[out] none
\retval none
*/
void pmu_flag_clear(uint32_t flag_reset)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_PMU_FLAG_RESET(flag_reset)) {
fw_debug_report_err(PMU_MODULE_ID, API_ID(0x0023U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(PMU_FLAG_WAKEUP == flag_reset) {
PMU_CTL0 |= PMU_CTL0_WURST;
} else {
if(PMU_FLAG_STANDBY == flag_reset) {
PMU_CTL0 |= PMU_CTL0_STBRST;
}
}
}
}
@@ -0,0 +1,513 @@
/*!
\file gd32h75e_rameccmu.c
\brief RAMECCMU driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_rameccmu.h"
#define RAMECCMU_REG_RESET_VALUE 0x00000000U
/*!
\brief deinit RAMECCMU unit
\param[in] rameccmu_periph: RAMECCMUx(x=0,1)
\param[out] none
\retval none
*/
void rameccmu_deinit(uint32_t rameccmu_periph)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_PERIPH(rameccmu_periph)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(0), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
RAMECCMU_INT(rameccmu_periph) = RAMECCMU_REG_RESET_VALUE;
if(RAMECCMU0 == rameccmu_periph){
/* reset RAMECCMU0_MONITOR0 registers */
RAMECCMU_MXCTL(RAMECCMU0_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXSTAT(RAMECCMU0_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFADDR(RAMECCMU0_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDL(RAMECCMU0_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDH(RAMECCMU0_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFECODE(RAMECCMU0_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
/* reset RAMECCMU0_MONITOR1 registers */
RAMECCMU_MXCTL(RAMECCMU0_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXSTAT(RAMECCMU0_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFADDR(RAMECCMU0_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDL(RAMECCMU0_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDH(RAMECCMU0_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFECODE(RAMECCMU0_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
/* reset RAMECCMU0_MONITOR2 registers */
RAMECCMU_MXCTL(RAMECCMU0_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXSTAT(RAMECCMU0_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFADDR(RAMECCMU0_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDL(RAMECCMU0_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDH(RAMECCMU0_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFECODE(RAMECCMU0_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
/* reset RAMECCMU0_MONITOR3 registers */
RAMECCMU_MXCTL(RAMECCMU0_MONITOR3) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXSTAT(RAMECCMU0_MONITOR3) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFADDR(RAMECCMU0_MONITOR3) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDL(RAMECCMU0_MONITOR3) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDH(RAMECCMU0_MONITOR3) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFECODE(RAMECCMU0_MONITOR3) = RAMECCMU_REG_RESET_VALUE;
/* reset RAMECCMU0_MONITOR4 registers */
RAMECCMU_MXCTL(RAMECCMU0_MONITOR4) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXSTAT(RAMECCMU0_MONITOR4) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFADDR(RAMECCMU0_MONITOR4) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDL(RAMECCMU0_MONITOR4) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDH(RAMECCMU0_MONITOR4) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFECODE(RAMECCMU0_MONITOR4) = RAMECCMU_REG_RESET_VALUE;
}else{
/* reset RAMECCMU1_MONITOR0 registers */
RAMECCMU_MXCTL(RAMECCMU1_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXSTAT(RAMECCMU1_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFADDR(RAMECCMU1_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDL(RAMECCMU1_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDH(RAMECCMU1_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFECODE(RAMECCMU1_MONITOR0) = RAMECCMU_REG_RESET_VALUE;
/* reset RAMECCMU1_MONITOR1 registers */
RAMECCMU_MXCTL(RAMECCMU1_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXSTAT(RAMECCMU1_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFADDR(RAMECCMU1_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDL(RAMECCMU1_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDH(RAMECCMU1_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFECODE(RAMECCMU1_MONITOR1) = RAMECCMU_REG_RESET_VALUE;
/* reset RAMECCMU1_MONITOR2 registers */
RAMECCMU_MXCTL(RAMECCMU1_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXSTAT(RAMECCMU1_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFADDR(RAMECCMU1_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDL(RAMECCMU1_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFDH(RAMECCMU1_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
RAMECCMU_MXFECODE(RAMECCMU1_MONITOR2) = RAMECCMU_REG_RESET_VALUE;
}
}
}
/*!
\brief get RAMECCMU monitor ECC failing address
\param[in] rameccmu_monitor: RAMECCMU monitor
only one parameter can be selected which is shown as below:
\arg RAMECCMU0_MONITOR0: RAMECCMU0 monitor 0
\arg RAMECCMU0_MONITOR1: RAMECCMU0 monitor 1
\arg RAMECCMU0_MONITOR2: RAMECCMU0 monitor 2
\arg RAMECCMU0_MONITOR3: RAMECCMU0 monitor 3
\arg RAMECCMU0_MONITOR4: RAMECCMU0 monitor 4
\arg RAMECCMU1_MONITOR0: RAMECCMU1 monitor 0
\arg RAMECCMU1_MONITOR1: RAMECCMU1 monitor 1
\arg RAMECCMU1_MONITOR2: RAMECCMU1 monitor 2
\param[out] none
\retval ECC error failing address
*/
uint32_t rameccmu_monitor_failing_address_get(rameccmu_monitor_enum rameccmu_monitor)
{
uint32_t temp_mxfaddr = 0U;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_MONITOR(rameccmu_monitor)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(1), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
temp_mxfaddr = RAMECCMU_MXFADDR(rameccmu_monitor);
}
return temp_mxfaddr;
}
/*!
\brief get RAMECCMU monitor ECC failing data low 32 bits
\param[in] rameccmu_monitor: RAMECCMU monitor
only one parameter can be selected which is shown as below:
\arg RAMECCMU0_MONITOR0: RAMECCMU0 monitor 0
\arg RAMECCMU0_MONITOR1: RAMECCMU0 monitor 1
\arg RAMECCMU0_MONITOR2: RAMECCMU0 monitor 2
\arg RAMECCMU0_MONITOR3: RAMECCMU0 monitor 3
\arg RAMECCMU0_MONITOR4: RAMECCMU0 monitor 4
\arg RAMECCMU1_MONITOR0: RAMECCMU1 monitor 0
\arg RAMECCMU1_MONITOR1: RAMECCMU1 monitor 1
\arg RAMECCMU1_MONITOR2: RAMECCMU1 monitor 2
\param[out] none
\retval ECC failing data low 32 bits
*/
uint32_t rameccmu_monitor_failing_data_low_bits_get(rameccmu_monitor_enum rameccmu_monitor)
{
uint32_t temp_mxfdl = 0U;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_MONITOR(rameccmu_monitor)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(2), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
temp_mxfdl = RAMECCMU_MXFDL(rameccmu_monitor);
}
return temp_mxfdl;
}
/*!
\brief get RAMECCMU monitor ECC failing data high 32 bits
\param[in] rameccmu_monitor: RAMECCMU monitor
only one parameter can be selected which is shown as below:
\arg RAMECCMU0_MONITOR0: RAMECCMU0 monitor 0
\arg RAMECCMU0_MONITOR1: RAMECCMU0 monitor 1
\arg RAMECCMU0_MONITOR2: RAMECCMU0 monitor 2
\arg RAMECCMU0_MONITOR3: RAMECCMU0 monitor 3
\arg RAMECCMU0_MONITOR4: RAMECCMU0 monitor 4
\arg RAMECCMU1_MONITOR0: RAMECCMU1 monitor 0
\arg RAMECCMU1_MONITOR1: RAMECCMU1 monitor 1
\arg RAMECCMU1_MONITOR2: RAMECCMU1 monitor 2
\param[out] none
\retval ECC failing data high 32 bits
*/
uint32_t rameccmu_monitor_failing_data_high_bits_get(rameccmu_monitor_enum rameccmu_monitor)
{
uint32_t temp_mxfdh = 0U;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_MONITOR(rameccmu_monitor)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(3), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
temp_mxfdh = RAMECCMU_MXFDH(rameccmu_monitor);
}
return temp_mxfdh;
}
/*!
\brief get RAMECCMU monitor failing ECC error code
\param[in] rameccmu_monitor: RAMECCMU monitor
only one parameter can be selected which is shown as below:
\arg RAMECCMU0_MONITOR0: RAMECCMU0 monitor 0
\arg RAMECCMU0_MONITOR1: RAMECCMU0 monitor 1
\arg RAMECCMU0_MONITOR2: RAMECCMU0 monitor 2
\arg RAMECCMU0_MONITOR3: RAMECCMU0 monitor 3
\arg RAMECCMU0_MONITOR4: RAMECCMU0 monitor 4
\arg RAMECCMU1_MONITOR0: RAMECCMU1 monitor 0
\arg RAMECCMU1_MONITOR1: RAMECCMU1 monitor 1
\arg RAMECCMU1_MONITOR2: RAMECCMU1 monitor 2
\param[out] none
\retval ECC failing error code
*/
uint32_t rameccmu_monitor_failing_ecc_error_code_get(rameccmu_monitor_enum rameccmu_monitor)
{
uint32_t temp_mxfecode = 0U;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_MONITOR(rameccmu_monitor)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(4), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
temp_mxfecode = RAMECCMU_MXFECODE(rameccmu_monitor);
}
return temp_mxfecode;
}
/*!
\brief enable RAMECCMU global ECC interruput
\param[in] rameccmu_periph: RAMECCMU
only one parameter can be selected which is shown as below:
\arg RAMECCMU0: RAMECCMU for region 0
\arg RAMECCMU1: RAMECCMU for region 1
\param[in] interrupt: global ECC interruput
one or more parameters can be selected which are shown as below:
\arg RAMECCMU_INT_ECC_GLOBAL_ERROR: ECC global error interrupt
\arg RAMECCMU_INT_ECC_SINGLE_ERROR: ECC single error interrupt
\arg RAMECCMU_INT_ECC_DOUBLE_ERROR: ECC double error interrupt
\arg RAMECCMU_INT_ECC_DOUBLE_ERROR_BYTE_WRITE: ECC double error on byte write interrupt
\param[out] none
\retval none
*/
void rameccmu_global_interrupt_enable(uint32_t rameccmu_periph, uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_PERIPH(rameccmu_periph)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(5), ERR_PARAM_INVALID);
} else if(NOT_RAMECCMU_INT_ERROR(interrupt)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(5), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
RAMECCMU_INT(rameccmu_periph) |= interrupt;
}
}
/*!
\brief disable RAMECCMU global ECC interruput
\param[in] rameccmu_periph: RAMECCMU
only one parameter can be selected which is shown as below:
\arg RAMECCMU0: RAMECCMU for region 0
\arg RAMECCMU1: RAMECCMU for region 1
\param[in] interrupt: global ECC interruput
one or more parameters can be selected which are shown as below:
\arg RAMECCMU_INT_ECC_GLOBAL_ERROR: ECC global error interrupt
\arg RAMECCMU_INT_ECC_SINGLE_ERROR: ECC single error interrupt
\arg RAMECCMU_INT_ECC_DOUBLE_ERROR: ECC double error interrupt
\arg RAMECCMU_INT_ECC_DOUBLE_ERROR_BYTE_WRITE: ECC double error on byte write interrupt
\param[out] none
\retval none
*/
void rameccmu_global_interrupt_disable(uint32_t rameccmu_periph, uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_PERIPH(rameccmu_periph)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(6), ERR_PARAM_INVALID);
} else if(NOT_RAMECCMU_INT_ERROR(interrupt)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(6), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
RAMECCMU_INT(rameccmu_periph) &= (uint32_t)(~interrupt);
}
}
/*!
\brief enable RAMECCMU monitor ECC error interruput
\param[in] rameccmu_monitor: RAMECCMU monitor
only one parameter can be selected which is shown as below:
\arg RAMECCMU0_MONITOR0: RAMECCMU0 monitor 0
\arg RAMECCMU0_MONITOR1: RAMECCMU0 monitor 1
\arg RAMECCMU0_MONITOR2: RAMECCMU0 monitor 2
\arg RAMECCMU0_MONITOR3: RAMECCMU0 monitor 3
\arg RAMECCMU0_MONITOR4: RAMECCMU0 monitor 4
\arg RAMECCMU1_MONITOR0: RAMECCMU1 monitor 0
\arg RAMECCMU1_MONITOR1: RAMECCMU1 monitor 1
\arg RAMECCMU1_MONITOR2: RAMECCMU1 monitor 2
\param[in] monitor_interrupt: RAMECCMU monitor interruput
one or more parameters can be selected which are shown as below:
\arg RAMECCMU_INT_ECC_SINGLE_ERROR: ECC single error interrupt
\arg RAMECCMU_INT_ECC_DOUBLE_ERROR: ECC double error interrupt
\arg RAMECCMU_INT_ECC_DOUBLE_ERROR_BYTE_WRITE: ECC double error on byte write interrupt
\arg RAMECCMU_INT_ECC_ERROR_LATCHING: ECC error latching
\param[out] none
\retval none
*/
void rameccmu_monitor_interrupt_enable(rameccmu_monitor_enum rameccmu_monitor, uint32_t monitor_interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_MONITOR(rameccmu_monitor)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(7), ERR_PARAM_INVALID);
} else if(NOT_RAMECCMU_MONITOR_INT_ERROR(monitor_interrupt)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(7), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
RAMECCMU_MXCTL(rameccmu_monitor) |= (uint32_t)monitor_interrupt << 1U;
}
}
/*!
\brief disable RAMECCMU monitor ECC error interruput
\param[in] rameccmu_monitor: RAMECCMU monitor
only one parameter can be selected which is shown as below:
\arg RAMECCMU0_MONITOR0: RAMECCMU0 monitor 0
\arg RAMECCMU0_MONITOR1: RAMECCMU0 monitor 1
\arg RAMECCMU0_MONITOR2: RAMECCMU0 monitor 2
\arg RAMECCMU0_MONITOR3: RAMECCMU0 monitor 3
\arg RAMECCMU0_MONITOR4: RAMECCMU0 monitor 4
\arg RAMECCMU1_MONITOR0: RAMECCMU1 monitor 0
\arg RAMECCMU1_MONITOR1: RAMECCMU1 monitor 1
\arg RAMECCMU1_MONITOR2: RAMECCMU1 monitor 2
\param[in] monitor_interrupt: RAMECCMU monitor interruput
one or more parameters can be selected which are shown as below:
\arg RAMECCMU_INT_ECC_SINGLE_ERROR: ECC single error interrupt
\arg RAMECCMU_INT_ECC_DOUBLE_ERROR: ECC double error interrupt
\arg RAMECCMU_INT_ECC_DOUBLE_ERROR_BYTE_WRITE: ECC double error on byte write interrupt
\arg RAMECCMU_INT_ECC_ERROR_LATCHING: ECC error latching
\param[out] none
\retval none
*/
void rameccmu_monitor_interrupt_disable(rameccmu_monitor_enum rameccmu_monitor, uint32_t monitor_interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_MONITOR(rameccmu_monitor)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(8), ERR_PARAM_INVALID);
} else if(NOT_RAMECCMU_MONITOR_INT_ERROR(monitor_interrupt)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(8), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
RAMECCMU_MXCTL(rameccmu_monitor) &= (uint32_t)~((uint32_t)monitor_interrupt << 1U);
}
}
/*!
\brief get RAMECCMU monitor ECC error flag
\param[in] rameccmu_monitor: RAMECCMU monitor
only one parameter can be selected which is shown as below:
\arg RAMECCMU0_MONITOR0: RAMECCMU0 monitor 0
\arg RAMECCMU0_MONITOR1: RAMECCMU0 monitor 1
\arg RAMECCMU0_MONITOR2: RAMECCMU0 monitor 2
\arg RAMECCMU0_MONITOR3: RAMECCMU0 monitor 3
\arg RAMECCMU0_MONITOR4: RAMECCMU0 monitor 4
\arg RAMECCMU1_MONITOR0: RAMECCMU1 monitor 0
\arg RAMECCMU1_MONITOR1: RAMECCMU1 monitor 1
\arg RAMECCMU1_MONITOR2: RAMECCMU1 monitor 2
\param[in] flag: RAMECCMU monitor flag
one or more parameters can be selected which are shown as below:
\arg RAMECCMU_FLAG_ECC_SINGLE_ERROR: ECC single error detected and corrected flag
\arg RAMECCMU_FLAG_ECC_DOUBLE_ERROR: ECC double error detected flag
\arg RAMECCMU_FLAG_ECC_DOUBLE_ERROR_BYTE_WRITE: ECC double error on byte write detected flag
\param[out] none
\retval RESET or SET
*/
FlagStatus rameccmu_monitor_flag_get(rameccmu_monitor_enum rameccmu_monitor, uint32_t flag)
{
FlagStatus temp_flag = RESET;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_MONITOR(rameccmu_monitor)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(9), ERR_PARAM_INVALID);
} else if(NOT_RAMECCMU_FLAG_ECC_ERROR(flag)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(9), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(RESET != ((RAMECCMU_MXSTAT(rameccmu_monitor)) & flag)){
temp_flag = SET;
} else {
temp_flag = RESET;
}
}
return temp_flag;
}
/*!
\brief clear RAMECCMU monitor ECC error flag
\param[in] rameccmu_monitor: RAMECCMU monitor
only one parameter can be selected which is shown as below:
\arg RAMECCMU0_MONITOR0: RAMECCMU0 monitor 0
\arg RAMECCMU0_MONITOR1: RAMECCMU0 monitor 1
\arg RAMECCMU0_MONITOR2: RAMECCMU0 monitor 2
\arg RAMECCMU0_MONITOR3: RAMECCMU0 monitor 3
\arg RAMECCMU0_MONITOR4: RAMECCMU0 monitor 4
\arg RAMECCMU1_MONITOR0: RAMECCMU1 monitor 0
\arg RAMECCMU1_MONITOR1: RAMECCMU1 monitor 1
\arg RAMECCMU1_MONITOR2: RAMECCMU1 monitor 2
\param[in] flag: RAMECCMU monitor flag
one or more parameters can be selected which are shown as below:
\arg RAMECCMU_FLAG_ECC_SINGLE_ERROR: ECC single error detected and corrected flag
\arg RAMECCMU_FLAG_ECC_DOUBLE_ERROR: ECC double error detected flag
\arg RAMECCMU_FLAG_ECC_DOUBLE_ERROR_BYTE_WRITE: ECC double error on byte write detected flag
\param[out] none
\retval none
*/
void rameccmu_monitor_flag_clear(rameccmu_monitor_enum rameccmu_monitor, uint32_t flag)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_MONITOR(rameccmu_monitor)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(10), ERR_PARAM_INVALID);
} else if(NOT_RAMECCMU_FLAG_ECC_ERROR(flag)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(10), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
RAMECCMU_MXSTAT(rameccmu_monitor) &= (uint32_t)(~flag);
}
}
/*!
\brief get RAMECCMU monitor ECC interrupt error flag
\param[in] rameccmu_monitor: RAMECCMU monitor
only one parameter can be selected which is shown as below:
\arg RAMECCMU0_MONITOR0: RAMECCMU0 monitor 0
\arg RAMECCMU0_MONITOR1: RAMECCMU0 monitor 1
\arg RAMECCMU0_MONITOR2: RAMECCMU0 monitor 2
\arg RAMECCMU0_MONITOR3: RAMECCMU0 monitor 3
\arg RAMECCMU0_MONITOR4: RAMECCMU0 monitor 4
\arg RAMECCMU1_MONITOR0: RAMECCMU1 monitor 0
\arg RAMECCMU1_MONITOR1: RAMECCMU1 monitor 1
\arg RAMECCMU1_MONITOR2: RAMECCMU1 monitor 2
\param[in] int_flag: RAMECCMU monitor flag
one or more parameters can be selected which are shown as below:
\arg RAMECCMU_INT_FLAG_ECC_SINGLE_ERROR: ECC single error detected and corrected flag
\arg RAMECCMU_INT_FLAG_ECC_DOUBLE_ERROR: ECC double error detected flag
\arg RAMECCMU_INT_FLAG_ECC_DOUBLE_ERROR_BYTE_WRITE: ECC double error on byte write detected flag
\param[out] none
\retval none
*/
FlagStatus rameccmu_monitor_interrupt_flag_get(rameccmu_monitor_enum rameccmu_monitor, uint32_t int_flag)
{
uint32_t ret1 = RESET;
uint32_t ret2 = RESET;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_MONITOR(rameccmu_monitor)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(11), ERR_PARAM_INVALID);
} else if(NOT_RAMECCMU_INT_FLAG_ECC_ERROR(int_flag)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(11), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* get the status of interrupt enable bit */
ret1 = RAMECCMU_MXCTL(rameccmu_monitor) & (uint32_t)(int_flag << 2U);
/* get the status of interrupt flag */
ret2 = RAMECCMU_MXSTAT(rameccmu_monitor) & int_flag;
if(ret1 && ret2) {
ret1 = SET;
} else {
ret1 = RESET;
}
}
return (FlagStatus)ret1;
}
/*!
\brief clear RAMECCMU monitor interrupt ECC error flag
\param[in] rameccmu_monitor: RAMECCMU monitor
only one parameter can be selected which is shown as below:
\arg RAMECCMU0_MONITOR0: RAMECCMU0 monitor 0
\arg RAMECCMU0_MONITOR1: RAMECCMU0 monitor 1
\arg RAMECCMU0_MONITOR2: RAMECCMU0 monitor 2
\arg RAMECCMU0_MONITOR3: RAMECCMU0 monitor 3
\arg RAMECCMU0_MONITOR4: RAMECCMU0 monitor 4
\arg RAMECCMU1_MONITOR0: RAMECCMU1 monitor 0
\arg RAMECCMU1_MONITOR1: RAMECCMU1 monitor 1
\arg RAMECCMU1_MONITOR2: RAMECCMU1 monitor 2
\param[in] int_flag: RAMECCMU monitor flag
one or more parameters can be selected which are shown as below:
\arg RAMECCMU_INT_FLAG_ECC_SINGLE_ERROR: ECC single error detected and corrected flag
\arg RAMECCMU_INT_FLAG_ECC_DOUBLE_ERROR: ECC double error detected flag
\arg RAMECCMU_INT_FLAG_ECC_DOUBLE_ERROR_BYTE_WRITE: ECC double error on byte write detected flag
\param[out] none
\retval none
*/
void rameccmu_monitor_interrupt_flag_clear(rameccmu_monitor_enum rameccmu_monitor, uint32_t int_flag)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_RAMECCMU_MONITOR(rameccmu_monitor)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(12), ERR_PARAM_INVALID);
} else if(NOT_RAMECCMU_INT_FLAG_ECC_ERROR(int_flag)) {
fw_debug_report_err(RAMECCMU_MODULE_ID, API_ID(12), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
RAMECCMU_MXSTAT(rameccmu_monitor) &= (uint32_t)(~int_flag);
}
}
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
@@ -0,0 +1,700 @@
/*!
\file gd32h75e_syscfg.c
\brief SYSCFG driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_syscfg.h"
/*!
\brief reset the SYSCFG registers
\param[in] none
\param[out] none
\retval none
*/
void syscfg_deinit(void)
{
rcu_periph_reset_enable(RCU_SYSCFGRST);
rcu_periph_reset_disable(RCU_SYSCFGRST);
}
/*!
\brief enable I2Cx(x=0,1,2,3) fast mode plus or I2C fast mode plus PBx(x=6,7,8,9)
\param[in] i2c_fmp
one or more parameters can be selected which are shown as below:
\arg SYSCFG_I2C0_FMP: I2C0 fast mode plus
\arg SYSCFG_I2C1_FMP: I2C1 fast mode plus
\arg SYSCFG_I2C2_FMP: I2C2 fast mode plus
\arg SYSCFG_I2C3_FMP: I2C3 fast mode plus
\arg SYSCFG_I2C_FMP_PB6: I2C fast mode plus on PB6 pin
\arg SYSCFG_I2C_FMP_PB7: I2C fast mode plus on PB7 pin
\arg SYSCFG_I2C_FMP_PB8: I2C fast mode plus on PB8 pin
\arg SYSCFG_I2C_FMP_PB9: I2C fast mode plus on PB9 pin
\param[out] none
\retval none
*/
void syscfg_i2c_fast_mode_plus_enable(uint32_t i2c_fmp)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_I2C_FMP(i2c_fmp)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(1), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
SYSCFG_PMCFG |= i2c_fmp;
}
}
/*!
\brief disable I2Cx(x=0,1,2,3) fast mode plus or I2C fast mode plus PBx(x=6,7,8,9)
\param[in] i2c_fmp
one or more parameters can be selected which are shown as below:
\arg SYSCFG_I2C0_FMP: I2C0 fast mode plus
\arg SYSCFG_I2C1_FMP: I2C1 fast mode plus
\arg SYSCFG_I2C2_FMP: I2C2 fast mode plus
\arg SYSCFG_I2C3_FMP: I2C3 fast mode plus
\arg SYSCFG_I2C_FMP_PB6: I2C fast mode plus on PB6 pin
\arg SYSCFG_I2C_FMP_PB7: I2C fast mode plus on PB7 pin
\arg SYSCFG_I2C_FMP_PB8: I2C fast mode plus on PB8 pin
\arg SYSCFG_I2C_FMP_PB9: I2C fast mode plus on PB9 pin
\param[out] none
\retval none
*/
void syscfg_i2c_fast_mode_plus_disable(uint32_t i2c_fmp)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_I2C_FMP(i2c_fmp)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(2), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
SYSCFG_PMCFG &= (uint32_t)(~i2c_fmp);
}
}
/*!
\brief open analog switch (Pxy and Pxy_C are separated pads)
\param[in] gpio_answ: GPIO analog switch
one or more parameters can be selected which are shown as below:
\arg SYSCFG_PA0_ANALOG_SWITCH: PA0 analog switch
\arg SYSCFG_PA1_ANALOG_SWITCH: PA1 analog switch
\arg SYSCFG_PC2_ANALOG_SWITCH: PC2 analog switch
\arg SYSCFG_PC3_ANALOG_SWITCH: PC3 analog switch
\param[out] none
\retval none
*/
void syscfg_analog_switch_enable(uint32_t gpio_answ)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_ANALOG_SWITCH(gpio_answ)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(3), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
SYSCFG_PMCFG |= gpio_answ;
}
}
/*!
\brief close analog switch (Pxy and Pxy_C are connected through the analog switch)
\param[in] gpio_answ: GPIO analog switch
one or more parameters can be selected which are shown as below:
\arg SYSCFG_PA0_ANALOG_SWITCH: PA0 analog switch
\arg SYSCFG_PA1_ANALOG_SWITCH: PA1 analog switch
\arg SYSCFG_PC2_ANALOG_SWITCH: PC2 analog switch
\arg SYSCFG_PC3_ANALOG_SWITCH: PC3 analog switch
\param[out] none
\retval none
*/
void syscfg_analog_switch_disable(uint32_t gpio_answ)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_ANALOG_SWITCH(gpio_answ)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(4), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
SYSCFG_PMCFG &= (uint32_t)(~gpio_answ);
}
}
/*!
\brief configure the GPIO pin as EXTI Line
\param[in] exti_port: specify the GPIO port used in EXTI
only one parameter can be selected which is shown as below:
\arg EXTI_SOURCE_GPIOx(x = A,B,C,D,E,F,G,H,J,K): EXTI GPIO port
\param[in] exti_pin: specify the EXTI line
only one parameter can be selected which is shown as below:
\arg EXTI_SOURCE_PINx(GPIOA x = 0..15,GPIOB x = 0..15,GPIOC x = 0..15,GPIOD x = 0..15,GPIOE x = 0..15,
GPIOF x = 0..15,GPIOG x = 0..15,GPIOH x = 0..15,GPIOI x = 0..15,GPIOJ x = 8,9,10,11, GPIOK x = 0,1,2,4,5,6): EXTI GPIO pin
\param[out] none
\retval none
*/
void syscfg_exti_line_config(uint8_t exti_port, uint8_t exti_pin)
{
uint32_t clear_exti_mask = ~((uint32_t)EXTI_SS_MASK << (EXTI_SS_MSTEP(exti_pin)));
uint32_t config_exti_mask = ((uint32_t)exti_port) << (EXTI_SS_MSTEP(exti_pin));
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_EXTI_SOURCE_GPIO(exti_port)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(5), ERR_PARAM_INVALID);
} else if(NOT_EXTI_SOURCE_PIN(exti_pin)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(5), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
switch(exti_pin / EXTI_SS_JSTEP) {
case EXTISS0:
/* clear EXTI source line(0..3) */
SYSCFG_EXTISS0 &= clear_exti_mask;
/* configure EXTI soure line(0..3) */
SYSCFG_EXTISS0 |= config_exti_mask;
break;
case EXTISS1:
/* clear EXTI soure line(4..7) */
SYSCFG_EXTISS1 &= clear_exti_mask;
/* configure EXTI soure line(4..7) */
SYSCFG_EXTISS1 |= config_exti_mask;
break;
case EXTISS2:
/* clear EXTI soure line(8..11) */
SYSCFG_EXTISS2 &= clear_exti_mask;
/* configure EXTI soure line(8..11) */
SYSCFG_EXTISS2 |= config_exti_mask;
break;
case EXTISS3:
/* clear EXTI soure line(12..15) */
SYSCFG_EXTISS3 &= clear_exti_mask;
/* configure EXTI soure line(12..15) */
SYSCFG_EXTISS3 |= config_exti_mask;
break;
default:
break;
}
}
}
/*!
\brief enable module lockup function (function can be disabled by system reset)
\param[in] lockup:
one or more parameters can be selected which are shown as below:
\arg SYSCFG_LVD_LOCKUP: LVD signal
\arg SYSCFG_CPU_LOCKUP: CPU lockup signal
\arg SYSCFG_BKPRAM_LOCKUP: Region 2 backup SRAM ECC double error signal
\arg SYSCFG_SRAM1_LOCKUP: Region 1 SRAM1 ECC double error signal
\arg SYSCFG_SRAM0_LOCKUP: Region 1 SRAM0 ECC double error signal
\arg SYSCFG_DTCM_LOCKUP: Region 0 DTCM ECC double error signal
\arg SYSCFG_ITCM_LOCKUP: Region 0 ITCM-RAM ECC double error signal
\arg SYSCFG_AXIRAM_LOCKUP: Region 0 AXI-SRAM ECC double error signal
\param[out] none
\retval none
*/
void syscfg_lockup_enable(uint32_t lockup)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_LOCKUP(lockup)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(6), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
SYSCFG_LKCTL |= lockup;
}
}
/*!
\brief select timer channel input source
\param[in] timer_input: TIMER channel input select, refer to timer_channel_input_enum
\arg TIMER7_CI0_INPUT_TIMER7_CH0: select CMP1 output as TIMER7 CI0
\arg TIMER7_CI0_INPUT_CMP1_OUT: select TIMER7 CH0 as TIMER7 CI0
\arg TIMER7_CI1_INPUT_TIMER7_CH1: select TIMER7 CH1 as TIMER7 CI1
\arg TIMER7_CI2_INPUT_TIMER7_CH2: select TIMER7 CH2 as TIMER7 CI2
\arg TIMER7_CI3_INPUT_TIMER7_CH3: select TIMER7 CH3 as TIMER7 CI3
\arg TIMER0_CI0_INPUT_TIMER0_CH0: select CMP0 output as TIMER0 CI0
\arg TIMER0_CI0_INPUT_CMP0_OUT: select TIMER0 CH0 as TIMER0 CI0
\arg TIMER0_CI1_INPUT_TIMER0_CH1: select TIMER0 CH1 as TIMER0 CI1
\arg TIMER0_CI2_INPUT_TIMER0_CH2: select TIMER0 CH2 as TIMER0 CI2
\arg TIMER0_CI3_INPUT_TIMER0_CH3: select TIMER0 CH3 as TIMER0 CI3
\arg TIMER2_CI0_INPUT_TIMER2_CH0: select TIMER2 CH0 as TIMER2 CI0
\arg TIMER2_CI0_INPUT_CMP0_OUT: select CMP0 as TIMER2 CI0
\arg TIMER2_CI0_INPUT_CMP1_OUT: select CMP1 as TIMER2 CI0
\arg TIMER2_CI0_INPUT_CMP0_OR_CMP1_OUT: select CMP0 or CMP1 as TIMER2 CI0
\arg TIMER2_CI1_INPUT_TIMER2_CH1: select TIMER2 CH1 as TIMER2 CI1
\arg TIMER2_CI2_INPUT_TIMER2_CH2: select TIMER2 CH2 as TIMER2 CI2
\arg TIMER2_CI3_INPUT_TIMER2_CH3: select TIMER2 CH3 as TIMER2 CI3
\arg TIMER1_CI0_INPUT_TIMER1_CH0: select TIMER1 CH0 as TIMER1 CI0
\arg TIMER1_CI1_INPUT_TIMER1_CH1: select TIMER1 CH1 as TIMER1 CI1
\arg TIMER1_CI2_INPUT_TIMER1_CH2: select TIMER1 CH2 as TIMER1 CI2
\arg TIMER1_CI3_INPUT_TIMER1_CH3: select TIMER1 CH3 as TIMER1 CI3
\arg TIMER1_CI3_INPUT_CMP0_OUT: select CMP0 output as TIMER1 CI3
\arg TIMER1_CI3_INPUT_CMP1_OUT: select CMP1 output as TIMER1 CI3
\arg TIMER1_CI3_INPUT_CMP0_OR_CMP1_OUT: select CMP0 or CMP1 output as TIMER1 CI3
\arg TIMER4_CI0_INPUT_TIMER4_CH0: select TIMER4 CH0 as TIMER4 CI0
\arg TIMER4_CI1_INPUT_TIMER4_CH1: select TIMER4 CH1 as TIMER4 CI1
\arg TIMER4_CI2_INPUT_TIMER4_CH2: select TIMER4 CH2 as TIMER4 CI2
\arg TIMER4_CI3_INPUT_TIMER4_CH3: select TIMER4 CH3 as TIMER4 CI3
\arg TIMER3_CI0_INPUT_TIMER3_CH0: select TIMER3 CH0 as TIMER3 CI0
\arg TIMER3_CI1_INPUT_TIMER3_CH1: select TIMER3 CH1 as TIMER3 CI1
\arg TIMER3_CI2_INPUT_TIMER3_CH2: select TIMER3 CH2 as TIMER3 CI2
\arg TIMER3_CI3_INPUT_TIMER3_CH3: select TIMER3 CH3 as TIMER3 CI3
\arg TIMER23_CI0_INPUT_TIMER23_CH0: select TIMER23 CH0 as TIMER23 CI0
\arg TIMER23_CI1_INPUT_TIMER23_CH1: select TIMER23 CH1 as TIMER23 CI1
\arg TIMER23_CI2_INPUT_TIMER23_CH2: select TIMER23 CH2 as TIMER23 CI2
\arg TIMER23_CI3_INPUT_TIMER23_CH3: select TIMER23 CH3 as TIMER23 CI3
\arg TIMER22_CI0_INPUT_TIMER22_CH0: select TIMER22 CH0 as TIMER22 CI0
\arg TIMER22_CI1_INPUT_TIMER22_CH1: select TIMER22 CH1 as TIMER22 CI1
\arg TIMER22_CI2_INPUT_TIMER22_CH2: select TIMER22 CH2 as TIMER22 CI2
\arg TIMER22_CI3_INPUT_TIMER22_CH3: select TIMER22 CH3 as TIMER22 CI3
\arg TIMER22_CI3_INPUT_CMP0_OUT: select CMP0 output as TIMER22 CI3
\arg TIMER22_CI3_INPUT_CMP1_OUT: select CMP1 output as TIMER22 CI3
\arg TIMER22_CI3_INPUT_CMP0_OR_CMP1_OUT: select CMP0 or CMP1 output as TIMER22 CI3
\arg TIMER14_CI0_INPUT_TIMER14_CH0: select TIMER14 CH0 as TIMER14 CI0
\arg TIMER14_CI0_INPUT_TIMER1_CH0: select TIMER1 CH0 as TIMER14 CI0
\arg TIMER14_CI0_INPUT_TIMER2_CH0: select TIMER2 CH0 as TIMER14 CI0
\arg TIMER14_CI0_INPUT_TIMER3_CH0: select TIMER3 CH0 as TIMER14 CI0
\arg TIMER14_CI0_INPUT_LXTAL: select LXTAL as TIMER14 CI0
\arg TIMER14_CI0_INPUT_LPIRC4M: select LPIRC4M as TIMER14 CI0
\arg TIMER14_CI0_INPUT_CKOUT1: select CKOUT1 as TIMER14 CI0
\arg TIMER14_CI1_INPUT_TIMER14_CH1: select TIMER14 CH1 as TIMER14 CI1
\arg TIMER14_CI1_INPUT_TIMER1_CH1: select TIMER1 CH1 as TIMER14 CI1
\arg TIMER14_CI1_INPUT_TIMER2_CH1: select TIMER2 CH1 as TIMER14 CI1
\arg TIMER14_CI1_INPUT_TIMER3_CH1: select TIMER3 CH1 as TIMER14 CI1
\arg TIMER40_CI0_INPUT_TIMER40_CH0: select TIMER40 CH0 as TIMER40 CI0
\arg TIMER40_CI0_INPUT_TIMER2_CH0: select TIMER2 CH0 as TIMER40 CI0
\arg TIMER40_CI0_INPUT_TIMER3_CH0: select TIMER3 CH0 as TIMER40 CI0
\arg TIMER40_CI0_INPUT_TIMER4_CH0: select TIMER4 CH0 as TIMER40 CI0
\arg TIMER40_CI0_INPUT_LXTAL: select LXTAL as TIMER40 CI0
\arg TIMER40_CI0_INPUT_LPIRC4M: select LPIRC4M as TIMER40 CI0
\arg TIMER40_CI0_INPUT_CKOUT1: select CKOUT1 as TIMER40 CI0
\arg TIMER40_CI1_INPUT_TIMER40_CH1: select TIMER40 CH1 as TIMER40 CI0
\arg TIMER40_CI1_INPUT_TIMER2_CH1: select TIMER2 CH1 as TIMER40 CI0
\arg TIMER40_CI1_INPUT_TIMER3_CH1: select TIMER3 CH1 as TIMER40 CI0
\arg TIMER40_CI1_INPUT_TIMER4_CH1: select TIMER4 CH1 as TIMER40 CI0
\arg TIMER41_CI0_INPUT_TIMER41_CH0: select TIMER41 CH0 as TIMER41 CI0
\arg TIMER41_CI0_INPUT_TIMER3_CH0: select TIMER3 CH0 as TIMER41 CI0
\arg TIMER41_CI0_INPUT_TIMER4_CH0: select TIMER4 CH0 as TIMER41 CI0
\arg TIMER41_CI0_INPUT_TIMER22_CH0: select TIMER22 CH0 as TIMER41 CI0
\arg TIMER41_CI0_INPUT_LXTAL: select LXTAL as TIMER41 CI0
\arg TIMER41_CI0_INPUT_LPIRC4M: select LPIRC4M as TIMER41 CI0
\arg TIMER41_CI0_INPUT_CKOUT1: select CKOUT1 as TIMER41 CI0
\arg TIMER41_CI1_INPUT_TIMER41_CH1: select TIMER41 CH1 as TIMER41 CI1
\arg TIMER41_CI1_INPUT_TIMER3_CH1: select TIMER3 CH1 as TIMER41 CI1
\arg TIMER41_CI1_INPUT_TIMER4_CH1: select TIMER4 CH1 as TIMER41 CI1
\arg TIMER41_CI1_INPUT_TIMER22_CH1: select TIMER22 CH1 as TIMER41 CI1
\arg TIMER42_CI0_INPUT_TIMER42_CH0: select TIMER42 CH0 as TIMER42 CI0
\arg TIMER42_CI0_INPUT_TIMER4_CH0: select TIMER4 CH0 as TIMER42 CI0
\arg TIMER42_CI0_INPUT_TIMER22_CH0: select TIMER22 CH0 as TIMER42 CI0
\arg TIMER42_CI0_INPUT_TIMER23_CH0: select TIMER23 CH0 as TIMER42 CI0
\arg TIMER42_CI0_INPUT_LXTAL: select LXTAL as TIMER42 CI0
\arg TIMER42_CI0_INPUT_LPIRC4M: select LPIRC4M as TIMER42 CI0
\arg TIMER42_CI0_INPUT_CKOUT1: select CKOUT1 as TIMER42 CI0
\arg TIMER42_CI1_INPUT_TIMER42_CH1: select TIMER42 CH1 as TIMER42 CI1
\arg TIMER42_CI1_INPUT_TIMER4_CH1: select TIMER4 CH1 as TIMER42 CI1
\arg TIMER42_CI1_INPUT_TIMER22_CH1: select TIMER22 CH1 as TIMER42 CI1
\arg TIMER42_CI1_INPUT_TIMER23_CH1: select TIMER23 CH1 as TIMER42 CI1
\arg TIMER15_CI0_INPUT_TIMER15_CH0: select TIMER15 CH0 as TIMER15 CI0
\arg TIMER15_CI0_INPUT_IRC32K: select IRC32K as TIMER15 CI0
\arg TIMER15_CI0_INPUT_LXTAL: select LXTAL as TIMER15 CI0
\arg TIMER15_CI0_INPUT_WKUP_IT: select WKUP IT as TIMER15 CI0
\arg TIMER16_CI0_INPUT_TIMER16_CH0: select TIMER16 CH0 as TIMER16 CI0
\arg TIMER16_CI0_INPUT_RSPDIF: select RSPDIF symbol ck as TIMER16 CI0
\arg TIMER16_CI0_INPUT_HXTAL_RTCDIV: select HXTAL/RTCDIV 1M as TIMER16 CI0
\arg TIMER16_CI0_INPUT_CKOUT0: select CKOUT0 as TIMER16 CI0
\arg TIMER43_CI0_INPUT_TIMER43_CH0: select TIMER43 CH0 as TIMER43 CI0
\arg TIMER43_CI0_INPUT_TIMER22_CH0: select TIMER22 CH0 as TIMER43 CI0
\arg TIMER43_CI0_INPUT_TIMER23_CH0: select TIMER23 CH0 as TIMER43 CI0
\arg TIMER43_CI0_INPUT_LXTAL: select LXTAL as TIMER43 CI0
\arg TIMER43_CI0_INPUT_LPIRC4M: select LPIRC4M as TIMER43 CI0
\arg TIMER43_CI0_INPUT_CKOUT1: select CKOUT1 as TIMER43 CI0
\arg TIMER43_CI1_INPUT_TIMER43_CH1: select TIMER43 CH1 as TIMER43 CI1
\arg TIMER43_CI1_INPUT_TIMER22_CH1: select TIMER22 CH1 as TIMER43 CI1
\arg TIMER43_CI1_INPUT_TIMER23_CH1: select TIMER23 CH1 as TIMER43 CI1
\arg TIMER44_CI0_INPUT_TIMER44_CH0: select TIMER44 CH0 as TIMER44 CI0
\arg TIMER44_CI0_INPUT_TIMER23_CH0: select TIMER23 CH0 as TIMER44 CI0
\arg TIMER44_CI0_INPUT_LXTAL: select LXTAL as TIMER44 CI0
\arg TIMER44_CI0_INPUT_LPIRC4M: select LPIRC4M as TIMER44 CI0
\arg TIMER44_CI0_INPUT_CKOUT1: select CKOUT1 as TIMER44 CI0
\arg TIMER44_CI1_INPUT_TIMER44_CH1: select TIMER44 CH1 as TIMER44 CI1
\arg TIMER44_CI1_INPUT_TIMER23_CH1: select TIMER23 CH1 as TIMER44 CI1
\param[out] none
\retval none
*/
void syscfg_timer_input_source_select(timer_channel_input_enum timer_input)
{
uint32_t clear_timer_mask = ~((uint32_t)TIMER_IS_MASK << (TIMER_BIT_POS(timer_input)));
uint32_t config_timer_mask = (TIMER_SEL_VAL(timer_input) << TIMER_BIT_POS(timer_input));
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_TIMERCI_INPUT(timer_input)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(7), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
switch(TIMER_REG_INDEX(timer_input)) {
case TIMERCISEL0:
/* clear TIMER channel input select */
SYSCFG_TIMERCISEL0 &= clear_timer_mask;
/* config TIMER channel input */
SYSCFG_TIMERCISEL0 |= config_timer_mask;
break;
case TIMERCISEL1:
/* clear TIMER channel input select */
SYSCFG_TIMERCISEL1 &= clear_timer_mask;
/* config TIMER channel input */
SYSCFG_TIMERCISEL1 |= config_timer_mask;
break;
case TIMERCISEL2:
/* clear TIMER channel input select */
SYSCFG_TIMERCISEL2 &= clear_timer_mask;
/* config TIMER channel input */
SYSCFG_TIMERCISEL2 |= config_timer_mask;
break;
case TIMERCISEL3:
/* clear TIMER channel input select */
SYSCFG_TIMERCISEL3 &= clear_timer_mask;
/* config TIMER channel input */
SYSCFG_TIMERCISEL3 |= config_timer_mask;
break;
case TIMERCISEL5:
/* clear TIMER channel input select */
SYSCFG_TIMERCISEL5 &= clear_timer_mask;
/* config TIMER channel input */
SYSCFG_TIMERCISEL5 |= config_timer_mask;
break;
case TIMERCISEL6:
/* clear TIMER channel input select */
SYSCFG_TIMERCISEL6 &= clear_timer_mask;
/* config TIMER channel input */
SYSCFG_TIMERCISEL6 |= config_timer_mask;
break;
default:
break;
}
}
}
/*!
\brief configure the I/O compensation cell
\param[in] syscfg_cps: specifies the I/O compensation cell mode
only one parameter can be selected which is shown as below:
\arg SYSCFG_IO_COMPENSATION_ENABLE: I/O compensation cell is enabled
\arg SYSCFG_IO_COMPENSATION_DISABLE: I/O compensation cell is disabled
\param[out] none
\retval none
*/
void syscfg_io_compensation_config(uint32_t syscfg_cps)
{
uint32_t reg;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_IO_COMPENSATION(syscfg_cps)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(8), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
reg = SYSCFG_CPSCTL;
/* reset the SYSCFG_CPSCTL_CPS_EN bit and set according to syscfg_compensation */
reg &= ~SYSCFG_CPSCTL_CPS_EN;
SYSCFG_CPSCTL = (reg | syscfg_cps);
}
}
/*!
\brief enable I/O speed optimization, high-speed at low-voltage
\param[in] none
\param[out] none
\retval none
*/
void syscfg_io_low_voltage_speed_optimization_enable(void)
{
SYSCFG_CPSCTL |= SYSCFG_CPSCTL_IOSPDOP;
}
/*!
\brief disable I/O speed optimization, high-speed at low-voltage
\param[in] none
\param[out] none
\retval none
*/
void syscfg_io_low_voltage_speed_optimization_disable(void)
{
SYSCFG_CPSCTL &= ~SYSCFG_CPSCTL_IOSPDOP;
}
/*!
\brief set P/N MOS compensation value
\param[in] mos
only one parameter can be selected which is shown as below:
\arg NMOS_COMPENSATION: NMOS
\arg PMOS_COMPENSATION: PMOS
\param[in] code: P/N MOS compensation value
\param[out] none
\retval none
*/
void syscfg_pnmos_compensation_code_set(uint32_t mos, uint32_t code)
{
uint32_t value;
value = SYSCFG_CPSCCCFG;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_MOS_COMPENSATION(mos)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(9), ERR_PARAM_INVALID);
} else if(code > 0xFU) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(9), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(NMOS_COMPENSATION == mos) {
value &= ~SYSCFG_CPSCCCFG_NCPSCC;
value |= (code & 0x0FU);
} else {
value &= ~SYSCFG_CPSCCCFG_PCPSCC;
value |= ((code & 0x0FU) << 4U);
}
SYSCFG_CPSCCCFG = value;
}
}
/*!
\brief set secure SRAM size
\param[in] SRAM size
only one parameter can be selected which is shown as below:
\arg SECURE_SRAM_SIZE_0KB: secure SRAM size is 0KB
\arg SECURE_SRAM_SIZE_32KB: secure SRAM size is 32KB
\arg SECURE_SRAM_SIZE_64KB: secure SRAM size is 64KB
\arg SECURE_SRAM_SIZE_128KB: secure SRAM size is 128KB
\param[out] none
\retval none
*/
void syscfg_secure_sram_size_set(uint32_t size)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_SECURE_SRAM_SIZE(size)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(10), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
SYSCFG_SRAMCFG0 &= (uint32_t)(~SYSCFG_SRAMCFG0_SECURE_SRAM_SIZE);
SYSCFG_SRAMCFG0 |= size;
}
}
/*!
\brief get secure SRAM size
\param[in] none
\param[out] none
\retval SRAM size
\arg SECURE_SRAM_SIZE_0KB: secure SRAM size is 0KB
\arg SECURE_SRAM_SIZE_32KB: secure SRAM size is 32KB
\arg SECURE_SRAM_SIZE_64KB: secure SRAM size is 64KB
\arg SECURE_SRAM_SIZE_128KB: secure SRAM size is 128KB
*/
uint32_t syscfg_secure_sram_size_get(void)
{
return (SYSCFG_SRAMCFG0 & SYSCFG_SRAMCFG0_SECURE_SRAM_SIZE);
}
/*!
\brief get BOOT mode
\param[in] none
\param[out] none
\retval boot mode
\arg BOOT_SRAM: BOOT from SRAM (ITCM/DTCM/RAM shared/AXI SRAM)
\arg BOOT_SECURITY: BOOT from Security
\arg BOOT_SYSTEM: BOOT_SYS (BootLoader)
\arg BOOT_USER_FLASH: BOOT_USER (User flash OSPI0/1)
*/
uint32_t syscfg_bootmode_get(void)
{
return ((SYSCFG_USERCFG & SYSCFG_USERCFG_BOOT_MODE) >> 4U);
}
/*!
\brief enable TCM wait state
\param[in] none
\param[out] none
\retval none
*/
void syscfg_tcm_wait_state_enable(void)
{
SYSCFG_SRAMCFG1 |= SYSCFG_SRAMCFG1_TCM_WAITSTATE;
}
/*!
\brief disable TCM wait state
\param[in] none
\param[out] none
\retval none
*/
void syscfg_tcm_wait_state_disable(void)
{
SYSCFG_SRAMCFG1 &= ~SYSCFG_SRAMCFG1_TCM_WAITSTATE;
}
/*!
\brief enable FPU interrupt
\param[in] fpu_int: FPU interrupt
one or more parameters can be selected which are shown as below:
\arg SYSCFG_FPUINT_INEXACT: inexact interrupt
\arg SYSCFG_FPUINT_INPUT_ABNORMAL: input abnormal interrupt
\arg SYSCFG_FPUINT_OVERFLOW: overflow interrupt
\arg SYSCFG_FPUINT_UNDERFLOW: underflow interrupt
\arg SYSCFG_FPUINT_DIV0: divide-by-zero interrupt
\arg SYSCFG_FPUINT_INVALID_OPERATION: invalid operation interrupt
\param[out] none
\retval none
*/
void syscfg_fpu_interrupt_enable(uint32_t fpu_int)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_FPUINT(fpu_int)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(11), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
SYSCFG_FPUINTEN |= fpu_int;
}
}
/*!
\brief disable FPU interrupt
\param[in] fpu_int: FPU interrupt
one or more parameters can be selected which are shown as below:
\arg SYSCFG_FPUINT_INEXACT: inexact interrupt
\arg SYSCFG_FPUINT_INPUT_ABNORMAL: input abnormal interrupt
\arg SYSCFG_FPUINT_OVERFLOW: overflow interrupt
\arg SYSCFG_FPUINT_UNDERFLOW: underflow interrupt
\arg SYSCFG_FPUINT_DIV0: divide-by-zero interrupt
\arg SYSCFG_FPUINT_INVALID_OPERATION: invalid operation interrupt
\param[out] none
\retval none
*/
void syscfg_fpu_interrupt_disable(uint32_t fpu_int)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_FPUINT(fpu_int)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(12), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
SYSCFG_FPUINTEN &= (uint32_t)(~fpu_int);
}
}
/*!
\brief get compensation cell flags
\param[in] cps_flag: compensation flag
\arg SYSCFG_FLAG_IO_LOW_VOLTAGE: I/O in low voltage state flag, product supply voltage is working below 2.5V
\arg SYSCFG_FLAG_COMPENSATION_READY: I/O compensation cell ready flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus syscfg_compensation_flag_get(uint32_t cps_flag)
{
FlagStatus temp_flag = RESET;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_FLAG(cps_flag)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(13), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(SYSCFG_CPSCTL & cps_flag) {
temp_flag = SET;
} else {
temp_flag = RESET;
}
}
return temp_flag;
}
/*!
\brief get the ICACHE or DCACHE detection and error information
\param[in] cache:
only one parameter can be selected which is shown as below:
\arg ICACHE_STATUS: select ICACHE
\arg DCACHE_STATUS: select DCACHE
\param[in] status:
only one parameter can be selected which is shown as below:
\arg CPU_CACHE_ERROR_DETECTION: select detection information
\arg CPU_CACHE_ERROR_BANK: select error information
\param[out] none
\retval value
*/
uint32_t syscfg_cpu_cache_status_get(uint32_t cache, uint32_t status)
{
uint32_t value = 0U;
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_SYSCFG_CACHE_STATUS(cache)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(14), ERR_PARAM_INVALID);
} else if(NOT_CPU_CACHE_ERROR(status)) {
fw_debug_report_err(SYSCFG_MODULE_ID, API_ID(14), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
switch(cache) {
/* get ICACHE information */
case ICACHE_STATUS:
if(CPU_CACHE_ERROR_DETECTION == status) {
/* return detection information */
value = (uint32_t)((SYSCFG_CPUICAC & SYSCFG_CPUICAC_CPU_ICDET) >> 28U);
} else {
/* return error bank information */
value = (uint32_t)((SYSCFG_CPUICAC & SYSCFG_CPUICAC_CPU_ICERR) >> 6U);
}
break;
/* get DCACHE information */
case DCACHE_STATUS:
if(CPU_CACHE_ERROR_DETECTION == status) {
/* return detection information */
value = (uint32_t)((SYSCFG_CPUDCAC & SYSCFG_CPUICAC_CPU_ICDET) >> 28U);
} else {
/* return error bank information */
value = (uint32_t)((SYSCFG_CPUDCAC & SYSCFG_CPUICAC_CPU_ICERR) >> 6U);
}
break;
default:
break;
}
}
return value;
}
/*!
\brief get brownout reset threshold level
\param[in] none
\param[out] none
\retval BOR level
\arg BOR_OFF: no BOR function
\arg BOR_THRESHOLD_VAL1: BOR threshold value 1
\arg BOR_THRESHOLD_VAL2: BOR threshold value 2
\arg BOR_THRESHOLD_VAL3: BOR threshold value 3
*/
uint32_t syscfg_brownout_reset_threshold_level_get(void)
{
return (SYSCFG_USERCFG & SYSCFG_USERCFG_BOR_TH);
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,298 @@
/*!
\file gd32h75e_tmu.c
\brief TMU driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_tmu.h"
#define MASK_LOW_HALFWORD ((uint32_t)0xFFFF0000U)
#define MASK_HIGH_HALFWORD ((uint32_t)0x0000FFFFU)
/*!
\brief reset the TMU registers (API_ID(0x0001U))
\param[in] none
\param[out] none
\retval none
*/
void tmu_deinit(void)
{
rcu_periph_reset_enable(RCU_TMURST);
rcu_periph_reset_disable(RCU_TMURST);
}
/*!
\brief initialize the parameters of TMU struct with the default values (API_ID(0x0002U))
\param[in] init_struct: pointer to init parameter struct
\param[out] none
\retval none
*/
void tmu_struct_para_init(tmu_parameter_struct* init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(init_struct)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x0002U), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* set the struct with the default values */
init_struct->mode = TMU_MODE_COS;
init_struct->iterations_number = TMU_ITERATION_STEPS_20;
init_struct->scale = TMU_SCALING_FACTOR_1;
init_struct->dma_read = TMU_READ_DMA_DISABLE;
init_struct->dma_write = TMU_WRITE_DMA_DISABLE;
init_struct->read_times = TMU_READ_TIMES_1;
init_struct->write_times = TMU_WRITE_TIMES_1;
init_struct->output_width = TMU_OUTPUT_WIDTH_32;
init_struct->input_width = TMU_INPUT_WIDTH_32;
}
}
/*!
\brief initialize TMU (API_ID(0x0003U))
\param[in] init_struct: pointer to init parameter struct
mode: TMU_MODE_COS,TMU_MODE_SIN,TMU_MODE_ATAN2,TMU_MODE_MODULUS,TMU_MODE_ATAN,
TMU_MODE_COSH,TMU_MODE_SINH,TMU_MODE_ATANH,TMU_MODE_LN,TMU_MODE_SQRT
iterations_number: TMU_ITERATION_STEPS_x(x=4,8,12,..24)
scale: TMU_SCALING_FACTOR_x(x=1,2,4,8,16,32,64,128)
dma_read: TMU_READ_DMA_DISABLE, TMU_READ_DMA_ENABLE
dma_write: TMU_WRITE_DMA_DISABLE, TMU_WRITE_DMA_ENABLE
read_times: TMU_READ_TIMES_1, TMU_READ_TIMES_2
write_times: TMU_WRITE_TIMES_1, TMU_WRITE_TIMES_2
output_width: TMU_OUTPUT_WIDTH_32, TMU_OUTPUT_WIDTH_16
input_width: TMU_INPUT_WIDTH_32, TMU_INPUT_WIDTH_16
\param[out] none
\retval none
*/
void tmu_init(tmu_parameter_struct* init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(init_struct)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x0003U), ERR_PARAM_POINTER);
} else if(NOT_TMU_MODE(init_struct->mode)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x0003U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_TMU_ITERATIONS_NUM(init_struct->iterations_number)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x0003U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_TMU_SCALE_FACTOR(init_struct->scale)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x0003U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_TMU_DMA_READ(init_struct->dma_read)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x0003U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_TMU_DMA_WRITE(init_struct->dma_write)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x0003U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_TMU_READ_TIMES(init_struct->read_times)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x0003U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_TMU_WRITE_TIMES(init_struct->write_times)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x0003U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_TMU_OUTPUT_WIDTH(init_struct->output_width)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x0003U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_TMU_INPUT_WIDTH(init_struct->input_width)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x0003U), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t reg = 0U;
reg |= ( init_struct->mode | init_struct->iterations_number | init_struct->scale |\
init_struct->dma_read | init_struct->dma_write | init_struct->read_times |\
init_struct->write_times | init_struct->output_width | init_struct->input_width);
TMU_CS = reg;
}
}
/*!
\brief enable TMU read interrupt (API_ID(0x0004U))
\param[in] none
\param[out] none
\retval none
*/
void tmu_read_interrupt_enable(void)
{
TMU_CS |= TMU_CS_RIE;
}
/*!
\brief disable TMU read interrupt (API_ID(0x0005U))
\param[in] none
\param[out] none
\retval none
*/
void tmu_read_interrupt_disable(void)
{
TMU_CS &= ~TMU_CS_RIE;
}
/*!
\brief enable TMU DMA read request (API_ID(0x0006U))
\param[in] none
\param[out] none
\retval none
*/
void tmu_dma_read_enable(void)
{
TMU_CS |= TMU_CS_RDEN;
}
/*!
\brief disable TMU DMA read request (API_ID(0x0007U))
\param[in] none
\param[out] none
\retval none
*/
void tmu_dma_read_disable(void)
{
TMU_CS &= ~TMU_CS_RDEN;
}
/*!
\brief enable TMU DMA write request (API_ID(0x0008U))
\param[in] none
\param[out] none
\retval none
*/
void tmu_dma_write_enable(void)
{
TMU_CS |= TMU_CS_WDEN;
}
/*!
\brief disable TMU DMA write request (API_ID(0x0009U))
\param[in] none
\param[out] none
\retval none
*/
void tmu_dma_write_disable(void)
{
TMU_CS &= ~TMU_CS_WDEN;
}
/*!
\brief write one data in q1.31 format (API_ID(0x000AU))
\param[in] data: the first input data only
\param[out] none
\retval none
*/
void tmu_one_q31_write(uint32_t data)
{
TMU_IDATA = data;
}
/*!
\brief write two data in q1.31 format (API_ID(0x000BU))
\param[in] data1: the first input data
\param[in] data2: the second input data
\param[out] none
\retval none
*/
void tmu_two_q31_write(uint32_t data1, uint32_t data2)
{
TMU_IDATA = data1;
TMU_IDATA = data2;
}
/*!
\brief write two data in q1.15 format (API_ID(0x000CU))
\param[in] data1: the first input data
\param[in] data2: the second input data (this data is meaningless in mode4 ~ mode9)
\param[out] none
\retval none
*/
void tmu_two_q15_write(uint16_t data1, uint16_t data2)
{
TMU_IDATA = ((((uint32_t)data1) & MASK_HIGH_HALFWORD)| (((uint32_t)data2 << 16U) & MASK_LOW_HALFWORD));
}
/*!
\brief read one data in q1.31 format (API_ID(0x000DU))
\param[in] none
\param[out] p: pointer to the first output data only
\retval none
*/
void tmu_one_q31_read(uint32_t* p)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(p)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x000DU), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
*p = TMU_ODATA;
}
}
/*!
\brief read two data in q1.31 format (API_ID(0x000EU))
\param[in] none
\param[out] p1: pointer to the first output data
\param[out] p2: pointer to the second output data
\retval none
*/
void tmu_two_q31_read(uint32_t* p1, uint32_t* p2)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(p1)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x000EU), ERR_PARAM_POINTER);
} else if(NOT_VALID_POINTER(p2)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x000EU), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
*p1 = TMU_ODATA;
*p2 = TMU_ODATA;
}
}
/*!
\brief read two data in q1.15 format (API_ID(0x000FU))
\param[in] none
\param[out] p1: pointer to the first output data
\param[out] p2: pointer to the second output data (this data is meaningless in mode4, mode7 ~ mode9)
\retval none
*/
void tmu_two_q15_read(uint16_t* p1, uint16_t* p2)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(p1)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x000EU), ERR_PARAM_POINTER);
} else if(NOT_VALID_POINTER(p2)) {
fw_debug_report_err(TMU_MODULE_ID, API_ID(0x000EU), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t data;
data = TMU_ODATA;
*p1 = (uint16_t)data;
*p2 = (uint16_t)(data >> 16U);
}
}
@@ -0,0 +1,485 @@
/*!
\file gd32h75e_trigsel.c
\brief TRIGSEL driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_trigsel.h"
/* TRIGSEL target register redefine */
#define TRIGSEL_TARGET_REG(target_periph) (REG32(TRIGSEL + ((uint32_t)(target_periph) & BITS(2,31)))) /*!< target peripheral register */
#define TRIGSEL_TARGET_PERIPH_SHIFT(target_periph) (((uint32_t)(target_periph) & BITS(0,1)) << 3U) /*!< bit offset in target peripheral register */
#define TRIGSEL_TARGET_PERIPH_MASK(target_periph) ((uint32_t)(BITS(0,7) << TRIGSEL_TARGET_PERIPH_SHIFT(target_periph))) /*!< bit mask in target peripheral register */
/*!
\brief deinitialize TRIGSEL
\param[in] none
\param[out] none
\retval none
*/
void trigsel_deinit(void)
{
rcu_periph_reset_enable(RCU_TRIGSELRST);
rcu_periph_reset_disable(RCU_TRIGSELRST);
}
/*!
\brief set the trigger input signal for target peripheral
\param[in] target_periph: target peripheral value
only one parameter can be selected which is shown as below:
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT0: output target peripheral TRIGSEL_OUT0 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT1: output target peripheral TRIGSEL_OUT1 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT2: output target peripheral TRIGSEL_OUT2 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT3: output target peripheral TRIGSEL_OUT3 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT4: output target peripheral TRIGSEL_OUT4 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT5: output target peripheral TRIGSEL_OUT5 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT6: output target peripheral TRIGSEL_OUT6 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT7: output target peripheral TRIGSEL_OUT7 pin
\arg TRIGSEL_OUTPUT_ADC0_REGTRG: output target peripheral ADC0_REGTRG
\arg TRIGSEL_OUTPUT_ADC0_INSTRG: output target peripheral ADC0_INSTRG
\arg TRIGSEL_OUTPUT_ADC1_REGTRG: output target peripheral ADC1_REGTRG
\arg TRIGSEL_OUTPUT_ADC1_INSTRG: output target peripheral ADC1_INSTRG
\arg TRIGSEL_OUTPUT_ADC2_REGTRG: output target peripheral ADC2_REGTRG
\arg TRIGSEL_OUTPUT_ADC2_INSTRG: output target peripheral ADC2_INSTRG
\arg TRIGSEL_OUTPUT_DAC0_OUT0_EXTRG: output target peripheral DAC0_OUT0_EXTRG
\arg TRIGSEL_OUTPUT_DAC0_OUT1_EXTRG: output target peripheral DAC0_OUT1_EXTRG
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN0: output target peripheral TIMER0_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN1: output target peripheral TIMER0_BRKIN1
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN2: output target peripheral TIMER0_BRKIN2
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN0: output target peripheral TIMER7_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN1: output target peripheral TIMER7_BRKIN1
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN2: output target peripheral TIMER7_BRKIN2
\arg TRIGSEL_OUTPUT_TIMER14_BRKIN0: output target peripheral TIMER14_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER15_BRKIN0: output target peripheral TIMER15_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER16_BRKIN0: output target peripheral TIMER16_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER40_BRKIN0: output target peripheral TIMER40_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER41_BRKIN0: output target peripheral TIMER41_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER42_BRKIN0: output target peripheral TIMER42_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER43_BRKIN0: output target peripheral TIMER43_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER44_BRKIN0: output target peripheral TIMER44_BRKIN0
\arg TRIGSEL_OUTPUT_CAN0_EX_TIME_TICK: output target peripheral CAN0_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_CAN1_EX_TIME_TICK: output target peripheral CAN1_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_CAN2_EX_TIME_TICK: output target peripheral CAN2_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_LPDTS_TRG: output target peripheral LPDTS_TRG
\arg TRIGSEL_OUTPUT_TIMER0_ETI: output target peripheral TIMER0_ETI
\arg TRIGSEL_OUTPUT_TIMER1_ETI: output target peripheral TIMER1_ETI
\arg TRIGSEL_OUTPUT_TIMER2_ETI: output target peripheral TIMER2_ETI
\arg TRIGSEL_OUTPUT_TIMER3_ETI: output target peripheral TIMER3_ETI
\arg TRIGSEL_OUTPUT_TIMER4_ETI: output target peripheral TIMER4_ETI
\arg TRIGSEL_OUTPUT_TIMER7_ETI: output target peripheral TIMER7_ETI
\arg TRIGSEL_OUTPUT_TIMER22_ETI: output target peripheral TIMER22_ETI
\arg TRIGSEL_OUTPUT_TIMER23_ETI: output target peripheral TIMER23_ETI
\arg TRIGSEL_OUTPUT_EDOUT_TRG: output target peripheral EDOUT_TRG
\arg TRIGSEL_OUTPUT_HPDF_ITRG: output target peripheral HPDF_ITR
\arg TRIGSEL_OUTPUT_TIMER0_ITI14: output target peripheral TIMER0_ITI14
\arg TRIGSEL_OUTPUT_TIMER1_ITI14: output target peripheral TIMER1_ITI14
\arg TRIGSEL_OUTPUT_TIMER2_ITI14: output target peripheral TIMER2_ITI14
\arg TRIGSEL_OUTPUT_TIMER3_ITI14: output target peripheral TIMER3_ITI14
\arg TRIGSEL_OUTPUT_TIMER4_ITI14: output target peripheral TIMER4_ITI14
\arg TRIGSEL_OUTPUT_TIMER7_ITI14: output target peripheral TIMER7_ITI14
\arg TRIGSEL_OUTPUT_TIMER14_ITI14: output target peripheral TIMER14_ITI14
\arg TRIGSEL_OUTPUT_TIMER22_ITI14: output target peripheral TIMER22_ITI14
\arg TRIGSEL_OUTPUT_TIMER23_ITI14: output target peripheral TIMER23_ITI14
\arg TRIGSEL_OUTPUT_TIMER40_ITI14: output target peripheral TIMER40_ITI14
\arg TRIGSEL_OUTPUT_TIMER41_ITI14: output target peripheral TIMER41_ITI14
\arg TRIGSEL_OUTPUT_TIMER42_ITI14: output target peripheral TIMER42_ITI14
\arg TRIGSEL_OUTPUT_TIMER43_ITI14: output target peripheral TIMER43_ITI14
\arg TRIGSEL_OUTPUT_TIMER44_ITI14: output target peripheral TIMER44_ITI14
\param[in] trigger_source: trigger source value
only one parameter can be selected which is shown as below:
\arg TRIGSEL_INPUT_0: trigger input source 0
\arg TRIGSEL_INPUT_1: trigger input source 1
\arg TRIGSEL_INPUT_TRIGSEL_IN0: trigger input source TRIGSEL_IN0 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN1: trigger input source TRIGSEL_IN1 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN2: trigger input source TRIGSEL_IN2 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN3: trigger input source TRIGSEL_IN3 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN4: trigger input source TRIGSEL_IN4 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN5: trigger input source TRIGSEL_IN5 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN6: trigger input source TRIGSEL_IN6 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN7: trigger input source TRIGSEL_IN7 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN8: trigger input source TRIGSEL_IN8 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN9: trigger input source TRIGSEL_IN9 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN10: trigger input source TRIGSEL_IN10 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN11: trigger input source TRIGSEL_IN11 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN12: trigger input source TRIGSEL_IN12 pin
\arg TRIGSEL_INPUT_TRIGSEL_IN13: trigger input source TRIGSEL_IN13 pin
\arg TRIGSEL_INPUT_LXTAL_TRG: trigger input source LXTAL_TRG
\arg TRIGSEL_INPUT_TIMER0_TRGO0: trigger input source TIMER0 TRGO0
\arg TRIGSEL_INPUT_TIMER0_TRGO1: trigger input source TIMER0 TRGO1
\arg TRIGSEL_INPUT_TIMER0_CH0: trigger input source TIMER0 CH0
\arg TRIGSEL_INPUT_TIMER0_CH1: trigger input source TIMER0 CH1
\arg TRIGSEL_INPUT_TIMER0_CH2: trigger input source TIMER0 CH2
\arg TRIGSEL_INPUT_TIMER0_CH3: trigger input source TIMER0 CH3
\arg TRIGSEL_INPUT_TIMER0_MCH0: trigger input source TIMER0 MCH0
\arg TRIGSEL_INPUT_TIMER0_MCH1: trigger input source TIMER0 MCH1
\arg TRIGSEL_INPUT_TIMER0_MCH2: trigger input source TIMER0 MCH2
\arg TRIGSEL_INPUT_TIMER0_MCH3: trigger input source TIMER0 MCH3
\arg TRIGSEL_INPUT_TIMER0_BRKIN0: trigger input source TIMER0 BRKIN0
\arg TRIGSEL_INPUT_TIMER0_BRKIN1: trigger input source TIMER0 BRKIN1
\arg TRIGSEL_INPUT_TIMER0_BRKIN2: trigger input source TIMER0 BRKIN2
\arg TRIGSEL_INPUT_TIMER0_ETI: trigger input source TIMER0 ETI
\arg TRIGSEL_INPUT_TIMER1_TRGO0: trigger input source TIMER1 TRGO0
\arg TRIGSEL_INPUT_TIMER1_CH0: trigger input source TIMER1 CH0
\arg TRIGSEL_INPUT_TIMER1_CH1: trigger input source TIMER1 CH1
\arg TRIGSEL_INPUT_TIMER1_CH2: trigger input source TIMER1 CH2
\arg TRIGSEL_INPUT_TIMER1_CH3: trigger input source TIMER1 CH2
\arg TRIGSEL_INPUT_TIMER1_ETI: trigger input source TIMER1 ETI
\arg TRIGSEL_INPUT_TIMER2_TRGO0: trigger input source TIMER2 TRGO0
\arg TRIGSEL_INPUT_TIMER2_CH0: trigger input source TIMER2 CH0
\arg TRIGSEL_INPUT_TIMER2_CH1: trigger input source TIMER2 CH1
\arg TRIGSEL_INPUT_TIMER2_CH2: trigger input source TIMER2 CH2
\arg TRIGSEL_INPUT_TIMER2_CH3: trigger input source TIMER2 CH3
\arg TRIGSEL_INPUT_TIMER2_ETI: trigger input source TIMER2 ETI
\arg TRIGSEL_INPUT_TIMER3_TRGO0: trigger input source TIMER3 TRGO0
\arg TRIGSEL_INPUT_TIMER3_CH0: trigger input source TIMER3 CH0
\arg TRIGSEL_INPUT_TIMER3_CH1: trigger input source TIMER3 CH1
\arg TRIGSEL_INPUT_TIMER3_CH2: trigger input source TIMER3 CH2
\arg TRIGSEL_INPUT_TIMER3_CH3: trigger input source TIMER3 CH3
\arg TRIGSEL_INPUT_TIMER3_ETI: trigger input source TIMER3 ETI
\arg TRIGSEL_INPUT_TIMER4_TRGO0: trigger input source TIMER4 TRGO0
\arg TRIGSEL_INPUT_TIMER4_CH0: trigger input source TIMER4 CH0
\arg TRIGSEL_INPUT_TIMER4_CH1: trigger input source TIMER4 CH1
\arg TRIGSEL_INPUT_TIMER4_CH2: trigger input source TIMER4 CH2
\arg TRIGSEL_INPUT_TIMER4_CH3: trigger input source TIMER4 CH3
\arg TRIGSEL_INPUT_TIMER4_ETI: trigger input source TIMER4 ETI
\arg TRIGSEL_INPUT_TIMER5_TRGO0: trigger input source TIMER5 TRGO0
\arg TRIGSEL_INPUT_TIMER6_TRGO0: trigger input source TIMER6 TRGO0
\arg TRIGSEL_INPUT_TIMER7_TRGO0: trigger input source TIMER7 TRGO0
\arg TRIGSEL_INPUT_TIMER7_TRGO1: trigger input source TIMER7 TRGO1
\arg TRIGSEL_INPUT_TIMER7_CH0: trigger input source TIMER7 CH0
\arg TRIGSEL_INPUT_TIMER7_CH1: trigger input source TIMER7 CH1
\arg TRIGSEL_INPUT_TIMER7_CH2: trigger input source TIMER7 CH2
\arg TRIGSEL_INPUT_TIMER7_CH3: trigger input source TIMER7 CH3
\arg TRIGSEL_INPUT_TIMER7_MCH0: trigger input source TIMER7 MCH0
\arg TRIGSEL_INPUT_TIMER7_MCH1: trigger input source TIMER7 MCH1
\arg TRIGSEL_INPUT_TIMER7_MCH2: trigger input source TIMER7 MCH2
\arg TRIGSEL_INPUT_TIMER7_MCH3: trigger input source TIMER7 MCH3
\arg TRIGSEL_INPUT_TIMER7_BRKIN0: trigger input source TIMER7 BRKIN0
\arg TRIGSEL_INPUT_TIMER7_BRKIN1: trigger input source TIMER7 BRKIN1
\arg TRIGSEL_INPUT_TIMER7_BRKIN2: trigger input source TIMER7 BRKIN2
\arg TRIGSEL_INPUT_TIMER7_ETI: trigger input source TIMER7 ETI
\arg TRIGSEL_INPUT_TIMER14_TRGO0: trigger input source TIMER14 TRGO0
\arg TRIGSEL_INPUT_TIMER14_CH0: trigger input source TIMER14 CH0
\arg TRIGSEL_INPUT_TIMER14_CH1: trigger input source TIMER14 CH1
\arg TRIGSEL_INPUT_TIMER14_MCH0: trigger input source TIMER14 MCH0
\arg TRIGSEL_INPUT_TIMER14_BRKIN0: trigger input source TIMER14 BRKIN0
\arg TRIGSEL_INPUT_TIMER15_CH0: trigger input source TIMER15 CH0
\arg TRIGSEL_INPUT_TIMER15_MCH0: trigger input source TIMER15 MCH0
\arg TRIGSEL_INPUT_TIMER15_BRKIN0: trigger input source TIMER15 BRKIN0
\arg TRIGSEL_INPUT_TIMER16_CH0: trigger input source TIMER16 CH0
\arg TRIGSEL_INPUT_TIMER16_MCH0: trigger input source TIMER16 MCH0
\arg TRIGSEL_INPUT_TIMER16_BRKIN0: trigger input source TIMER16 BRKIN0
\arg TRIGSEL_INPUT_TIMER22_TRGO0: trigger input source TIMER22 TRGO0
\arg TRIGSEL_INPUT_TIMER22_CH0: trigger input source TIMER22 CH0
\arg TRIGSEL_INPUT_TIMER22_CH1: trigger input source TIMER22 CH1
\arg TRIGSEL_INPUT_TIMER22_CH2: trigger input source TIMER22 CH2
\arg TRIGSEL_INPUT_TIMER22_CH3: trigger input source TIMER22 CH3
\arg TRIGSEL_INPUT_TIMER22_ETI: trigger input source TIMER22 ETI
\arg TRIGSEL_INPUT_TIMER23_TRGO0: trigger input source TIMER23 TRGO0
\arg TRIGSEL_INPUT_TIMER23_CH0: trigger input source TIMER23 CH0
\arg TRIGSEL_INPUT_TIMER23_CH1: trigger input source TIMER23 CH1
\arg TRIGSEL_INPUT_TIMER23_CH2: trigger input source TIMER23 CH2
\arg TRIGSEL_INPUT_TIMER23_CH3: trigger input source TIMER23 CH3
\arg TRIGSEL_INPUT_TIMER23_ETI: trigger input source TIMER23 ETI
\arg TRIGSEL_INPUT_TIMER40_TRGO0: trigger input source TIMER40 TRGO0
\arg TRIGSEL_INPUT_TIMER40_CH0: trigger input source TIMER40 CH0
\arg TRIGSEL_INPUT_TIMER40_CH1: trigger input source TIMER40 CH1
\arg TRIGSEL_INPUT_TIMER40_MCH0: trigger input source TIMER40 MCH0
\arg TRIGSEL_INPUT_TIMER40_BRKIN0: trigger input source TIMER40 BRKIN0
\arg TRIGSEL_INPUT_TIMER41_TRGO0: trigger input source TIMER41 TRGO0
\arg TRIGSEL_INPUT_TIMER41_CH0: trigger input source TIMER41 CH0
\arg TRIGSEL_INPUT_TIMER41_CH1: trigger input source TIMER41 CH1
\arg TRIGSEL_INPUT_TIMER41_MCH0: trigger input source TIMER41 MCH0
\arg TRIGSEL_INPUT_TIMER41_BRKIN0: trigger input source TIMER41 BRKIN0
\arg TRIGSEL_INPUT_TIMER42_TRGO0: trigger input source TIMER42 TRGO0
\arg TRIGSEL_INPUT_TIMER42_CH0: trigger input source TIMER42 CH0
\arg TRIGSEL_INPUT_TIMER42_CH1: trigger input source TIMER42 CH1
\arg TRIGSEL_INPUT_TIMER42_MCH0: trigger input source TIMER42 MCH0
\arg TRIGSEL_INPUT_TIMER42_BRKIN0: trigger input source TIMER42 BRKIN0
\arg TRIGSEL_INPUT_TIMER43_TRGO0: trigger input source TIMER43 TRGO0
\arg TRIGSEL_INPUT_TIMER43_CH0: trigger input source TIMER43 CH0
\arg TRIGSEL_INPUT_TIMER43_CH1: trigger input source TIMER43 CH1
\arg TRIGSEL_INPUT_TIMER43_MCH0: trigger input source TIMER43 MCH0
\arg TRIGSEL_INPUT_TIMER43_BRKIN0: trigger input source TIMER43 BRKIN0
\arg TRIGSEL_INPUT_TIMER44_TRGO0: trigger input source TIMER44 TRGO0
\arg TRIGSEL_INPUT_TIMER44_CH0: trigger input source TIMER44 CH0
\arg TRIGSEL_INPUT_TIMER44_CH1: trigger input source TIMER44 CH1
\arg TRIGSEL_INPUT_TIMER44_MCH0: trigger input source TIMER44 MCH0
\arg TRIGSEL_INPUT_TIMER44_BRKIN0: trigger input source TIMER44 BRKIN0
\arg TRIGSEL_INPUT_TIMER50_TRGO0: trigger input source TIMER50 TRGO0
\arg TRIGSEL_INPUT_TIMER51_TRGO0: trigger input source TIMER51 TRGO0
\arg TRIGSEL_INPUT_RTC_ALARM: trigger input source RTC alarm
\arg TRIGSEL_INPUT_RTC_TPTS: trigger input source RTC tamper and time-stamp
\arg TRIGSEL_INPUT_ADC0_WD0_OUT: trigger input source ADC0 watchdog0 output
\arg TRIGSEL_INPUT_ADC0_WD1_OUT: trigger input source ADC0 watchdog1 output
\arg TRIGSEL_INPUT_ADC0_WD2_OUT: trigger input source ADC0 watchdog2 output
\arg TRIGSEL_INPUT_ADC1_WD0_OUT: trigger input source ADC1 watchdog0 output
\arg TRIGSEL_INPUT_ADC1_WD1_OUT: trigger input source ADC1 watchdog1 output
\arg TRIGSEL_INPUT_ADC1_WD2_OUT: trigger input source ADC1 watchdog2 output
\arg TRIGSEL_INPUT_ADC2_WD0_OUT: trigger input source ADC2 watchdog0 output
\arg TRIGSEL_INPUT_ADC2_WD1_OUT: trigger input source ADC2 watchdog1 output
\arg TRIGSEL_INPUT_ADC2_WD2_OUT: trigger input source ADC2 watchdog2 output
\arg TRIGSEL_INPUT_CMP0_OUT: trigger input source CMP0_OUT
\arg TRIGSEL_INPUT_CMP1_OUT: trigger input source CMP1_OUT
\arg TRIGSEL_INPUT_SAI0_FS0: trigger input source SAI0_FS0
\arg TRIGSEL_INPUT_SAI0_FS1: trigger input source SAI0_FS1
\arg TRIGSEL_INPUT_SAI2_FS0: trigger input source SAI2_FS0
\arg TRIGSEL_INPUT_SAI2_FS1: trigger input source SAI2_FS1
\param[out] none
\retval none
*/
void trigsel_init(trigsel_periph_enum target_periph, trigsel_source_enum trigger_source)
{
/* if register write is enabled, set trigger source to target peripheral */
if (RESET == trigsel_register_lock_get(target_periph)){
TRIGSEL_TARGET_REG(target_periph) &= ~TRIGSEL_TARGET_PERIPH_MASK(target_periph);
TRIGSEL_TARGET_REG(target_periph) |= ((uint32_t)trigger_source << TRIGSEL_TARGET_PERIPH_SHIFT(target_periph)) & TRIGSEL_TARGET_PERIPH_MASK(target_periph);
}
}
/*!
\brief get the trigger input signal for target peripheral
\param[in] target_periph: target peripheral value
only one parameter can be selected which is shown as below:
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT0: output target peripheral TRIGSEL_OUT0 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT1: output target peripheral TRIGSEL_OUT1 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT2: output target peripheral TRIGSEL_OUT2 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT3: output target peripheral TRIGSEL_OUT3 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT4: output target peripheral TRIGSEL_OUT4 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT5: output target peripheral TRIGSEL_OUT5 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT6: output target peripheral TRIGSEL_OUT6 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT7: output target peripheral TRIGSEL_OUT7 pin
\arg TRIGSEL_OUTPUT_ADC0_REGTRG: output target peripheral ADC0_REGTRG
\arg TRIGSEL_OUTPUT_ADC0_INSTRG: output target peripheral ADC0_INSTRG
\arg TRIGSEL_OUTPUT_ADC1_REGTRG: output target peripheral ADC1_REGTRG
\arg TRIGSEL_OUTPUT_ADC1_INSTRG: output target peripheral ADC1_INSTRG
\arg TRIGSEL_OUTPUT_ADC2_REGTRG: output target peripheral ADC2_REGTRG
\arg TRIGSEL_OUTPUT_ADC2_INSTRG: output target peripheral ADC2_INSTRG
\arg TRIGSEL_OUTPUT_DAC0_OUT0_EXTRG: output target peripheral DAC0_OUT0_EXTRG
\arg TRIGSEL_OUTPUT_DAC0_OUT1_EXTRG: output target peripheral DAC0_OUT1_EXTRG
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN0: output target peripheral TIMER0_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN1: output target peripheral TIMER0_BRKIN1
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN2: output target peripheral TIMER0_BRKIN2
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN0: output target peripheral TIMER7_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN1: output target peripheral TIMER7_BRKIN1
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN2: output target peripheral TIMER7_BRKIN2
\arg TRIGSEL_OUTPUT_TIMER14_BRKIN0: output target peripheral TIMER14_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER15_BRKIN0: output target peripheral TIMER15_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER16_BRKIN0: output target peripheral TIMER16_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER40_BRKIN0: output target peripheral TIMER40_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER41_BRKIN0: output target peripheral TIMER41_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER42_BRKIN0: output target peripheral TIMER42_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER43_BRKIN0: output target peripheral TIMER43_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER44_BRKIN0: output target peripheral TIMER44_BRKIN0
\arg TRIGSEL_OUTPUT_CAN0_EX_TIME_TICK: output target peripheral CAN0_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_CAN1_EX_TIME_TICK: output target peripheral CAN1_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_CAN2_EX_TIME_TICK: output target peripheral CAN2_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_LPDTS_TRG: output target peripheral LPDTS_TRG
\arg TRIGSEL_OUTPUT_TIMER0_ETI: output target peripheral TIMER0_ETI
\arg TRIGSEL_OUTPUT_TIMER1_ETI: output target peripheral TIMER1_ETI
\arg TRIGSEL_OUTPUT_TIMER2_ETI: output target peripheral TIMER2_ETI
\arg TRIGSEL_OUTPUT_TIMER3_ETI: output target peripheral TIMER3_ETI
\arg TRIGSEL_OUTPUT_TIMER4_ETI: output target peripheral TIMER4_ETI
\arg TRIGSEL_OUTPUT_TIMER7_ETI: output target peripheral TIMER7_ETI
\arg TRIGSEL_OUTPUT_TIMER22_ETI: output target peripheral TIMER22_ETI
\arg TRIGSEL_OUTPUT_TIMER23_ETI: output target peripheral TIMER23_ETI
\arg TRIGSEL_OUTPUT_EDOUT_TRG: output target peripheral EDOUT_TRG
\arg TRIGSEL_OUTPUT_HPDF_ITRG: output target peripheral HPDF_ITR
\arg TRIGSEL_OUTPUT_TIMER0_ITI14: output target peripheral TIMER0_ITI14
\arg TRIGSEL_OUTPUT_TIMER1_ITI14: output target peripheral TIMER1_ITI14
\arg TRIGSEL_OUTPUT_TIMER2_ITI14: output target peripheral TIMER2_ITI14
\arg TRIGSEL_OUTPUT_TIMER3_ITI14: output target peripheral TIMER3_ITI14
\arg TRIGSEL_OUTPUT_TIMER4_ITI14: output target peripheral TIMER4_ITI14
\arg TRIGSEL_OUTPUT_TIMER7_ITI14: output target peripheral TIMER7_ITI14
\arg TRIGSEL_OUTPUT_TIMER14_ITI14: output target peripheral TIMER14_ITI14
\arg TRIGSEL_OUTPUT_TIMER22_ITI14: output target peripheral TIMER22_ITI14
\arg TRIGSEL_OUTPUT_TIMER23_ITI14: output target peripheral TIMER23_ITI14
\arg TRIGSEL_OUTPUT_TIMER40_ITI14: output target peripheral TIMER40_ITI14
\arg TRIGSEL_OUTPUT_TIMER41_ITI14: output target peripheral TIMER41_ITI14
\arg TRIGSEL_OUTPUT_TIMER42_ITI14: output target peripheral TIMER42_ITI14
\arg TRIGSEL_OUTPUT_TIMER43_ITI14: output target peripheral TIMER43_ITI14
\arg TRIGSEL_OUTPUT_TIMER44_ITI14: output target peripheral TIMER44_ITI14
\param[out] none
\retval trigger_source: trigger source value(0~177)
*/
trigsel_source_enum trigsel_trigger_source_get(trigsel_periph_enum target_periph)
{
trigsel_source_enum trigger_source;
trigger_source = (trigsel_source_enum)((TRIGSEL_TARGET_REG(target_periph) & TRIGSEL_TARGET_PERIPH_MASK(target_periph)) >> TRIGSEL_TARGET_PERIPH_SHIFT(target_periph));
return trigger_source;
}
/*!
\brief lock the trigger register
\param[in] target_periph: target peripheral value
only one parameter can be selected which is shown as below:
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT0: output target peripheral TRIGSEL_OUT0 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT1: output target peripheral TRIGSEL_OUT1 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT2: output target peripheral TRIGSEL_OUT2 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT3: output target peripheral TRIGSEL_OUT3 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT4: output target peripheral TRIGSEL_OUT4 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT5: output target peripheral TRIGSEL_OUT5 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT6: output target peripheral TRIGSEL_OUT6 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT7: output target peripheral TRIGSEL_OUT7 pin
\arg TRIGSEL_OUTPUT_ADC0_REGTRG: output target peripheral ADC0_REGTRG
\arg TRIGSEL_OUTPUT_ADC0_INSTRG: output target peripheral ADC0_INSTRG
\arg TRIGSEL_OUTPUT_ADC1_REGTRG: output target peripheral ADC1_REGTRG
\arg TRIGSEL_OUTPUT_ADC1_INSTRG: output target peripheral ADC1_INSTRG
\arg TRIGSEL_OUTPUT_ADC2_REGTRG: output target peripheral ADC2_REGTRG
\arg TRIGSEL_OUTPUT_ADC2_INSTRG: output target peripheral ADC2_INSTRG
\arg TRIGSEL_OUTPUT_DAC0_OUT0_EXTRG: output target peripheral DAC0_OUT0_EXTRG
\arg TRIGSEL_OUTPUT_DAC0_OUT1_EXTRG: output target peripheral DAC0_OUT1_EXTRG
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN0: output target peripheral TIMER0_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN1: output target peripheral TIMER0_BRKIN1
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN2: output target peripheral TIMER0_BRKIN2
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN0: output target peripheral TIMER7_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN1: output target peripheral TIMER7_BRKIN1
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN2: output target peripheral TIMER7_BRKIN2
\arg TRIGSEL_OUTPUT_TIMER14_BRKIN0: output target peripheral TIMER14_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER15_BRKIN0: output target peripheral TIMER15_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER16_BRKIN0: output target peripheral TIMER16_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER40_BRKIN0: output target peripheral TIMER40_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER41_BRKIN0: output target peripheral TIMER41_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER42_BRKIN0: output target peripheral TIMER42_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER43_BRKIN0: output target peripheral TIMER43_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER44_BRKIN0: output target peripheral TIMER44_BRKIN0
\arg TRIGSEL_OUTPUT_CAN0_EX_TIME_TICK: output target peripheral CAN0_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_CAN1_EX_TIME_TICK: output target peripheral CAN1_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_CAN2_EX_TIME_TICK: output target peripheral CAN2_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_LPDTS_TRG: output target peripheral LPDTS_TRG
\arg TRIGSEL_OUTPUT_TIMER0_ETI: output target peripheral TIMER0_ETI
\arg TRIGSEL_OUTPUT_TIMER1_ETI: output target peripheral TIMER1_ETI
\arg TRIGSEL_OUTPUT_TIMER2_ETI: output target peripheral TIMER2_ETI
\arg TRIGSEL_OUTPUT_TIMER3_ETI: output target peripheral TIMER3_ETI
\arg TRIGSEL_OUTPUT_TIMER4_ETI: output target peripheral TIMER4_ETI
\arg TRIGSEL_OUTPUT_TIMER7_ETI: output target peripheral TIMER7_ETI
\arg TRIGSEL_OUTPUT_TIMER22_ETI: output target peripheral TIMER22_ETI
\arg TRIGSEL_OUTPUT_TIMER23_ETI: output target peripheral TIMER23_ETI
\arg TRIGSEL_OUTPUT_EDOUT_TRG: output target peripheral EDOUT_TRG
\arg TRIGSEL_OUTPUT_HPDF_ITRG: output target peripheral HPDF_ITR
\arg TRIGSEL_OUTPUT_TIMER0_ITI14: output target peripheral TIMER0_ITI14
\arg TRIGSEL_OUTPUT_TIMER1_ITI14: output target peripheral TIMER1_ITI14
\arg TRIGSEL_OUTPUT_TIMER2_ITI14: output target peripheral TIMER2_ITI14
\arg TRIGSEL_OUTPUT_TIMER3_ITI14: output target peripheral TIMER3_ITI14
\arg TRIGSEL_OUTPUT_TIMER4_ITI14: output target peripheral TIMER4_ITI14
\arg TRIGSEL_OUTPUT_TIMER7_ITI14: output target peripheral TIMER7_ITI14
\arg TRIGSEL_OUTPUT_TIMER14_ITI14: output target peripheral TIMER14_ITI14
\arg TRIGSEL_OUTPUT_TIMER22_ITI14: output target peripheral TIMER22_ITI14
\arg TRIGSEL_OUTPUT_TIMER23_ITI14: output target peripheral TIMER23_ITI14
\arg TRIGSEL_OUTPUT_TIMER40_ITI14: output target peripheral TIMER40_ITI14
\arg TRIGSEL_OUTPUT_TIMER41_ITI14: output target peripheral TIMER41_ITI14
\arg TRIGSEL_OUTPUT_TIMER42_ITI14: output target peripheral TIMER42_ITI14
\arg TRIGSEL_OUTPUT_TIMER43_ITI14: output target peripheral TIMER43_ITI14
\arg TRIGSEL_OUTPUT_TIMER44_ITI14: output target peripheral TIMER44_ITI14
\param[out] none
\retval none
*/
void trigsel_register_lock_set(trigsel_periph_enum target_periph)
{
/*!< lock target peripheral register */
TRIGSEL_TARGET_REG(target_periph) |= TRIGSEL_TARGET_LK;
}
/*!
\brief get the trigger register lock status
\param[in] target_periph: target peripheral value
only one parameter can be selected which is shown as below:
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT0: output target peripheral TRIGSEL_OUT0 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT1: output target peripheral TRIGSEL_OUT1 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT2: output target peripheral TRIGSEL_OUT2 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT3: output target peripheral TRIGSEL_OUT3 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT4: output target peripheral TRIGSEL_OUT4 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT5: output target peripheral TRIGSEL_OUT5 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT6: output target peripheral TRIGSEL_OUT6 pin
\arg TRIGSEL_OUTPUT_TRIGSEL_OUT7: output target peripheral TRIGSEL_OUT7 pin
\arg TRIGSEL_OUTPUT_ADC0_REGTRG: output target peripheral ADC0_REGTRG
\arg TRIGSEL_OUTPUT_ADC0_INSTRG: output target peripheral ADC0_INSTRG
\arg TRIGSEL_OUTPUT_ADC1_REGTRG: output target peripheral ADC1_REGTRG
\arg TRIGSEL_OUTPUT_ADC1_INSTRG: output target peripheral ADC1_INSTRG
\arg TRIGSEL_OUTPUT_ADC2_REGTRG: output target peripheral ADC2_REGTRG
\arg TRIGSEL_OUTPUT_ADC2_INSTRG: output target peripheral ADC2_INSTRG
\arg TRIGSEL_OUTPUT_DAC0_OUT0_EXTRG: output target peripheral DAC0_OUT0_EXTRG
\arg TRIGSEL_OUTPUT_DAC0_OUT1_EXTRG: output target peripheral DAC0_OUT1_EXTRG
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN0: output target peripheral TIMER0_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN1: output target peripheral TIMER0_BRKIN1
\arg TRIGSEL_OUTPUT_TIMER0_BRKIN2: output target peripheral TIMER0_BRKIN2
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN0: output target peripheral TIMER7_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN1: output target peripheral TIMER7_BRKIN1
\arg TRIGSEL_OUTPUT_TIMER7_BRKIN2: output target peripheral TIMER7_BRKIN2
\arg TRIGSEL_OUTPUT_TIMER14_BRKIN0: output target peripheral TIMER14_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER15_BRKIN0: output target peripheral TIMER15_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER16_BRKIN0: output target peripheral TIMER16_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER40_BRKIN0: output target peripheral TIMER40_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER41_BRKIN0: output target peripheral TIMER41_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER42_BRKIN0: output target peripheral TIMER42_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER43_BRKIN0: output target peripheral TIMER43_BRKIN0
\arg TRIGSEL_OUTPUT_TIMER44_BRKIN0: output target peripheral TIMER44_BRKIN0
\arg TRIGSEL_OUTPUT_CAN0_EX_TIME_TICK: output target peripheral CAN0_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_CAN1_EX_TIME_TICK: output target peripheral CAN1_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_CAN2_EX_TIME_TICK: output target peripheral CAN2_EX_TIME_TICK
\arg TRIGSEL_OUTPUT_LPDTS_TRG: output target peripheral LPDTS_TRG
\arg TRIGSEL_OUTPUT_TIMER0_ETI: output target peripheral TIMER0_ETI
\arg TRIGSEL_OUTPUT_TIMER1_ETI: output target peripheral TIMER1_ETI
\arg TRIGSEL_OUTPUT_TIMER2_ETI: output target peripheral TIMER2_ETI
\arg TRIGSEL_OUTPUT_TIMER3_ETI: output target peripheral TIMER3_ETI
\arg TRIGSEL_OUTPUT_TIMER4_ETI: output target peripheral TIMER4_ETI
\arg TRIGSEL_OUTPUT_TIMER7_ETI: output target peripheral TIMER7_ETI
\arg TRIGSEL_OUTPUT_TIMER22_ETI: output target peripheral TIMER22_ETI
\arg TRIGSEL_OUTPUT_TIMER23_ETI: output target peripheral TIMER23_ETI
\arg TRIGSEL_OUTPUT_EDOUT_TRG: output target peripheral EDOUT_TRG
\arg TRIGSEL_OUTPUT_HPDF_ITRG: output target peripheral HPDF_ITR
\arg TRIGSEL_OUTPUT_TIMER0_ITI14: output target peripheral TIMER0_ITI14
\arg TRIGSEL_OUTPUT_TIMER1_ITI14: output target peripheral TIMER1_ITI14
\arg TRIGSEL_OUTPUT_TIMER2_ITI14: output target peripheral TIMER2_ITI14
\arg TRIGSEL_OUTPUT_TIMER3_ITI14: output target peripheral TIMER3_ITI14
\arg TRIGSEL_OUTPUT_TIMER4_ITI14: output target peripheral TIMER4_ITI14
\arg TRIGSEL_OUTPUT_TIMER7_ITI14: output target peripheral TIMER7_ITI14
\arg TRIGSEL_OUTPUT_TIMER14_ITI14: output target peripheral TIMER14_ITI14
\arg TRIGSEL_OUTPUT_TIMER22_ITI14: output target peripheral TIMER22_ITI14
\arg TRIGSEL_OUTPUT_TIMER23_ITI14: output target peripheral TIMER23_ITI14
\arg TRIGSEL_OUTPUT_TIMER40_ITI14: output target peripheral TIMER40_ITI14
\arg TRIGSEL_OUTPUT_TIMER41_ITI14: output target peripheral TIMER41_ITI14
\arg TRIGSEL_OUTPUT_TIMER42_ITI14: output target peripheral TIMER42_ITI14
\arg TRIGSEL_OUTPUT_TIMER43_ITI14: output target peripheral TIMER43_ITI14
\arg TRIGSEL_OUTPUT_TIMER44_ITI14: output target peripheral TIMER44_ITI14
\param[out] none
\retval SET or RESET
*/
FlagStatus trigsel_register_lock_get(trigsel_periph_enum target_periph)
{
if(RESET != (TRIGSEL_TARGET_REG(target_periph) & TRIGSEL_TARGET_LK)){
return SET;
}else{
return RESET;
}
}
@@ -0,0 +1,469 @@
/*!
\file gd32h75e_trng.c
\brief TRNG driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_trng.h"
/*!
\brief deinitialize the TRNG
\param[in] none
\param[out] none
\retval none
*/
void trng_deinit(void)
{
rcu_periph_reset_enable(RCU_TRNGRST);
rcu_periph_reset_disable(RCU_TRNGRST);
}
/*!
\brief enable the TRNG interface
\param[in] none
\param[out] none
\retval none
*/
void trng_enable(void)
{
uint32_t trng_config = TRNG_CTL;
trng_config &= ~TRNG_CTL_CONDRST;
trng_config |= TRNG_CTL_TRNGEN;
TRNG_CTL = trng_config;
}
/*!
\brief disable the TRNG interface
\param[in] none
\param[out] none
\retval none
*/
void trng_disable(void)
{
TRNG_CTL &= ~TRNG_CTL_TRNGEN;
}
/*!
\brief lock the TRNG control bits
\param[in] none
\param[out] none
\retval none
*/
void trng_lock(void)
{
TRNG_CTL |= TRNG_CTL_LK;
}
/*!
\brief configure TRNG working mode
\param[in] mode_select: the TRNG working mode
only one parameter can be selected which is shown as below:
\arg TRNG_MODSEL_LFSR: TRNG working in LFSR mode
\arg TRNG_MODSEL_NIST: TRNG working in NIST mode
\param[out] none
\retval none
*/
void trng_mode_config(trng_modsel_enum mode_select)
{
uint32_t trng_config = TRNG_CTL;
trng_config &= ~TRNG_CTL_MODSEL;
trng_config |= mode_select;
TRNG_CTL = trng_config;
}
/*!
\brief enable the TRNG post-processing module
\param[in] none
\param[out] none
\retval none
*/
void trng_postprocessing_enable(void)
{
TRNG_CTL |= TRNG_CTL_PPEN;
}
/*!
\brief disable the TRNG post-processing module
\param[in] none
\param[out] none
\retval none
*/
void trng_postprocessing_disable(void)
{
TRNG_CTL &= ~TRNG_CTL_PPEN;
}
/*!
\brief enable the TRNG conditioning module
\param[in] none
\param[out] none
\retval none
*/
void trng_conditioning_enable(void)
{
TRNG_CTL |= TRNG_CTL_CONDEN;
}
/*!
\brief disable the TRNG conditioning module
\param[in] none
\param[out] none
\retval none
*/
void trng_conditioning_disable(void)
{
TRNG_CTL &= ~TRNG_CTL_CONDEN;
}
/*!
\brief configure TRNG conditioning module input bitwidth
\param[in] input_bitwidth: the input bit width
only one parameter can be selected which is shown as below:
\arg TRNG_INMOD_256BIT: conditioning module input bitwidth 256bits
\arg TRNG_INMOD_440BIT: conditioning module input bitwidth 440bits
\param[out] none
\retval none
*/
void trng_conditioning_input_bitwidth(trng_inmod_enum input_bitwidth)
{
uint32_t trng_config = TRNG_CTL;
trng_config &= ~TRNG_CTL_INMOD;
trng_config |= input_bitwidth;
TRNG_CTL = trng_config;
}
/*!
\brief configure TRNG conditioning module output bitwidth
\param[in] output_bitwidth:
only one parameter can be selected which is shown as below:
\arg TRNG_OUTMOD_128BIT: conditioning module output bitwidth 128bits
\arg TRNG_OUTMOD_256BIT: conditioning module output bitwidth 256bits
\param[out] none
\retval none
*/
void trng_conditioning_output_bitwidth(trng_outmod_enum output_bitwidth)
{
uint32_t trng_config = TRNG_CTL;
trng_config &= ~TRNG_CTL_OUTMOD;
trng_config |= (uint32_t)output_bitwidth;
TRNG_CTL = trng_config;
}
/*!
\brief enable TRNG replace test
\param[in] none
\param[out] none
\retval none
*/
void trng_replace_test_enable(void)
{
TRNG_CTL |= TRNG_CTL_RTEN;
}
/*!
\brief disable TRNG replace test
\param[in] none
\param[out] none
\retval none
*/
void trng_replace_test_disable(void)
{
TRNG_CTL &= ~TRNG_CTL_RTEN;
}
/*!
\brief enable hash algorithm init when conditioning module enabled
\param[in] none
\param[out] none
\retval none
*/
void trng_hash_init_enable(void)
{
TRNG_CTL |= TRNG_CTL_INIT;
}
/*!
\brief disable hash algorithm init when conditioning module enabled
\param[in] none
\param[out] none
\retval none
*/
void trng_hash_init_disable(void)
{
TRNG_CTL &= ~TRNG_CTL_INIT;
}
/*!
\brief configure TRNG analog power mode
\param[in] powermode: the power mode selection
only one parameter can be selected which is shown as below:
\arg TRNG_NR_ULTRALOW: TRNG analog power mode ultralow
\arg TRNG_NR_LOW: TRNG analog power mode low
\arg TRNG_NR_MEDIUM: TRNG analog power mode medium
\arg TRNG_NR_HIGH: TRNG analog power mode high
\param[out] none
\retval none
*/
void trng_powermode_config(uint32_t powermode)
{
uint32_t trng_config = TRNG_CTL;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_TRNG_POWER_MODE(powermode)) {
fw_debug_report_err(TRNG_MODULE_ID, API_ID(0x0010U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
trng_config &= ~TRNG_CTL_NR;
trng_config |= powermode;
TRNG_CTL = trng_config;
}
}
/*!
\brief configure TRNG clock divider
\param[in] clkdiv: TRNG clock divider
only one parameter can be selected which is shown as below:
\arg TRNG_CLK_DIVx (x=1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768)
\param[out] none
\retval none
*/
void trng_clockdiv_config(uint32_t clkdiv)
{
uint32_t trng_config = TRNG_CTL;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_TRNG_CLOCK_DIVIDER(clkdiv)) {
fw_debug_report_err(TRNG_MODULE_ID, API_ID(0x0011U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
trng_config &= ~TRNG_CTL_CLKDIV;
trng_config |= clkdiv;
TRNG_CTL = trng_config;
}
}
/*!
\brief enable the TRNG clock error detection
\param[in] none
\param[out] none
\retval none
*/
void trng_clockerror_detection_enable(void)
{
TRNG_CTL |= TRNG_CTL_CED;
}
/*!
\brief disable the TRNG clock error detection
\param[in] none
\param[out] none
\retval none
*/
void trng_clockerror_detection_disable(void)
{
TRNG_CTL &= ~TRNG_CTL_CED;
}
/*!
\brief get the true random data
\param[in] none
\param[out] none
\retval the generated random data
*/
uint32_t trng_get_true_random_data(void)
{
return (TRNG_DATA);
}
/*!
\brief enable the conditioning logic reset
\param[in] none
\param[out] none
\retval none
*/
void trng_conditioning_reset_enable(void)
{
TRNG_CTL |= TRNG_CTL_CONDRST;
}
/*!
\brief disable the conditioning logic reset
\param[in] none
\param[out] none
\retval none
*/
void trng_conditioning_reset_disable(void)
{
TRNG_CTL &= ~TRNG_CTL_CONDRST;
}
/*!
\brief configure the conditioning module hash algorithm
\param[in] module_algo: module hash algorithm
only one parameter can be selected which is shown as below:
\arg TRNG_ALGO_SHA1: TRNG conditioning module hash SHA1
\arg TRNG_ALGO_MD5: TRNG conditioning module hash MD5
\arg TRNG_ALGO_SHA224: TRNG conditioning module hash SHA224
\arg TRNG_ALGO_SHA256: TRNG conditioning module hash SHA256
\param[out] none
\retval none
*/
void trng_conditioning_algo_config(uint32_t module_algo)
{
uint32_t tmp = TRNG_CTL;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_TRNG_MODULE_ALGORITHM(module_algo)) {
fw_debug_report_err(TRNG_MODULE_ID, API_ID(0x0017U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
tmp &= ~(TRNG_CTL_ALGO);
tmp |= module_algo;
TRNG_CTL = tmp;
}
}
/*!
\brief configure health tests default value
\param[in] adpo_threshold: adaptive proportion test threshold value
\param[in] rep_threshold: repetitive (00/11) test threshold value
\param[out] none
\retval none
*/
void trng_health_tests_config(uint32_t adpo_threshold, uint8_t rep_threshold)
{
uint32_t tmp = TRNG_HTCFG;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_TRNG_ADPO_THRESHOLD(adpo_threshold)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0018U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_TRNG_REP_THRESHOLD(rep_threshold)) {
fw_debug_report_err(GPIO_MODULE_ID, API_ID(0x0018U), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
tmp &= ~(TRNG_HTCFG_APTTH | TRNG_HTCFG_RCTTH);
tmp |= (((uint32_t)(adpo_threshold << 16U) & TRNG_HTCFG_APTTH) | (rep_threshold & TRNG_HTCFG_RCTTH));
TRNG_HTCFG = tmp;
}
}
/*!
\brief get the TRNG status flags
\param[in] flag: TRNG status flag, refer to trng_flag_enum
only one parameter can be selected which is shown as below:
\arg TRNG_FLAG_DRDY: random data ready status
\arg TRNG_FLAG_CECS: clock error current status
\arg TRNG_FLAG_SECS: seed error current status
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus trng_flag_get(trng_flag_enum flag)
{
FlagStatus reval = RESET;
if(RESET != (TRNG_STAT & flag)) {
reval = SET;
} else {
reval = RESET;
}
return reval;
}
/*!
\brief enable the TRNG interrupt
\param[in] none
\param[out] none
\retval none
*/
void trng_interrupt_enable(void)
{
TRNG_CTL |= TRNG_CTL_IE;
}
/*!
\brief disable the TRNG interrupt
\param[in] none
\param[out] none
\retval none
*/
void trng_interrupt_disable(void)
{
TRNG_CTL &= ~TRNG_CTL_IE;
}
/*!
\brief get the TRNG interrupt flags
\param[in] int_flag: TRNG interrupt flag, refer to trng_int_flag_enum
only one parameter can be selected which is shown as below:
\arg TRNG_INT_FLAG_CEIF: clock error interrupt flag
\arg TRNG_INT_FLAG_SEIF: seed error interrupt flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus trng_interrupt_flag_get(trng_int_flag_enum int_flag)
{
FlagStatus reval = RESET;
if(RESET != (TRNG_STAT & int_flag)) {
reval = SET;
} else {
reval = RESET;
}
return reval;
}
/*!
\brief clear the TRNG interrupt flags
\param[in] int_flag: TRNG interrupt flag, refer to trng_int_flag_enum
only one parameter can be selected which is shown as below:
\arg TRNG_INT_FLAG_CEIF: clock error interrupt flag
\arg TRNG_INT_FLAG_SEIF: seed error interrupt flag
\param[out] none
\retval none
*/
void trng_interrupt_flag_clear(trng_int_flag_enum int_flag)
{
TRNG_STAT &= ~(uint32_t)int_flag;
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,167 @@
/*!
\file gd32h75e_vref.c
\brief VREF driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_vref.h"
/*!
\brief deinitialize the VREF
\param[in] none
\param[out] none
\retval none
*/
void vref_deinit(void)
{
rcu_periph_reset_enable(RCU_VREFRST);
rcu_periph_reset_disable(RCU_VREFRST);
}
/*!
\brief enable VREF
\param[in] none
\param[out] none
\retval none
*/
void vref_enable(void)
{
VREF_CS |= VREF_EN;
}
/*!
\brief disable VREF
\param[in] none
\param[out] none
\retval none
*/
void vref_disable(void)
{
VREF_CS &= (uint32_t)~VREF_EN;
}
/*!
\brief enable VREF high impendance mode
\param[in] none
\param[out] none
\retval none
*/
void vref_high_impedance_mode_enable(void)
{
VREF_CS |= VREF_HIGH_IMPEDANCE_MODE;
}
/*!
\brief disable VREF high impendance mode
\param[in] none
\param[out] none
\retval none
*/
void vref_high_impedance_mode_disable(void)
{
VREF_CS &= (uint32_t)~VREF_HIGH_IMPEDANCE_MODE;
}
/*!
\brief get the status of VREF
\param[in] none
\param[out] none
\retval the status of VREF output
\arg SET: the VREF output is ready
\arg RESET: the VREF output is not ready
*/
FlagStatus vref_status_get(void)
{
if(RESET != (VREF_CS & (uint32_t)VREF_CS_VREFRDY)){
return SET;
}else{
return RESET;
}
}
/*!
\brief select the VREF voltage reference
\param[in] vref_voltage: voltage reference select,
only one parameter can be selected which is shown as below:
\arg VREF_VOLTAGE_SEL_2_5V: VREF voltage reference select 2.5 V
\arg VREF_VOLTAGE_SEL_2_048V: VREF voltage reference select 2.048 V
\arg VREF_VOLTAGE_SEL_1_8V: VREF voltage reference select 1.8 V
\arg VREF_VOLTAGE_SEL_1_5V: VREF voltage reference select 1.5 V
\param[out] none
\retval none
*/
void vref_voltage_select(uint32_t vref_voltage)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_VREF_VOLTAGE(vref_voltage)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0001U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
uint32_t temp = VREF_CS;
/* clear old value */
temp &= ~(uint32_t)VREF_VOLTAGE_SEL_1_5V;
temp |= (uint32_t)vref_voltage;
VREF_CS = temp;
}
}
/*!
\brief set the calibration value of VREF
\param[in] value: calibration value (0x00 - 0x3F)
\param[out] none
\retval none
*/
void vref_calib_value_set(uint8_t value)
{
#ifdef FW_DEBUG_ERR_REPORT
if(NOT_VREF_CALIB_VALUE(value)) {
fw_debug_report_err(ADC_MODULE_ID, API_ID(0x0002U), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
VREF_CALIB = (uint32_t)(VREF_CALIB_VREFCAL & value);
}
}
/*!
\brief get the calibration value of VREF
\param[in] none
\param[out] none
\retval calibration value (0x00 - 0x3F)
*/
uint8_t vref_calib_value_get(void)
{
uint8_t temp = (uint8_t)VREF_CALIB;
return temp;
}
@@ -0,0 +1,151 @@
/*!
\file gd32h75e_wwdgt.c
\brief WWDGT driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_wwdgt.h"
/* WWDGT_CTL register value */
#define CTL_CNT(regval) (BITS(0,6) & ((uint32_t)(regval) << 0U))
/* WWDGT_CFG register value */
#define CFG_WIN(regval) (BITS(0,6) & ((uint32_t)(regval) << 0U))
/*!
\brief reset the window watchdog timer configuration
\param[in] none
\param[out] none
\retval none
*/
void wwdgt_deinit(void)
{
rcu_periph_reset_enable(RCU_WWDGTRST);
rcu_periph_reset_disable(RCU_WWDGTRST);
}
/*!
\brief start the WWDGT counter
\param[in] none
\param[out] none
\retval none
*/
void wwdgt_enable(void)
{
WWDGT_CTL |= WWDGT_CTL_WDGTEN;
}
/*!
\brief configure the WWDGT counter value
\param[in] counter_value: 0x00 - 0x7F
\param[out] none
\retval none
*/
void wwdgt_counter_update(uint16_t counter_value)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_WWDGT_COUNTER_VALUE(counter_value)) {
fw_debug_report_err(WWDGT_MODULE_ID, API_ID(0x0003U), ERR_PARAM_INVALID);
} else
#endif
{
WWDGT_CTL = (uint32_t)(CTL_CNT(counter_value));
}
}
/*!
\brief configure counter value, window value, and prescaler divider value
\param[in] counter: 0x0000 - 0x007F
\param[in] window: 0x0000 - 0x007F
\param[in] prescaler: WWDGT prescaler value
only one parameter can be selected which is shown as below:
\arg WWDGT_CFG_PSC_DIV1: the time base of window watchdog counter = (PCLK3/4096)/1
\arg WWDGT_CFG_PSC_DIV2: the time base of window watchdog counter = (PCLK3/4096)/2
\arg WWDGT_CFG_PSC_DIV4: the time base of window watchdog counter = (PCLK3/4096)/4
\arg WWDGT_CFG_PSC_DIV8: the time base of window watchdog counter = (PCLK3/4096)/8
\param[out] none
\retval none
*/
void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_WWDGT_COUNTER_VALUE(counter)) {
fw_debug_report_err(WWDGT_MODULE_ID, API_ID(0x0004U), ERR_PARAM_INVALID);
} else if(NOT_WWDGT_WINDOW_VALUE(window)) {
fw_debug_report_err(WWDGT_MODULE_ID, API_ID(0x0004U), ERR_PARAM_INVALID);
} else if(NOT_WWDGT_PSC_DIV(prescaler)) {
fw_debug_report_err(WWDGT_MODULE_ID, API_ID(0x0004U), ERR_PARAM_INVALID);
} else
#endif
{
WWDGT_CTL = (uint32_t)(CTL_CNT(counter));
WWDGT_CFG = (uint32_t)(CFG_WIN(window) | prescaler);
}
}
/*!
\brief enable early wakeup interrupt of WWDGT
\param[in] none
\param[out] none
\retval none
*/
void wwdgt_interrupt_enable(void)
{
WWDGT_CFG |= WWDGT_CFG_EWIE;
}
/*!
\brief check early wakeup interrupt state of WWDGT
\param[in] none
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus wwdgt_flag_get(void)
{
if (RESET != (WWDGT_STAT & WWDGT_STAT_EWIF)){
return SET;
}
return RESET;
}
/*!
\brief clear early wakeup interrupt state of WWDGT
\param[in] none
\param[out] none
\retval none
*/
void wwdgt_flag_clear(void)
{
WWDGT_STAT = (uint32_t)RESET;
}