Sync betaflight to Gitea

This commit is contained in:
2026-08-03 16:37:10 +08:00
commit ad3163cf91
4712 changed files with 3301380 additions and 0 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,127 @@
/*!
\file gd32f4xx_crc.c
\brief CRC driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_crc.h"
#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU)
#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U)
/*!
\brief deinit CRC calculation unit
\param[in] none
\param[out] none
\retval none
*/
void crc_deinit(void)
{
CRC_DATA = CRC_DATA_RESET_VALUE;
CRC_FDATA = CRC_FDATA_RESET_VALUE;
CRC_CTL = (uint32_t)CRC_CTL_RST;
}
/*!
\brief reset data register(CRC_DATA) to the value of 0xFFFFFFFF
\param[in] none
\param[out] none
\retval none
*/
void crc_data_register_reset(void)
{
CRC_CTL |= (uint32_t)CRC_CTL_RST;
}
/*!
\brief read the value of 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 value of 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 data to the free data register
\param[in] free_data: specified 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 calculate the CRC value of a 32-bit data
\param[in] sdata: specified 32-bit data
\param[out] none
\retval 32-bit value calculated by CRC
*/
uint32_t crc_single_data_calculate(uint32_t sdata)
{
CRC_DATA = sdata;
return (CRC_DATA);
}
/*!
\brief calculate the CRC value of an array of 32-bit values
\param[in] array: pointer to an array of 32-bit values
\param[in] size: size of the array
\param[out] none
\retval 32-bit value calculated by CRC
*/
uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size)
{
uint32_t index;
for(index = 0U; index < size; index++) {
CRC_DATA = array[index];
}
return (CRC_DATA);
}
@@ -0,0 +1,388 @@
/*!
\file gd32f4xx_ctc.c
\brief CTC driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_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] ctc_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)
{
/* 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)
{
CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM);
CTC_CTL0 |= (uint32_t)hardmode;
}
/*!
\brief configure reference signal source polarity
\param[in] polarity:
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)
{
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL);
CTC_CTL1 |= (uint32_t)polarity;
}
/*!
\brief select reference signal source
\param[in] refs:
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)
{
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL);
CTC_CTL1 |= (uint32_t)refs;
}
/*!
\brief configure reference signal source prescaler
\param[in] 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)
{
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 enable the CTC interrupt
\param[in] interrupt: CTC interrupt enable
one or more parameters can be selected which are shown as below:
\arg CTC_INT_CKOK: clock trim OK interrupt enable
\arg CTC_INT_CKWARN: clock trim warning interrupt enable
\arg CTC_INT_ERR: error interrupt enable
\arg CTC_INT_EREF: expect reference interrupt enable
\param[out] none
\retval none
*/
void ctc_interrupt_enable(uint32_t interrupt)
{
CTC_CTL0 |= (uint32_t)interrupt;
}
/*!
\brief disable 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 enable
\arg CTC_INT_CKWARN: clock trim warning interrupt enable
\arg CTC_INT_ERR: error interrupt enable
\arg CTC_INT_EREF: expect reference interrupt enable
\param[out] none
\retval none
*/
void ctc_interrupt_disable(uint32_t interrupt)
{
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
\arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
\arg CTC_INT_FLAG_ERR: error interrupt
\arg CTC_INT_FLAG_EREF: expect reference interrupt
\arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
\arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
\arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus ctc_interrupt_flag_get(uint32_t int_flag)
{
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) {
return SET;
} else {
return RESET;
}
}
/*!
\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
\arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
\arg CTC_INT_FLAG_ERR: error interrupt
\arg CTC_INT_FLAG_EREF: expect reference interrupt
\arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
\arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
\arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
\param[out] none
\retval none
*/
void ctc_interrupt_flag_clear(uint32_t int_flag)
{
if(RESET != (int_flag & CTC_FLAG_MASK)) {
CTC_INTC |= CTC_INTC_ERRIC;
} else {
CTC_INTC |= int_flag;
}
}
/*!
\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 bit
\arg CTC_FLAG_REFMISS: reference sync pulse miss
\arg CTC_FLAG_TRIMERR: trim value error bit
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus ctc_flag_get(uint32_t flag)
{
if(RESET != (CTC_STAT & flag)) {
return SET;
} else {
return RESET;
}
}
/*!
\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 bit
\arg CTC_FLAG_REFMISS: reference sync pulse miss
\arg CTC_FLAG_TRIMERR: trim value error bit
\param[out] none
\retval none
*/
void ctc_flag_clear(uint32_t flag)
{
if(RESET != (flag & CTC_FLAG_MASK)) {
CTC_INTC |= CTC_INTC_ERRIC;
} else {
CTC_INTC |= flag;
}
}
@@ -0,0 +1,678 @@
/*!
\file gd32f4xx_dac.c
\brief DAC driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_dac.h"
/* DAC register bit offset */
#define OUT1_REG_OFFSET ((uint32_t)0x00000010U)
#define DH_12BIT_OFFSET ((uint32_t)0x00000010U)
#define DH_8BIT_OFFSET ((uint32_t)0x00000008U)
#define DAC_STAT_FLAG_MASK0 (DAC_FLAG_DDUDR0 | DAC_FLAG_DDUDR1)
#define DAC_INT_EN_MASK0 (DAC_INT_DDUDR0 | DAC_INT_DDUDR1)
#define DAC_INT_FLAG_MASK0 (DAC_INT_FLAG_DDUDR0 | DAC_INT_FLAG_DDUDR1)
/*!
\brief deinitialize DAC
\param[in] dac_periph: DACx(x=0)
\param[out] none
\retval none
*/
void dac_deinit(uint32_t dac_periph)
{
switch(dac_periph){
case DAC0:
/* reset DAC0 */
rcu_periph_reset_enable(RCU_DACRST);
rcu_periph_reset_disable(RCU_DACRST);
break;
default:
break;
}
}
/*!
\brief enable DAC
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[out] none
\retval none
*/
void dac_enable(uint32_t dac_periph, uint8_t dac_out)
{
if(DAC_OUT0 == dac_out){
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DEN0;
}else if(DAC_OUT1 == dac_out){
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DEN1;
}else{
/* illegal parameters */
}
}
/*!
\brief disable DAC
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[out] none
\retval none
*/
void dac_disable(uint32_t dac_periph, uint8_t dac_out)
{
if(DAC_OUT0 == dac_out){
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DEN0);
}else if(DAC_OUT1 == dac_out){
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DEN1);
}else{
/* illegal parameters */
}
}
/*!
\brief enable DAC DMA function
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[out] none
\retval none
*/
void dac_dma_enable(uint32_t dac_periph, uint8_t dac_out)
{
if(DAC_OUT0 == dac_out){
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DDMAEN0;
}else if(DAC_OUT1 == dac_out){
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DDMAEN1;
}else{
/* illegal parameters */
}
}
/*!
\brief disable DAC DMA function
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[out] none
\retval none
*/
void dac_dma_disable(uint32_t dac_periph, uint8_t dac_out)
{
if(DAC_OUT0 == dac_out){
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DDMAEN0);
}else if(DAC_OUT1 == dac_out){
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DDMAEN1);
}else{
/* illegal parameters */
}
}
/*!
\brief enable DAC output buffer
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[out] none
\retval none
*/
void dac_output_buffer_enable(uint32_t dac_periph, uint8_t dac_out)
{
if(DAC_OUT0 == dac_out){
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DBOFF0);
}else if(DAC_OUT1 == dac_out){
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DBOFF1);
}else{
/* illegal parameters */
}
}
/*!
\brief disable DAC output buffer
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[out] none
\retval none
*/
void dac_output_buffer_disable(uint32_t dac_periph, uint8_t dac_out)
{
if(DAC_OUT0 == dac_out){
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DBOFF0;
}else if(DAC_OUT1 == dac_out){
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DBOFF1;
}else{
/* illegal parameters */
}
}
/*!
\brief get DAC output value
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[out] none
\retval DAC output data: 0~4095
*/
uint16_t dac_output_value_get(uint32_t dac_periph, uint8_t dac_out)
{
uint16_t data = 0U;
if(DAC_OUT0 == dac_out){
/* store the DACx_OUT0 output value */
data = (uint16_t)DAC_OUT0_DO(dac_periph);
}else if(DAC_OUT1 == dac_out){
/* store the DACx_OUT1 output value */
data = (uint16_t)DAC_OUT1_DO(dac_periph);
}else{
/* illegal parameters */
}
return data;
}
/*!
\brief set DAC data holding register value
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[in] dac_align: DAC data alignment mode
only one parameter can be selected which is shown as below:
\arg DAC_ALIGN_12B_R: 12-bit right-aligned data
\arg DAC_ALIGN_12B_L: 12-bit left-aligned data
\arg DAC_ALIGN_8B_R: 8-bit right-aligned data
\param[in] data: data to be loaded(0~4095)
\param[out] none
\retval none
*/
void dac_data_set(uint32_t dac_periph, uint8_t dac_out, uint32_t dac_align, uint16_t data)
{
/* DAC_OUT0 data alignment */
if(DAC_OUT0 == dac_out){
switch(dac_align){
/* 12-bit right-aligned data */
case DAC_ALIGN_12B_R:
DAC_OUT0_R12DH(dac_periph) = data;
break;
/* 12-bit left-aligned data */
case DAC_ALIGN_12B_L:
DAC_OUT0_L12DH(dac_periph) = data;
break;
/* 8-bit right-aligned data */
case DAC_ALIGN_8B_R:
DAC_OUT0_R8DH(dac_periph) = data;
break;
default:
break;
}
}else if(DAC_OUT1 == dac_out){
/* DAC_OUT1 data alignment */
switch(dac_align){
/* 12-bit right-aligned data */
case DAC_ALIGN_12B_R:
DAC_OUT1_R12DH(dac_periph) = data;
break;
/* 12-bit left-aligned data */
case DAC_ALIGN_12B_L:
DAC_OUT1_L12DH(dac_periph) = data;
break;
/* 8-bit right-aligned data */
case DAC_ALIGN_8B_R:
DAC_OUT1_R8DH(dac_periph) = data;
break;
default:
break;
}
}else{
/* illegal parameters */
}
}
/*!
\brief enable DAC trigger
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[out] none
\retval none
*/
void dac_trigger_enable(uint32_t dac_periph, uint8_t dac_out)
{
if(DAC_OUT0 == dac_out){
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DTEN0;
}else if(DAC_OUT1 == dac_out){
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DTEN1;
}else{
/* illegal parameters */
}
}
/*!
\brief disable DAC trigger
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[out] none
\retval none
*/
void dac_trigger_disable(uint32_t dac_periph, uint8_t dac_out)
{
if(DAC_OUT0 == dac_out){
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTEN0);
}else if(DAC_OUT1 == dac_out){
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTEN1);
}else{
/* illegal parameters */
}
}
/*!
\brief configure DAC trigger source
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[in] triggersource: external trigger of DAC
only one parameter can be selected which is shown as below:
\arg DAC_TRIGGER_T1_TRGO: TIMER1 TRGO
\arg DAC_TRIGGER_T3_TRGO: TIMER3 TRGO
\arg DAC_TRIGGER_T4_TRGO: TIMER4 TRGO
\arg DAC_TRIGGER_T5_TRGO: TIMER5 TRGO
\arg DAC_TRIGGER_T6_TRGO: TIMER6 TRGO
\arg DAC_TRIGGER_T7_TRGO: TIMER7 TRGO
\arg DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event
\arg DAC_TRIGGER_SOFTWARE: software trigger
\param[out] none
\retval none
*/
void dac_trigger_source_config(uint32_t dac_periph, uint8_t dac_out, uint32_t triggersource)
{
if(DAC_OUT0 == dac_out){
/* configure DACx_OUT0 trigger source */
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTSEL0);
DAC_CTL0(dac_periph) |= triggersource;
}else if(DAC_OUT1 == dac_out){
/* configure DACx_OUT1 trigger source */
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTSEL1);
DAC_CTL0(dac_periph) |= (triggersource << OUT1_REG_OFFSET);
}else{
/* illegal parameters */
}
}
/*!
\brief enable DAC software trigger
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\retval none
*/
void dac_software_trigger_enable(uint32_t dac_periph, uint8_t dac_out)
{
if(DAC_OUT0 == dac_out){
DAC_SWT(dac_periph) |= (uint32_t)DAC_SWT_SWTR0;
}else if(DAC_OUT1 == dac_out){
DAC_SWT(dac_periph) |= (uint32_t)DAC_SWT_SWTR1;
}else{
/* illegal parameters */
}
}
/*!
\brief configure DAC wave mode
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[in] wave_mode: DAC wave mode
only one parameter can be selected which is shown as below:
\arg DAC_WAVE_DISABLE: wave mode disable
\arg DAC_WAVE_MODE_LFSR: LFSR noise mode
\arg DAC_WAVE_MODE_TRIANGLE: triangle noise mode
\param[out] none
\retval none
*/
void dac_wave_mode_config(uint32_t dac_periph, uint8_t dac_out, uint32_t wave_mode)
{
if(DAC_OUT0 == dac_out){
/* configure DACx_OUT0 wave mode */
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWM0);
DAC_CTL0(dac_periph) |= wave_mode;
}else if(DAC_OUT1 == dac_out){
/* configure DACx_OUT1 wave mode */
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWM1);
DAC_CTL0(dac_periph) |= (wave_mode << OUT1_REG_OFFSET);
}else{
/* illegal parameters */
}
}
/*!
\brief configure DAC LFSR noise mode
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[in] unmask_bits: LFSR noise unmask bits
only one parameter can be selected which is shown as below:
\arg DAC_LFSR_BIT0: unmask the LFSR bit0
\arg DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0]
\arg DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0]
\arg DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0]
\arg DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0]
\arg DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0]
\arg DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0]
\arg DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0]
\arg DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0]
\arg DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0]
\arg DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0]
\arg DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0]
\param[out] none
\retval none
*/
void dac_lfsr_noise_config(uint32_t dac_periph, uint8_t dac_out, uint32_t unmask_bits)
{
if(DAC_OUT0 == dac_out){
/* configure DACx_OUT0 LFSR noise mode */
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW0);
DAC_CTL0(dac_periph) |= unmask_bits;
}else if(DAC_OUT1 == dac_out){
/* configure DACx_OUT1 LFSR noise mode */
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW1);
DAC_CTL0(dac_periph) |= (unmask_bits << OUT1_REG_OFFSET);
}else{
/* illegal parameters */
}
}
/*!
\brief configure DAC triangle noise mode
\param[in] dac_periph: DACx(x=0)
\param[in] dac_out: DAC_OUTx(x=0,1)
\param[in] amplitude: the amplitude of the triangle
only one parameter can be selected which is shown as below:
\arg DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1
\arg DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3
\arg DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7
\arg DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15
\arg DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31
\arg DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63
\arg DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127
\arg DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255
\arg DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511
\arg DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023
\arg DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047
\arg DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095
\param[out] none
\retval none
*/
void dac_triangle_noise_config(uint32_t dac_periph, uint8_t dac_out, uint32_t amplitude)
{
if(DAC_OUT0 == dac_out){
/* configure DACx_OUT0 triangle noise mode */
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW0);
DAC_CTL0(dac_periph) |= amplitude;
}else if(DAC_OUT1 == dac_out){
/* configure DACx_OUT1 triangle noise mode */
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW1);
DAC_CTL0(dac_periph) |= (amplitude << OUT1_REG_OFFSET);
}else{
/* illegal parameters */
}
}
/*!
\brief enable DAC concurrent mode
\param[in] dac_periph: DACx(x=0)
\param[out] none
\retval none
*/
void dac_concurrent_enable(uint32_t dac_periph)
{
uint32_t ctl = 0U;
ctl = (uint32_t)(DAC_CTL0_DEN0 | DAC_CTL0_DEN1);
DAC_CTL0(dac_periph) |= (uint32_t)ctl;
}
/*!
\brief disable DAC concurrent mode
\param[in] dac_periph: DACx(x=0)
\param[out] none
\retval none
*/
void dac_concurrent_disable(uint32_t dac_periph)
{
uint32_t ctl = 0U;
ctl = (uint32_t)(DAC_CTL0_DEN0 | DAC_CTL0_DEN1);
DAC_CTL0(dac_periph) &= (uint32_t)(~ctl);
}
/*!
\brief enable DAC concurrent software trigger
\param[in] dac_periph: DACx(x=0)
\param[out] none
\retval none
*/
void dac_concurrent_software_trigger_enable(uint32_t dac_periph)
{
uint32_t swt = 0U;
swt = (uint32_t)(DAC_SWT_SWTR0 | DAC_SWT_SWTR1);
DAC_SWT(dac_periph) |= (uint32_t)swt;
}
/*!
\brief enable DAC concurrent buffer function
\param[in] dac_periph: DACx(x=0)
\param[out] none
\retval none
*/
void dac_concurrent_output_buffer_enable(uint32_t dac_periph)
{
uint32_t ctl = 0U;
ctl = (uint32_t)(DAC_CTL0_DBOFF0 | DAC_CTL0_DBOFF1);
DAC_CTL0(dac_periph) &= (uint32_t)(~ctl);
}
/*!
\brief disable DAC concurrent buffer function
\param[in] dac_periph: DACx(x=0)
\param[out] none
\retval none
*/
void dac_concurrent_output_buffer_disable(uint32_t dac_periph)
{
uint32_t ctl = 0U;
ctl = (uint32_t)(DAC_CTL0_DBOFF0 | DAC_CTL0_DBOFF1);
DAC_CTL0(dac_periph) |= (uint32_t)ctl;
}
/*!
\brief set DAC concurrent mode data holding register value
\param[in] dac_periph: DACx(x=0)
\param[in] dac_align: DAC data alignment mode
only one parameter can be selected which is shown as below:
\arg DAC_ALIGN_12B_R: 12-bit right-aligned data
\arg DAC_ALIGN_12B_L: 12-bit left-aligned data
\arg DAC_ALIGN_8B_R: 8-bit right-aligned data
\param[in] data0: data to be loaded(0~4095)
\param[in] data1: data to be loaded(0~4095)
\param[out] none
\retval none
*/
void dac_concurrent_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data0, uint16_t data1)
{
uint32_t data = 0U;
switch(dac_align){
/* 12-bit right-aligned data */
case DAC_ALIGN_12B_R:
data = (uint32_t)(((uint32_t)data1 << DH_12BIT_OFFSET) | data0);
DACC_R12DH(dac_periph) = (uint32_t)data;
break;
/* 12-bit left-aligned data */
case DAC_ALIGN_12B_L:
data = (uint32_t)(((uint32_t)data1 << DH_12BIT_OFFSET) | data0);
DACC_L12DH(dac_periph) = (uint32_t)data;
break;
/* 8-bit right-aligned data */
case DAC_ALIGN_8B_R:
data = (uint32_t)(((uint32_t)data1 << DH_8BIT_OFFSET) | data0);
DACC_R8DH(dac_periph) = (uint32_t)data;
break;
default:
break;
}
}
/*!
\brief get the DAC flag
\param[in] dac_periph: DACx(x=0)
\param[in] flag: the DAC status flags, only one parameter can be selected which is shown
as below:
\arg DAC_FLAG_DDUDR0: DACx_OUT0 DMA underrun flag
\arg DAC_FLAG_DDUDR1: DACx_OUT1 DMA underrun flag
\param[out] none
\retval the state of DAC bit(SET or RESET)
*/
FlagStatus dac_flag_get(uint32_t dac_periph, uint32_t flag)
{
if(flag & DAC_STAT_FLAG_MASK0){
/* check DAC_STAT0 flag */
if(RESET != (DAC_STAT0(dac_periph) & flag)){
return SET;
}else{
return RESET;
}
}else{
/* illegal parameters */
return RESET;
}
}
/*!
\brief clear the DAC flag
\param[in] dac_periph: DACx(x=0)
\param[in] flag: DAC flag
one or more parameter can be selected which are shown as below:
\arg DAC_FLAG_DDUDR0: DACx_OUT0 DMA underrun flag
\arg DAC_FLAG_DDUDR1: DACx_OUT1 DMA underrun flag
\param[out] none
\retval none
*/
void dac_flag_clear(uint32_t dac_periph, uint32_t flag)
{
if(flag & DAC_STAT_FLAG_MASK0){
/* check DAC_STAT0 flag */
DAC_STAT0(dac_periph) = (uint32_t)(flag & DAC_STAT_FLAG_MASK0);
}else{
/* illegal parameters */
}
}
/*!
\brief enable DAC interrupt(DAC DMA underrun interrupt)
\param[in] dac_periph: DACx(x=0)
\param[in] interrupt: the DAC interrupt
one or more parameter can be selected which are shown as below:
\arg DAC_INT_DDUDR0: DACx_OUT0 DMA underrun interrupt
\arg DAC_INT_DDUDR1: DACx_OUT1 DMA underrun interrupt
\param[out] none
\retval none
*/
void dac_interrupt_enable(uint32_t dac_periph, uint32_t interrupt)
{
if(interrupt & DAC_INT_EN_MASK0){
/* enable underrun interrupt */
DAC_CTL0(dac_periph) |= (uint32_t)(interrupt & DAC_INT_EN_MASK0);
}else{
/* illegal parameters */
}
}
/*!
\brief disable DAC interrupt(DAC DMA underrun interrupt)
\param[in] dac_periph: DACx(x=0)
\param[in] interrupt: the DAC interrupt
one and more parameter can be selected which are shown as below:
\arg DAC_INT_DDUDR0: DACx_OUT0 DMA underrun interrupt
\arg DAC_INT_DDUDR1: DACx_OUT1 DMA underrun interrupt
\param[out] none
\retval none
*/
void dac_interrupt_disable(uint32_t dac_periph, uint32_t interrupt)
{
if(interrupt & DAC_INT_EN_MASK0){
/* disable underrun interrupt */
DAC_CTL0(dac_periph) &= (uint32_t)(~(interrupt & DAC_INT_EN_MASK0));
}else{
/* illegal parameters */
}
}
/*!
\brief get the DAC interrupt flag(DAC DMA underrun interrupt flag)
\param[in] dac_periph: DACx(x=0)
\param[in] int_flag: DAC interrupt flag
only one parameter can be selected which is shown as below:
\arg DAC_INT_FLAG_DDUDR0: DACx_OUT0 DMA underrun interrupt flag
\arg DAC_INT_FLAG_DDUDR1: DACx_OUT1 DMA underrun interrupt flag
\param[out] none
\retval the state of DAC interrupt flag(SET or RESET)
*/
FlagStatus dac_interrupt_flag_get(uint32_t dac_periph, uint32_t int_flag)
{
uint32_t reg1 = 0U, reg2 = 0U;
if(int_flag & DAC_INT_FLAG_MASK0){
/* check underrun interrupt int_flag */
reg1 = DAC_STAT0(dac_periph) & int_flag;
reg2 = DAC_CTL0(dac_periph) & int_flag;
}else{
/* illegal parameters */
}
/*get DAC interrupt flag status */
if((RESET != reg1) && (RESET != reg2)){
return SET;
}else{
return RESET;
}
}
/*!
\brief clear the DAC interrupt flag(DAC DMA underrun interrupt flag)
\param[in] dac_periph: DACx(x=0)
\param[in] int_flag: DAC interrupt flag
one or more parameter can be selected which are shown as below:
\arg DAC_INT_FLAG_DDUDR0: DACx_OUT0 DMA underrun interrupt flag
\arg DAC_INT_FLAG_DDUDR1: DACx_OUT1 DMA underrun interrupt flag
\param[out] none
\retval none
*/
void dac_interrupt_flag_clear(uint32_t dac_periph, uint32_t int_flag)
{
/* clear underrun interrupt int_flag */
if(int_flag & DAC_INT_FLAG_MASK0){
DAC_STAT0(dac_periph) = (uint32_t)(int_flag & DAC_INT_FLAG_MASK0);
}else{
/* illegal parameters */
}
}
@@ -0,0 +1,180 @@
/*!
\file gd32f4xx_dbg.c
\brief DBG driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_dbg.h"
#define DBG_RESET_VAL 0x00000000U
/*!
\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;
}
/*!
\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:
this parameter can be any combination of the following values:
\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)
{
DBG_CTL0 |= dbg_low_power;
}
/*!
\brief disable low power behavior when the mcu is in debug mode
\param[in] dbg_low_power:
this parameter can be any combination of the following values:
\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)
{
DBG_CTL0 &= ~dbg_low_power;
}
/*!
\brief enable peripheral behavior when the mcu is in debug mode
\param[in] dbg_periph: dbg_periph_enum
only one parameter can be selected which is shown as below:
\arg DBG_TIMER1_HOLD: hold TIMER1 counter when core is halted
\arg DBG_TIMER2_HOLD: hold TIMER2 counter when core is halted
\arg DBG_TIMER3_HOLD: hold TIMER3 counter when core is halted
\arg DBG_TIMER4_HOLD: hold TIMER4 counter when core is halted
\arg DBG_TIMER5_HOLD: hold TIMER5 counter when core is halted
\arg DBG_TIMER6_HOLD: hold TIMER6 counter when core is halted
\arg DBG_TIMER11_HOLD: hold TIMER11 counter when core is halted
\arg DBG_TIMER12_HOLD: hold TIMER12 counter when core is halted
\arg DBG_TIMER13_HOLD: hold TIMER13 counter when core is halted
\arg DBG_RTC_HOLD: hold RTC calendar and wakeup counter when core is halted
\arg DBG_WWDGT_HOLD: debug WWDGT kept when core is halted
\arg DBG_FWDGT_HOLD: debug FWDGT kept when core is halted
\arg DBG_I2C0_HOLD: hold I2C0 smbus when core is halted
\arg DBG_I2C1_HOLD: hold I2C1 smbus when core is halted
\arg DBG_I2C2_HOLD: hold I2C2 smbus when core is halted
\arg DBG_CAN0_HOLD: debug CAN0 kept when core is halted
\arg DBG_CAN1_HOLD: debug CAN1 kept when core is halted
\arg DBG_TIMER0_HOLD: hold TIMER0 counter when core is halted
\arg DBG_TIMER7_HOLD: hold TIMER7 counter when core is halted
\arg DBG_TIMER8_HOLD: hold TIMER8 counter when core is halted
\arg DBG_TIMER9_HOLD: hold TIMER9 counter when core is halted
\arg DBG_TIMER10_HOLD: hold TIMER10 counter when core is halted
\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: dbg_periph_enum
only one parameter can be selected which is shown as below:
\arg DBG_TIMER1_HOLD: hold TIMER1 counter when core is halted
\arg DBG_TIMER2_HOLD: hold TIMER2 counter when core is halted
\arg DBG_TIMER3_HOLD: hold TIMER3 counter when core is halted
\arg DBG_TIMER4_HOLD: hold TIMER4 counter when core is halted
\arg DBG_TIMER5_HOLD: hold TIMER5 counter when core is halted
\arg DBG_TIMER6_HOLD: hold TIMER6 counter when core is halted
\arg DBG_TIMER11_HOLD: hold TIMER11 counter when core is halted
\arg DBG_TIMER12_HOLD: hold TIMER12 counter when core is halted
\arg DBG_TIMER13_HOLD: hold TIMER13 counter when core is halted
\arg DBG_RTC_HOLD: hold RTC calendar and wakeup counter when core is halted
\arg DBG_WWDGT_HOLD: debug WWDGT kept when core is halted
\arg DBG_FWDGT_HOLD: debug FWDGT kept when core is halted
\arg DBG_I2C0_HOLD: hold I2C0 smbus when core is halted
\arg DBG_I2C1_HOLD: hold I2C1 smbus when core is halted
\arg DBG_I2C2_HOLD: hold I2C2 smbus when core is halted
\arg DBG_CAN0_HOLD: debug CAN0 kept when core is halted
\arg DBG_CAN1_HOLD: debug CAN1 kept when core is halted
\arg DBG_TIMER0_HOLD: hold TIMER0 counter when core is halted
\arg DBG_TIMER7_HOLD: hold TIMER7 counter when core is halted
\arg DBG_TIMER8_HOLD: hold TIMER8 counter when core is halted
\arg DBG_TIMER9_HOLD: hold TIMER9 counter when core is halted
\arg DBG_TIMER10_HOLD: hold TIMER10 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));
}
/*!
\brief enable trace pin assignment
\param[in] none
\param[out] none
\retval none
*/
void dbg_trace_pin_enable(void)
{
DBG_CTL0 |= DBG_CTL0_TRACE_IOEN;
}
/*!
\brief disable trace pin assignment
\param[in] none
\param[out] none
\retval none
*/
void dbg_trace_pin_disable(void)
{
DBG_CTL0 &= ~DBG_CTL0_TRACE_IOEN;
}
@@ -0,0 +1,343 @@
/*!
\file gd32f4xx_dci.c
\brief DCI driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_dci.h"
/*!
\brief DCI deinit
\param[in] none
\param[out] none
\retval none
*/
void dci_deinit(void)
{
rcu_periph_reset_enable(RCU_DCIRST);
rcu_periph_reset_disable(RCU_DCIRST);
}
/*!
\brief initialize DCI registers
\param[in] dci_struct: DCI parameter initialization structure
members of the structure and the member values are shown as below:
capture_mode : DCI_CAPTURE_MODE_CONTINUOUS, DCI_CAPTURE_MODE_SNAPSHOT
clock_polarity : DCI_CK_POLARITY_FALLING, DCI_CK_POLARITY_RISING
hsync_polarity : DCI_HSYNC_POLARITY_LOW, DCI_HSYNC_POLARITY_HIGH
vsync_polarity : DCI_VSYNC_POLARITY_LOW, DCI_VSYNC_POLARITY_HIGH
frame_rate : DCI_FRAME_RATE_ALL, DCI_FRAME_RATE_1_2, DCI_FRAME_RATE_1_4
interface_format: DCI_INTERFACE_FORMAT_8BITS, DCI_INTERFACE_FORMAT_10BITS,
DCI_INTERFACE_FORMAT_12BITS, DCI_INTERFACE_FORMAT_14BITS
\param[out] none
\retval none
*/
void dci_init(dci_parameter_struct *dci_struct)
{
uint32_t reg = 0U;
/* disable capture function and DCI */
DCI_CTL &= ~(DCI_CTL_CAP | DCI_CTL_DCIEN);
/* configure DCI parameter */
reg |= dci_struct->capture_mode;
reg |= dci_struct->clock_polarity;
reg |= dci_struct->hsync_polarity;
reg |= dci_struct->vsync_polarity;
reg |= dci_struct->frame_rate;
reg |= dci_struct->interface_format;
DCI_CTL = reg;
}
/*!
\brief enable DCI function
\param[in] none
\param[out] none
\retval none
*/
void dci_enable(void)
{
DCI_CTL |= DCI_CTL_DCIEN;
}
/*!
\brief disable DCI function
\param[in] none
\param[out] none
\retval none
*/
void dci_disable(void)
{
DCI_CTL &= ~DCI_CTL_DCIEN;
}
/*!
\brief enable DCI capture
\param[in] none
\param[out] none
\retval none
*/
void dci_capture_enable(void)
{
DCI_CTL |= DCI_CTL_CAP;
}
/*!
\brief disable DCI capture
\param[in] none
\param[out] none
\retval none
*/
void dci_capture_disable(void)
{
DCI_CTL &= ~DCI_CTL_CAP;
}
/*!
\brief enable DCI jpeg mode
\param[in] none
\param[out] none
\retval none
*/
void dci_jpeg_enable(void)
{
DCI_CTL |= DCI_CTL_JM;
}
/*!
\brief disable DCI jpeg mode
\param[in] none
\param[out] none
\retval none
*/
void dci_jpeg_disable(void)
{
DCI_CTL &= ~DCI_CTL_JM;
}
/*!
\brief enable cropping window function
\param[in] none
\param[out] none
\retval none
*/
void dci_crop_window_enable(void)
{
DCI_CTL |= DCI_CTL_WDEN;
}
/*!
\brief disable cropping window function
\param[in] none
\param[out] none
\retval none
*/
void dci_crop_window_disable(void)
{
DCI_CTL &= ~DCI_CTL_WDEN;
}
/*!
\brief configure DCI cropping window
\param[in] start_x: window horizontal start position
\param[in] start_y: window vertical start position
\param[in] size_width: window horizontal size
\param[in] size_height: window vertical size
\param[out] none
\retval none
*/
void dci_crop_window_config(uint16_t start_x, uint16_t start_y, uint16_t size_width, uint16_t size_height)
{
DCI_CWSPOS = ((uint32_t)start_x | ((uint32_t)start_y << 16));
DCI_CWSZ = ((uint32_t)size_width | ((uint32_t)size_height << 16));
}
/*!
\brief enable embedded synchronous mode
\param[in] none
\param[out] none
\retval none
*/
void dci_embedded_sync_enable(void)
{
DCI_CTL |= DCI_CTL_ESM;
}
/*!
\brief disble embedded synchronous mode
\param[in] none
\param[out] none
\retval none
*/
void dci_embedded_sync_disable(void)
{
DCI_CTL &= ~DCI_CTL_ESM;
}
/*!
\brief config synchronous codes in embedded synchronous mode
\param[in] frame_start: frame start code in embedded synchronous mode
\param[in] line_start: line start code in embedded synchronous mode
\param[in] line_end: line end code in embedded synchronous mode
\param[in] frame_end: frame end code in embedded synchronous mode
\param[out] none
\retval none
*/
void dci_sync_codes_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end)
{
DCI_SC = ((uint32_t)frame_start | ((uint32_t)line_start << 8) | ((uint32_t)line_end << 16) | ((uint32_t)frame_end << 24));
}
/*!
\brief config synchronous codes unmask in embedded synchronous mode
\param[in] frame_start: frame start code unmask bits in embedded synchronous mode
\param[in] line_start: line start code unmask bits in embedded synchronous mode
\param[in] line_end: line end code unmask bits in embedded synchronous mode
\param[in] frame_end: frame end code unmask bits in embedded synchronous mode
\param[out] none
\retval none
*/
void dci_sync_codes_unmask_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end)
{
DCI_SCUMSK = ((uint32_t)frame_start | ((uint32_t)line_start << 8) | ((uint32_t)line_end << 16) | ((uint32_t)frame_end << 24));
}
/*!
\brief read DCI data register
\param[in] none
\param[out] none
\retval data
*/
uint32_t dci_data_read(void)
{
return DCI_DATA;
}
/*!
\brief get specified flag
\param[in] flag:
\arg DCI_FLAG_HS: HS line status
\arg DCI_FLAG_VS: VS line status
\arg DCI_FLAG_FV:FIFO valid
\arg DCI_FLAG_EF: end of frame flag
\arg DCI_FLAG_OVR: FIFO overrun flag
\arg DCI_FLAG_ESE: embedded synchronous error flag
\arg DCI_FLAG_VSYNC: vsync flag
\arg DCI_FLAG_EL: end of line flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus dci_flag_get(uint32_t flag)
{
uint32_t stat = 0U;
if(flag >> 31) {
/* get flag status from DCI_STAT1 register */
stat = DCI_STAT1;
} else {
/* get flag status from DCI_STAT0 register */
stat = DCI_STAT0;
}
if(flag & stat) {
return SET;
} else {
return RESET;
}
}
/*!
\brief enable specified DCI interrupt
\param[in] interrupt:
\arg DCI_INT_EF: end of frame interrupt
\arg DCI_INT_OVR: FIFO overrun interrupt
\arg DCI_INT_ESE: embedded synchronous error interrupt
\arg DCI_INT_VSYNC: vsync interrupt
\arg DCI_INT_EL: end of line interrupt
\param[out] none
\retval none
*/
void dci_interrupt_enable(uint32_t interrupt)
{
DCI_INTEN |= interrupt;
}
/*!
\brief disable specified DCI interrupt
\param[in] interrupt:
\arg DCI_INT_EF: end of frame interrupt
\arg DCI_INT_OVR: FIFO overrun interrupt
\arg DCI_INT_ESE: embedded synchronous error interrupt
\arg DCI_INT_VSYNC: vsync interrupt
\arg DCI_INT_EL: end of line interrupt
\param[out] none
\retval none
*/
void dci_interrupt_disable(uint32_t interrupt)
{
DCI_INTEN &= ~interrupt;
}
/*!
\brief clear specified interrupt flag
\param[in] int_flag:
\arg DCI_INT_EF: end of frame interrupt
\arg DCI_INT_OVR: FIFO overrun interrupt
\arg DCI_INT_ESE: embedded synchronous error interrupt
\arg DCI_INT_VSYNC: vsync interrupt
\arg DCI_INT_EL: end of line interrupt
\param[out] none
\retval none
*/
void dci_interrupt_flag_clear(uint32_t int_flag)
{
DCI_INTC |= int_flag;
}
/*!
\brief get specified interrupt flag
\param[in] int_flag:
\arg DCI_INT_FLAG_EF: end of frame interrupt flag
\arg DCI_INT_FLAG_OVR: FIFO overrun interrupt flag
\arg DCI_INT_FLAG_ESE: embedded synchronous error interrupt flag
\arg DCI_INT_FLAG_VSYNC: vsync interrupt flag
\arg DCI_INT_FLAG_EL: end of line interrupt flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus dci_interrupt_flag_get(uint32_t int_flag)
{
if(RESET == (DCI_INTF & int_flag)) {
return RESET;
} else {
return SET;
}
}
@@ -0,0 +1,911 @@
/*!
\file gd32f4xx_dma.c
\brief DMA driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_dma.h"
/* DMA register bit offset */
#define CHXCTL_PERIEN_OFFSET ((uint32_t)25U)
/*!
\brief deinitialize DMA a channel registers
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel is deinitialized
\arg DMA_CHx(x=0..7)
\param[out] none
\retval none
*/
void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx)
{
/* disable DMA a channel */
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
/* reset DMA channel registers */
DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE;
DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE;
DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE;
DMA_CHM0ADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
DMA_CHM1ADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
DMA_CHFCTL(dma_periph, channelx) = DMA_CHFCTL_RESET_VALUE;
if(channelx < DMA_CH4) {
DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
} else {
channelx -= (dma_channel_enum)4;
DMA_INTC1(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
}
}
/*!
\brief initialize the DMA single data mode parameters struct with the default values
\param[in] init_struct: the initialization data needed to initialize DMA channel
\param[out] none
\retval none
*/
void dma_single_data_para_struct_init(dma_single_data_parameter_struct *init_struct)
{
/* set the DMA struct with the default values */
init_struct->periph_addr = 0U;
init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE;
init_struct->memory0_addr = 0U;
init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE;
init_struct->periph_memory_width = 0U;
init_struct->circular_mode = DMA_CIRCULAR_MODE_DISABLE;
init_struct->direction = DMA_PERIPH_TO_MEMORY;
init_struct->number = 0U;
init_struct->priority = DMA_PRIORITY_LOW;
}
/*!
\brief initialize the DMA multi data mode parameters struct with the default values
\param[in] init_struct: the initialization data needed to initialize DMA channel
\param[out] none
\retval none
*/
void dma_multi_data_para_struct_init(dma_multi_data_parameter_struct *init_struct)
{
/* set the DMA struct with the default values */
init_struct->periph_addr = 0U;
init_struct->periph_width = 0U;
init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE;
init_struct->memory0_addr = 0U;
init_struct->memory_width = 0U;
init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE;
init_struct->memory_burst_width = 0U;
init_struct->periph_burst_width = 0U;
init_struct->circular_mode = DMA_CIRCULAR_MODE_DISABLE;
init_struct->direction = DMA_PERIPH_TO_MEMORY;
init_struct->number = 0U;
init_struct->priority = DMA_PRIORITY_LOW;
}
/*!
\brief initialize DMA single data mode
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel is initialized
\arg DMA_CHx(x=0..7)
\param[in] init_struct: the data needed to initialize DMA single data mode
periph_addr: peripheral base address
periph_inc: DMA_PERIPH_INCREASE_ENABLE,DMA_PERIPH_INCREASE_DISABLE,DMA_PERIPH_INCREASE_FIX
memory0_addr: memory base address
memory_inc: DMA_MEMORY_INCREASE_ENABLE,DMA_MEMORY_INCREASE_DISABLE
periph_memory_width: DMA_PERIPH_WIDTH_8BIT,DMA_PERIPH_WIDTH_16BIT,DMA_PERIPH_WIDTH_32BIT
circular_mode: DMA_CIRCULAR_MODE_ENABLE,DMA_CIRCULAR_MODE_DISABLE
direction: DMA_PERIPH_TO_MEMORY,DMA_MEMORY_TO_PERIPH,DMA_MEMORY_TO_MEMORY
number: the number of remaining data to be transferred by the DMA
priority: DMA_PRIORITY_LOW,DMA_PRIORITY_MEDIUM,DMA_PRIORITY_HIGH,DMA_PRIORITY_ULTRA_HIGH
\param[out] none
\retval none
*/
void dma_single_data_mode_init(uint32_t dma_periph, dma_channel_enum channelx, dma_single_data_parameter_struct *init_struct)
{
uint32_t ctl;
/* select single data mode */
DMA_CHFCTL(dma_periph, channelx) &= ~DMA_CHXFCTL_MDMEN;
/* configure peripheral base address */
DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
/* configure memory base address */
DMA_CHM0ADDR(dma_periph, channelx) = init_struct->memory0_addr;
/* configure the number of remaining data to be transferred */
DMA_CHCNT(dma_periph, channelx) = init_struct->number;
/* configure peripheral and memory transfer width,channel priotity,transfer mode */
ctl = DMA_CHCTL(dma_periph, channelx);
ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO | DMA_CHXCTL_TM);
ctl |= (init_struct->periph_memory_width | (init_struct->periph_memory_width << 2) | init_struct->priority | init_struct->direction);
DMA_CHCTL(dma_periph, channelx) = ctl;
/* configure peripheral increasing mode */
if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc) {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
} else if(DMA_PERIPH_INCREASE_DISABLE == init_struct->periph_inc) {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
} else {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PAIF;
}
/* configure memory increasing mode */
if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc) {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
} else {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
}
/* configure DMA circular mode */
if(DMA_CIRCULAR_MODE_ENABLE == init_struct->circular_mode) {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
} else {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
}
}
/*!
\brief initialize DMA multi data mode
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel is initialized
\arg DMA_CHx(x=0..7)
\param[in] dma_multi_data_parameter_struct: the data needed to initialize DMA multi data mode
periph_addr: peripheral base address
periph_width: DMA_PERIPH_WIDTH_8BIT,DMA_PERIPH_WIDTH_16BIT,DMA_PERIPH_WIDTH_32BIT
periph_inc: DMA_PERIPH_INCREASE_ENABLE,DMA_PERIPH_INCREASE_DISABLE,DMA_PERIPH_INCREASE_FIX
memory0_addr: memory0 base address
memory_width: DMA_MEMORY_WIDTH_8BIT,DMA_MEMORY_WIDTH_16BIT,DMA_MEMORY_WIDTH_32BIT
memory_inc: DMA_MEMORY_INCREASE_ENABLE,DMA_MEMORY_INCREASE_DISABLE
memory_burst_width: DMA_MEMORY_BURST_SINGLE,DMA_MEMORY_BURST_4_BEAT,DMA_MEMORY_BURST_8_BEAT,DMA_MEMORY_BURST_16_BEAT
periph_burst_width: DMA_PERIPH_BURST_SINGLE,DMA_PERIPH_BURST_4_BEAT,DMA_PERIPH_BURST_8_BEAT,DMA_PERIPH_BURST_16_BEAT
critical_value: DMA_FIFO_1_WORD,DMA_FIFO_2_WORD,DMA_FIFO_3_WORD,DMA_FIFO_4_WORD
circular_mode: DMA_CIRCULAR_MODE_ENABLE,DMA_CIRCULAR_MODE_DISABLE
direction: DMA_PERIPH_TO_MEMORY,DMA_MEMORY_TO_PERIPH,DMA_MEMORY_TO_MEMORY
number: the number of remaining data to be transferred by the DMA
priority: DMA_PRIORITY_LOW,DMA_PRIORITY_MEDIUM,DMA_PRIORITY_HIGH,DMA_PRIORITY_ULTRA_HIGH
\param[out] none
\retval none
*/
void dma_multi_data_mode_init(uint32_t dma_periph, dma_channel_enum channelx, dma_multi_data_parameter_struct *init_struct)
{
uint32_t ctl;
#if 0
/* select multi data mode and configure FIFO critical value */
DMA_CHFCTL(dma_periph, channelx) |= (DMA_CHXFCTL_MDMEN | init_struct->critical_value);
#else
// /* select multi data mode and configure FIFO critical value */
// DMA_CHFCTL(dma_periph, channelx) |= init_struct->critical_value;
// DMA_CHFCTL(dma_periph, channelx)|= DMA_CHXFCTL_MDMEN;
ctl = DMA_CHFCTL(dma_periph, channelx);
ctl &= ~(DMA_FIFO_4_WORD | DMA_CHXFCTL_MDMEN);
ctl |= init_struct->critical_value;
DMA_CHFCTL(dma_periph, channelx) = ctl;
DMA_CHFCTL(dma_periph, channelx)|= DMA_CHXFCTL_MDMEN;
#endif
/* configure peripheral base address */
DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
/* configure memory base address */
DMA_CHM0ADDR(dma_periph, channelx) = init_struct->memory0_addr;
/* configure the number of remaining data to be transferred */
DMA_CHCNT(dma_periph, channelx) = init_struct->number;
/* configure peripheral and memory transfer width,channel priotity,transfer mode,peripheral and memory burst transfer width */
ctl = DMA_CHCTL(dma_periph, channelx);
ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO | DMA_CHXCTL_TM | DMA_CHXCTL_PBURST | DMA_CHXCTL_MBURST);
ctl |= (init_struct->periph_width | (init_struct->memory_width) | init_struct->priority | init_struct->direction | init_struct->memory_burst_width |
init_struct->periph_burst_width);
DMA_CHCTL(dma_periph, channelx) = ctl;
/* configure peripheral increasing mode */
if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc) {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
} else if(DMA_PERIPH_INCREASE_DISABLE == init_struct->periph_inc) {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
} else {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PAIF;
}
/* configure memory increasing mode */
if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc) {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
} else {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
}
/* configure DMA circular mode */
if(DMA_CIRCULAR_MODE_ENABLE == init_struct->circular_mode) {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
} else {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
}
}
/*!
\brief set DMA peripheral base address
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel to set peripheral base address
\arg DMA_CHx(x=0..7)
\param[in] address: peripheral base address
\param[out] none
\retval none
*/
void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
{
DMA_CHPADDR(dma_periph, channelx) = address;
}
/*!
\brief set DMA Memory0 base address
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel to set Memory base address
\arg DMA_CHx(x=0..7)
\param[in] memory_flag: DMA_MEMORY_x(x=0,1)
\param[in] address: Memory base address
\param[out] none
\retval none
*/
void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t memory_flag, uint32_t address)
{
if(memory_flag) {
DMA_CHM1ADDR(dma_periph, channelx) = address;
} else {
DMA_CHM0ADDR(dma_periph, channelx) = address;
}
}
/*!
\brief set the number of remaining data to be transferred by the DMA
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel to set number
\arg DMA_CHx(x=0..7)
\param[in] number: the number of remaining data to be transferred by the DMA
\param[out] none
\retval none
*/
void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number)
{
DMA_CHCNT(dma_periph, channelx) = number;
}
/*!
\brief get the number of remaining data to be transferred by the DMA
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel to set number
\arg DMA_CHx(x=0..7)
\param[out] none
\retval uint32_t: the number of remaining data to be transferred by the DMA
*/
uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
{
return (uint32_t)DMA_CHCNT(dma_periph, channelx);
}
/*!
\brief configure priority level of DMA channel
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] priority: priority Level of this channel
only one parameter can be selected which is shown as below:
\arg DMA_PRIORITY_LOW: low priority
\arg DMA_PRIORITY_MEDIUM: medium priority
\arg DMA_PRIORITY_HIGH: high priority
\arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority
\param[out] none
\retval none
*/
void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority)
{
uint32_t ctl;
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_PRIO;
ctl |= priority;
DMA_CHCTL(dma_periph, channelx) = ctl;
}
/*!
\brief configure transfer burst beats of memory
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] mbeat: transfer burst beats
\arg DMA_MEMORY_BURST_SINGLE: memory transfer single burst
\arg DMA_MEMORY_BURST_4_BEAT: memory transfer 4-beat burst
\arg DMA_MEMORY_BURST_8_BEAT: memory transfer 8-beat burst
\arg DMA_MEMORY_BURST_16_BEAT: memory transfer 16-beat burst
\param[out] none
\retval none
*/
void dma_memory_burst_beats_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mbeat)
{
uint32_t ctl;
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_MBURST;
ctl |= mbeat;
DMA_CHCTL(dma_periph, channelx) = ctl;
}
/*!
\brief configure transfer burst beats of peripheral
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] pbeat: transfer burst beats
only one parameter can be selected which is shown as below:
\arg DMA_PERIPH_BURST_SINGLE: peripheral transfer single burst
\arg DMA_PERIPH_BURST_4_BEAT: peripheral transfer 4-beat burst
\arg DMA_PERIPH_BURST_8_BEAT: peripheral transfer 8-beat burst
\arg DMA_PERIPH_BURST_16_BEAT: peripheral transfer 16-beat burst
\param[out] none
\retval none
*/
void dma_periph_burst_beats_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pbeat)
{
uint32_t ctl;
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_PBURST;
ctl |= pbeat;
DMA_CHCTL(dma_periph, channelx) = ctl;
}
/*!
\brief configure transfer data size of memory
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] msize: transfer data size of memory
only one parameter can be selected which is shown as below:
\arg DMA_MEMORY_WIDTH_8BIT: transfer data size of memory is 8-bit
\arg DMA_MEMORY_WIDTH_16BIT: transfer data size of memory is 16-bit
\arg DMA_MEMORY_WIDTH_32BIT: transfer data size of memory is 32-bit
\param[out] none
\retval none
*/
void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t msize)
{
uint32_t ctl;
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_MWIDTH;
ctl |= msize;
DMA_CHCTL(dma_periph, channelx) = ctl;
}
/*!
\brief configure transfer data size of peripheral
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] msize: transfer data size of peripheral
only one parameter can be selected which is shown as below:
\arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data size of peripheral is 8-bit
\arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data size of peripheral is 16-bit
\arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data size of peripheral is 32-bit
\param[out] none
\retval none
*/
void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t psize)
{
uint32_t ctl;
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_PWIDTH;
ctl |= psize;
DMA_CHCTL(dma_periph, channelx) = ctl;
}
/*!
\brief configure memory address generation generation_algorithm
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] generation_algorithm: the address generation algorithm
only one parameter can be selected which is shown as below:
\arg DMA_MEMORY_INCREASE_ENABLE: next address of memory is increasing address mode
\arg DMA_MEMORY_INCREASE_DISABLE: next address of memory is fixed address mode
\param[out] none
\retval none
*/
void dma_memory_address_generation_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t generation_algorithm)
{
if(DMA_MEMORY_INCREASE_ENABLE == generation_algorithm) {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
} else {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
}
}
/*!
\brief configure peripheral address generation_algorithm
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] generation_algorithm: the address generation algorithm
only one parameter can be selected which is shown as below:
\arg DMA_PERIPH_INCREASE_ENABLE: next address of peripheral is increasing address mode
\arg DMA_PERIPH_INCREASE_DISABLE: next address of peripheral is fixed address mode
\arg DMA_PERIPH_INCREASE_FIX: increasing steps of peripheral address is fixed
\param[out] none
\retval none
*/
void dma_peripheral_address_generation_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t generation_algorithm)
{
if(DMA_PERIPH_INCREASE_ENABLE == generation_algorithm) {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
} else if(DMA_PERIPH_INCREASE_DISABLE == generation_algorithm) {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
} else {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PAIF;
}
}
/*!
\brief enable DMA circulation mode
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[out] none
\retval none
*/
void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
{
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
}
/*!
\brief disable DMA circulation mode
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[out] none
\retval none
*/
void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
{
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
}
/*!
\brief enable DMA channel
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[out] none
\retval none
*/
void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
{
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN;
}
/*!
\brief disable DMA channel
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[out] none
\retval none
*/
void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
{
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
}
/*!
\brief configure the direction of data transfer on the channel
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] direction: specify the direction of data transfer
only one parameter can be selected which is shown as below:
\arg DMA_PERIPH_TO_MEMORY: read from peripheral and write to memory
\arg DMA_MEMORY_TO_PERIPH: read from memory and write to peripheral
\arg DMA_MEMORY_TO_MEMORY: read from memory and write to memory
\param[out] none
\retval none
*/
void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction)
{
uint32_t ctl;
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_TM;
ctl |= direction;
DMA_CHCTL(dma_periph, channelx) = ctl;
}
/*!
\brief DMA switch buffer mode config
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] memory1_addr: memory1 base address
\param[in] memory_select: DMA_MEMORY_0 or DMA_MEMORY_1
\param[out] none
\retval none
*/
void dma_switch_buffer_mode_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t memory1_addr, uint32_t memory_select)
{
/* configure memory1 base address */
DMA_CHM1ADDR(dma_periph, channelx) = memory1_addr;
if(DMA_MEMORY_0 == memory_select) {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MBS;
} else {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MBS;
}
}
/*!
\brief DMA using memory get
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[out] none
\retval the using memory
*/
uint32_t dma_using_memory_get(uint32_t dma_periph, dma_channel_enum channelx)
{
if((DMA_CHCTL(dma_periph, channelx)) & DMA_CHXCTL_MBS) {
return DMA_MEMORY_1;
} else {
return DMA_MEMORY_0;
}
}
/*!
\brief DMA channel peripheral select
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] sub_periph: specify DMA channel peripheral
\arg DMA_SUBPERIx(x=0..7)
\param[out] none
\retval none
*/
void dma_channel_subperipheral_select(uint32_t dma_periph, dma_channel_enum channelx, dma_subperipheral_enum sub_periph)
{
uint32_t ctl;
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_PERIEN;
ctl |= ((uint32_t)sub_periph << CHXCTL_PERIEN_OFFSET);
DMA_CHCTL(dma_periph, channelx) = ctl;
}
/*!
\brief DMA flow controller configure
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] controller: specify DMA flow controler
only one parameter can be selected which is shown as below:
\arg DMA_FLOW_CONTROLLER_DMA: DMA is the flow controller
\arg DMA_FLOW_CONTROLLER_PERI: peripheral is the flow controller
\param[out] none
\retval none
*/
void dma_flow_controller_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t controller)
{
if(DMA_FLOW_CONTROLLER_DMA == controller) {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_TFCS;
} else {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_TFCS;
}
}
/*!
\brief DMA switch buffer mode enable
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] newvalue: ENABLE or DISABLE
\param[out] none
\retval none
*/
void dma_switch_buffer_mode_enable(uint32_t dma_periph, dma_channel_enum channelx, ControlStatus newvalue)
{
if(ENABLE == newvalue) {
/* switch buffer mode enable */
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_SBMEN;
} else {
/* switch buffer mode disable */
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_SBMEN;
}
}
/*!
\brief DMA FIFO status get
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[out] none
\retval the using memory
*/
uint32_t dma_fifo_status_get(uint32_t dma_periph, dma_channel_enum channelx)
{
return (DMA_CHFCTL(dma_periph, channelx) & DMA_CHXFCTL_FCNT);
}
/*!
\brief get DMA flag is set or not
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel to get flag
\arg DMA_CHx(x=0..7)
\param[in] flag: specify get which flag
only one parameter can be selected which is shown as below:
\arg DMA_FLAG_FEE: FIFO error and exception flag
\arg DMA_FLAG_SDE: single data mode exception flag
\arg DMA_FLAG_TAE: transfer access error flag
\arg DMA_FLAG_HTF: half transfer finish flag
\arg DMA_FLAG_FTF: full transger finish flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
{
if(channelx < DMA_CH4) {
if(DMA_INTF0(dma_periph) & DMA_FLAG_ADD(flag, channelx)) {
return SET;
} else {
return RESET;
}
} else {
channelx -= (dma_channel_enum)4;
if(DMA_INTF1(dma_periph) & DMA_FLAG_ADD(flag, channelx)) {
return SET;
} else {
return RESET;
}
}
}
/*!
\brief clear DMA a channel flag
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel to get flag
\arg DMA_CHx(x=0..7)
\param[in] flag: specify get which flag
only one parameter can be selected which is shown as below:
\arg DMA_FLAG_FEE: FIFO error and exception flag
\arg DMA_FLAG_SDE: single data mode exception flag
\arg DMA_FLAG_TAE: transfer access error flag
\arg DMA_FLAG_HTF: half transfer finish flag
\arg DMA_FLAG_FTF: full transger finish flag
\param[out] none
\retval none
*/
void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
{
if(channelx < DMA_CH4) {
DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
} else {
channelx -= (dma_channel_enum)4;
DMA_INTC1(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
}
}
/*!
\brief enable DMA interrupt
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] source: specify which interrupt to enbale
only one parameters can be selected which are shown as below:
\arg DMA_INT_SDE: single data mode exception interrupt enable
\arg DMA_INT_TAE: tranfer access error interrupt enable
\arg DMA_INT_HTF: half transfer finish interrupt enable
\arg DMA_INT_FTF: full transfer finish interrupt enable
\arg DMA_INT_FEE: FIFO exception interrupt enable
\param[out] none
\retval none
*/
void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
{
if(DMA_CHXFCTL_FEEIE != source) {
DMA_CHCTL(dma_periph, channelx) |= source;
} else {
DMA_CHFCTL(dma_periph, channelx) |= source;
}
}
/*!
\brief disable DMA interrupt
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel
\arg DMA_CHx(x=0..7)
\param[in] source: specify which interrupt to disbale
only one parameters can be selected which are shown as below:
\arg DMA_INT_SDE: single data mode exception interrupt enable
\arg DMA_INT_TAE: tranfer access error interrupt enable
\arg DMA_INT_HTF: half transfer finish interrupt enable
\arg DMA_INT_FTF: full transfer finish interrupt enable
\arg DMA_INT_FEE: FIFO exception interrupt enable
\param[out] none
\retval none
*/
void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
{
if(DMA_CHXFCTL_FEEIE != source) {
DMA_CHCTL(dma_periph, channelx) &= ~source;
} else {
DMA_CHFCTL(dma_periph, channelx) &= ~source;
}
}
/*!
\brief get DMA interrupt flag is set or not
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel to get interrupt flag
\arg DMA_CHx(x=0..7)
\param[in] interrupt: specify get which flag
only one parameter can be selected which is shown as below:
\arg DMA_INT_FLAG_FEE: FIFO error and exception flag
\arg DMA_INT_FLAG_SDE: single data mode exception flag
\arg DMA_INT_FLAG_TAE: transfer access error flag
\arg DMA_INT_FLAG_HTF: half transfer finish flag
\arg DMA_INT_FLAG_FTF: full transger finish flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t interrupt)
{
uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
dma_channel_enum channel_flag_offset = channelx;
if(channelx < DMA_CH4) {
switch(interrupt) {
case DMA_INTF_FEEIF:
interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt, channelx);
interrupt_enable = DMA_CHFCTL(dma_periph, channelx) & DMA_CHXFCTL_FEEIE;
break;
case DMA_INTF_SDEIF:
interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt, channelx);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_SDEIE;
break;
case DMA_INTF_TAEIF:
interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt, channelx);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_TAEIE;
break;
case DMA_INTF_HTFIF:
interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt, channelx);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
break;
case DMA_INTF_FTFIF:
interrupt_flag = (DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt, channelx));
interrupt_enable = (DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE);
break;
default:
break;
}
} else {
channel_flag_offset -= (dma_channel_enum)4;
switch(interrupt) {
case DMA_INTF_FEEIF:
interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt, channel_flag_offset);
interrupt_enable = DMA_CHFCTL(dma_periph, channelx) & DMA_CHXFCTL_FEEIE;
break;
case DMA_INTF_SDEIF:
interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt, channel_flag_offset);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_SDEIE;
break;
case DMA_INTF_TAEIF:
interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt, channel_flag_offset);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_TAEIE;
break;
case DMA_INTF_HTFIF:
interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt, channel_flag_offset);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
break;
case DMA_INTF_FTFIF:
interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt, channel_flag_offset);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE;
break;
default:
break;
}
}
if(interrupt_flag && interrupt_enable) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear DMA a channel interrupt flag
\param[in] dma_periph: DMAx(x=0,1)
\arg DMAx(x=0,1)
\param[in] channelx: specify which DMA channel to clear interrupt flag
\arg DMA_CHx(x=0..7)
\param[in] interrupt: specify get which flag
only one parameter can be selected which is shown as below:
\arg DMA_INT_FLAG_FEE: FIFO error and exception flag
\arg DMA_INT_FLAG_SDE: single data mode exception flag
\arg DMA_INT_FLAG_TAE: transfer access error flag
\arg DMA_INT_FLAG_HTF: half transfer finish flag
\arg DMA_INT_FLAG_FTF: full transger finish flag
\param[out] none
\retval none
*/
void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t interrupt)
{
if(channelx < DMA_CH4) {
DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(interrupt, channelx);
} else {
channelx -= (dma_channel_enum)4;
DMA_INTC1(dma_periph) |= DMA_FLAG_ADD(interrupt, channelx);
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,250 @@
/*!
\file gd32f4xx_exti.c
\brief EXTI driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_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_INTEN = EXTI_REG_RESET_VALUE;
EXTI_EVEN = EXTI_REG_RESET_VALUE;
EXTI_RTEN = EXTI_REG_RESET_VALUE;
EXTI_FTEN = EXTI_REG_RESET_VALUE;
EXTI_SWIEV = 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..22): 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 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 &= ~(uint32_t)linex;
EXTI_EVEN &= ~(uint32_t)linex;
EXTI_RTEN &= ~(uint32_t)linex;
EXTI_FTEN &= ~(uint32_t)linex;
/* set the EXTI mode and enable the interrupts or events from EXTI line x */
switch(mode) {
case EXTI_INTERRUPT:
EXTI_INTEN |= (uint32_t)linex;
break;
case EXTI_EVENT:
EXTI_EVEN |= (uint32_t)linex;
break;
default:
break;
}
/* set the EXTI trigger type */
switch(trig_type) {
case EXTI_TRIG_RISING:
EXTI_RTEN |= (uint32_t)linex;
EXTI_FTEN &= ~(uint32_t)linex;
break;
case EXTI_TRIG_FALLING:
EXTI_RTEN &= ~(uint32_t)linex;
EXTI_FTEN |= (uint32_t)linex;
break;
case EXTI_TRIG_BOTH:
EXTI_RTEN |= (uint32_t)linex;
EXTI_FTEN |= (uint32_t)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..22): EXTI line x
\param[out] none
\retval none
*/
void exti_interrupt_enable(exti_line_enum linex)
{
EXTI_INTEN |= (uint32_t)linex;
}
/*!
\brief disable the interrupt 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..22): EXTI line x
\param[out] none
\retval none
*/
void exti_interrupt_disable(exti_line_enum linex)
{
EXTI_INTEN &= ~(uint32_t)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..22): EXTI line x
\param[out] none
\retval none
*/
void exti_event_enable(exti_line_enum linex)
{
EXTI_EVEN |= (uint32_t)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..22): EXTI line x
\param[out] none
\retval none
*/
void exti_event_disable(exti_line_enum linex)
{
EXTI_EVEN &= ~(uint32_t)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..22): EXTI line x
\param[out] none
\retval none
*/
void exti_software_interrupt_enable(exti_line_enum linex)
{
EXTI_SWIEV |= (uint32_t)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..22): EXTI line x
\param[out] none
\retval none
*/
void exti_software_interrupt_disable(exti_line_enum linex)
{
EXTI_SWIEV &= ~(uint32_t)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..22): 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 & (uint32_t)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..22): EXTI line x
\param[out] none
\retval none
*/
void exti_flag_clear(exti_line_enum linex)
{
EXTI_PD = (uint32_t)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..22): 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 & (uint32_t)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..22): EXTI line x
\param[out] none
\retval none
*/
void exti_interrupt_flag_clear(exti_line_enum linex)
{
EXTI_PD = (uint32_t)linex;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,215 @@
/*!
\file gd32f4xx_fwdgt.c
\brief FWDGT driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_fwdgt.h"
/*!
\brief enable write access to FWDGT_PSC and FWDGT_RLD
\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 and FWDGT_RLD
\param[in] none
\param[out] none
\retval none
*/
void fwdgt_write_disable(void)
{
FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE;
}
/*!
\brief start the free watchdog timer counter
\param[in] none
\param[out] none
\retval none
*/
void fwdgt_enable(void)
{
FWDGT_CTL = FWDGT_KEY_ENABLE;
}
/*!
\brief configure the free watchdog timer 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)
{
uint32_t timeout = FWDGT_PSC_TIMEOUT;
uint32_t flag_status = RESET;
/* 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 > 0U) && ((uint32_t)RESET != flag_status));
if ((uint32_t)RESET != flag_status){
return ERROR;
}
/* configure FWDGT */
FWDGT_PSC = (uint32_t)prescaler_value;
return SUCCESS;
}
/*!
\brief configure the free watchdog timer 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;
/* 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 > 0U) && ((uint32_t)RESET != flag_status));
if ((uint32_t)RESET != flag_status){
return ERROR;
}
FWDGT_RLD = RLD_RLD(reload_value);
return SUCCESS;
}
/*!
\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;
/* 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 > 0U) && ((uint32_t)RESET != flag_status));
if ((uint32_t)RESET != flag_status){
return 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 > 0U) && ((uint32_t)RESET != flag_status));
if ((uint32_t)RESET != flag_status){
return ERROR;
}
FWDGT_RLD = RLD_RLD(reload_value);
/* reload the counter */
FWDGT_CTL = FWDGT_KEY_RELOAD;
return SUCCESS;
}
/*!
\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_STAT_PUD: a write operation to FWDGT_PSC register is on going
\arg FWDGT_STAT_RUD: a write operation to FWDGT_RLD register is on going
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus fwdgt_flag_get(uint16_t flag)
{
if(RESET != (FWDGT_STAT & flag)){
return SET;
}
return RESET;
}
@@ -0,0 +1,431 @@
/*!
\file gd32f4xx_gpio.c
\brief GPIO driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_gpio.h"
/*!
\brief reset GPIO port
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\param[out] none
\retval none
*/
void gpio_deinit(uint32_t gpio_periph)
{
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 GPIOI:
/* reset GPIOI */
rcu_periph_reset_enable(RCU_GPIOIRST);
rcu_periph_reset_disable(RCU_GPIOIRST);
break;
default:
break;
}
}
/*!
\brief set GPIO mode
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\param[in] mode: GPIO pin mode
\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
\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;
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: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\param[in] otype: GPIO pin output mode
\arg GPIO_OTYPE_PP: push pull mode
\arg GPIO_OTYPE_OD: open drain mode
\param[in] speed: GPIO pin output max speed
\arg GPIO_OSPEED_2MHZ: output max speed 2MHz
\arg GPIO_OSPEED_25MHZ: output max speed 25MHz
\arg GPIO_OSPEED_50MHZ: output max speed 50MHz
\arg GPIO_OSPEED_MAX: output max speed more than 50MHz
\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 ospeedr;
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 */
ospeedr = GPIO_OSPD(gpio_periph);
for(i = 0U; i < 16U; i++) {
if((1U << i) & pin) {
/* clear the specified pin output speed bits */
ospeedr &= ~GPIO_OSPEED_MASK(i);
/* set the specified pin output speed bits */
ospeedr |= GPIO_OSPEED_SET(i, speed);
}
}
GPIO_OSPD(gpio_periph) = ospeedr;
}
/*!
\brief set GPIO pin bit
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\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)
{
GPIO_BOP(gpio_periph) = (uint32_t)pin;
}
/*!
\brief reset GPIO pin bit
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\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)
{
GPIO_BC(gpio_periph) = (uint32_t)pin;
}
/*!
\brief write data to the specified GPIO pin
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\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
\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)
{
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: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\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)
{
GPIO_OCTL(gpio_periph) = (uint32_t)data;
}
/*!
\brief get GPIO pin input status
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\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 input status of GPIO pin: SET or RESET
*/
FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin)
{
if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph) & (pin))) {
return SET;
} else {
return RESET;
}
}
/*!
\brief get GPIO all pins input status
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\param[out] none
\retval input status of GPIO all pins
*/
uint16_t gpio_input_port_get(uint32_t gpio_periph)
{
return ((uint16_t)GPIO_ISTAT(gpio_periph));
}
/*!
\brief get GPIO pin output status
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\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 output status of GPIO pin: SET or RESET
*/
FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin)
{
if((uint32_t)RESET != (GPIO_OCTL(gpio_periph) & (pin))) {
return SET;
} else {
return RESET;
}
}
/*!
\brief get GPIO port output status
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\param[out] none
\retval output status of GPIO all pins
*/
uint16_t gpio_output_port_get(uint32_t gpio_periph)
{
return ((uint16_t)GPIO_OCTL(gpio_periph));
}
/*!
\brief set GPIO alternate function
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\param[in] alt_func_num: GPIO pin af function
\arg GPIO_AF_0: SYSTEM
\arg GPIO_AF_1: TIMER0, TIMER1
\arg GPIO_AF_2: TIMER2, TIMER3, TIMER4
\arg GPIO_AF_3: TIMER7, TIMER8, TIMER9, TIMER10
\arg GPIO_AF_4: I2C0, I2C1, I2C2
\arg GPIO_AF_5: SPI0, SPI1, SPI2, SPI3, SPI4, SPI5
\arg GPIO_AF_6: SPI2, SPI3, SPI4
\arg GPIO_AF_7: USART0, USART1, USART2, SPI1, SPI2
\arg GPIO_AF_8: UART3, UART4, USART5, UART6, UART7
\arg GPIO_AF_9: CAN0, CAN1, TLI, TIMER11, TIMER12, TIMER13, I2C1, I2C2, CTC
\arg GPIO_AF_10: USB_FS, USB_HS
\arg GPIO_AF_11: ENET
\arg GPIO_AF_12: EXMC, SDIO, USB_HS
\arg GPIO_AF_13: DCI
\arg GPIO_AF_14: TLI
\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;
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: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\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;
/* 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: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\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)
{
GPIO_TG(gpio_periph) = (uint32_t)pin;
}
/*!
\brief toggle GPIO port status
\param[in] gpio_periph: GPIO port
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,E,F,G,H,I)
\param[out] none
\retval none
*/
void gpio_port_toggle(uint32_t gpio_periph)
{
GPIO_TG(gpio_periph) = 0x0000FFFFU;
}
@@ -0,0 +1,836 @@
/*!
\file gd32f4xx_i2c.c
\brief I2C driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_i2c.h"
/* I2C register bit mask */
#define I2CCLK_MAX ((uint32_t)0x0000003CU) /*!< i2cclk maximum value */
#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */
#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */
#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */
#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */
/* I2C register bit offset */
#define STAT1_PECV_OFFSET ((uint32_t)0x00000008U) /* bit offset of PECV in I2C_STAT1 */
/*!
\brief reset I2C
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_deinit(uint32_t i2c_periph)
{
switch(i2c_periph) {
case I2C0:
/* reset I2C0 */
rcu_periph_reset_enable(RCU_I2C0RST);
rcu_periph_reset_disable(RCU_I2C0RST);
break;
case I2C1:
/* reset I2C1 */
rcu_periph_reset_enable(RCU_I2C1RST);
rcu_periph_reset_disable(RCU_I2C1RST);
break;
case I2C2:
/* reset I2C2 */
rcu_periph_reset_enable(RCU_I2C2RST);
rcu_periph_reset_disable(RCU_I2C2RST);
break;
default:
break;
}
}
/*!
\brief configure I2C clock
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz)
\param[in] dutycyc: duty cycle in fast mode
only one parameter can be selected which is shown as below:
\arg I2C_DTCY_2: T_low/T_high = 2 in fast mode
\arg I2C_DTCY_16_9: T_low/T_high = 16/9 in fast mode
\param[out] none
\retval none
*/
void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc)
{
uint32_t pclk1, clkc, freq, risetime;
uint32_t temp;
pclk1 = rcu_clock_freq_get(CK_APB1);
/* I2C peripheral clock frequency */
freq = (uint32_t)(pclk1 / 1000000U);
if(freq >= I2CCLK_MAX) {
freq = I2CCLK_MAX;
}
temp = I2C_CTL1(i2c_periph);
temp &= ~I2C_CTL1_I2CCLK;
temp |= freq;
I2C_CTL1(i2c_periph) = temp;
if(100000U >= clkspeed) {
/* the maximum SCL rise time is 1000ns in standard mode */
risetime = (uint32_t)((pclk1 / 1000000U) + 1U);
if(risetime >= I2CCLK_MAX) {
I2C_RT(i2c_periph) = I2CCLK_MAX;
} else if(risetime <= I2CCLK_MIN) {
I2C_RT(i2c_periph) = I2CCLK_MIN;
} else {
I2C_RT(i2c_periph) = risetime;
}
clkc = (uint32_t)(pclk1 / (clkspeed * 2U));
if(clkc < 0x04U) {
/* the CLKC in standard mode minmum value is 4 */
clkc = 0x04U;
}
I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc);
} else if(400000U >= clkspeed) {
/* the maximum SCL rise time is 300ns in fast mode */
I2C_RT(i2c_periph) = (uint32_t)(((freq * (uint32_t)300U) / (uint32_t)1000U) + (uint32_t)1U);
if(I2C_DTCY_2 == dutycyc) {
/* I2C duty cycle is 2 */
clkc = (uint32_t)(pclk1 / (clkspeed * 3U));
I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
} else {
/* I2C duty cycle is 16/9 */
clkc = (uint32_t)(pclk1 / (clkspeed * 25U));
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
}
if(0U == (clkc & I2C_CKCFG_CLKC)) {
/* the CLKC in fast mode minmum value is 1 */
clkc |= 0x0001U;
}
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
I2C_CKCFG(i2c_periph) |= clkc;
} else {
}
}
/*!
\brief configure I2C address
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] mode:
only one parameter can be selected which is shown as below:
\arg I2C_I2CMODE_ENABLE: I2C mode
\arg I2C_SMBUSMODE_ENABLE: SMBus mode
\param[in] addformat: 7bits or 10bits
only one parameter can be selected which is shown as below:
\arg I2C_ADDFORMAT_7BITS: address format is 7 bits
\arg I2C_ADDFORMAT_10BITS: address format is 10 bits
\param[in] addr: I2C address
\param[out] none
\retval none
*/
void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr)
{
/* SMBus/I2C mode selected */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SMBEN);
ctl |= mode;
I2C_CTL0(i2c_periph) = ctl;
/* configure address */
addr = addr & I2C_ADDRESS_MASK;
I2C_SADDR0(i2c_periph) = (addformat | addr);
}
/*!
\brief select SMBus type
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] type:
only one parameter can be selected which is shown as below:
\arg I2C_SMBUS_DEVICE: SMBus mode device type
\arg I2C_SMBUS_HOST: SMBus mode host type
\param[out] none
\retval none
*/
void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type)
{
if(I2C_SMBUS_HOST == type) {
I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL;
} else {
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL);
}
}
/*!
\brief whether or not to send an ACK
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] ack:
only one parameter can be selected which is shown as below:
\arg I2C_ACK_ENABLE: ACK will be sent
\arg I2C_ACK_DISABLE: ACK will not be sent
\param[out] none
\retval none
*/
void i2c_ack_config(uint32_t i2c_periph, uint32_t ack)
{
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_ACKEN);
ctl |= ack;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief configure I2C POAP position
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] pos:
only one parameter can be selected which is shown as below:
\arg I2C_ACKPOS_CURRENT: ACKEN bit decides whether or not to send ACK or not for the current byte
\arg I2C_ACKPOS_NEXT: ACKEN bit decides whether or not to send ACK for the next byte
\param[out] none
\retval none
*/
void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos)
{
uint32_t ctl = 0U;
/* configure I2C POAP position */
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_POAP);
ctl |= pos;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief master sends slave address
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] addr: slave address
\param[in] trandirection: transmitter or receiver
only one parameter can be selected which is shown as below:
\arg I2C_TRANSMITTER: transmitter
\arg I2C_RECEIVER: receiver
\param[out] none
\retval none
*/
void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection)
{
/* master is a transmitter or a receiver */
if(I2C_TRANSMITTER == trandirection) {
addr = addr & I2C_TRANSMITTER;
} else {
addr = addr | I2C_RECEIVER;
}
/* send slave address */
I2C_DATA(i2c_periph) = addr;
}
/*!
\brief enable dual-address mode
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] addr: the second address in dual-address mode
\param[out] none
\retval none
*/
void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr)
{
/* configure address */
addr = addr & I2C_ADDRESS2_MASK;
I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr);
}
/*!
\brief disable dual-address mode
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_dualaddr_disable(uint32_t i2c_periph)
{
I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN);
}
/*!
\brief enable I2C
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_enable(uint32_t i2c_periph)
{
I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN;
}
/*!
\brief disable I2C
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_disable(uint32_t i2c_periph)
{
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN);
}
/*!
\brief generate a START condition on I2C bus
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_start_on_bus(uint32_t i2c_periph)
{
I2C_CTL0(i2c_periph) |= I2C_CTL0_START;
}
/*!
\brief generate a STOP condition on I2C bus
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_stop_on_bus(uint32_t i2c_periph)
{
I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP;
}
/*!
\brief I2C transmit data function
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] data: data of transmission
\param[out] none
\retval none
*/
void i2c_data_transmit(uint32_t i2c_periph, uint8_t data)
{
I2C_DATA(i2c_periph) = DATA_TRANS(data);
}
/*!
\brief I2C receive data function
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval data of received
*/
uint8_t i2c_data_receive(uint32_t i2c_periph)
{
return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph));
}
/*!
\brief configure I2C DMA mode
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] dmastate:
only one parameter can be selected which is shown as below:
\arg I2C_DMA_ON: enable DMA mode
\arg I2C_DMA_OFF: disable DMA mode
\param[out] none
\retval none
*/
void i2c_dma_config(uint32_t i2c_periph, uint32_t dmastate)
{
/* configure I2C DMA function */
uint32_t ctl = 0U;
ctl = I2C_CTL1(i2c_periph);
ctl &= ~(I2C_CTL1_DMAON);
ctl |= dmastate;
I2C_CTL1(i2c_periph) = ctl;
}
/*!
\brief configure whether next DMA EOT is DMA last transfer or not
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] dmalast:
only one parameter can be selected which is shown as below:
\arg I2C_DMALST_ON: next DMA EOT is the last transfer
\arg I2C_DMALST_OFF: next DMA EOT is not the last transfer
\param[out] none
\retval none
*/
void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast)
{
/* configure DMA last transfer */
uint32_t ctl = 0U;
ctl = I2C_CTL1(i2c_periph);
ctl &= ~(I2C_CTL1_DMALST);
ctl |= dmalast;
I2C_CTL1(i2c_periph) = ctl;
}
/*!
\brief whether to stretch SCL low when data is not ready in slave mode
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] stretchpara:
only one parameter can be selected which is shown as below:
\arg I2C_SCLSTRETCH_ENABLE: enable SCL stretching
\arg I2C_SCLSTRETCH_DISABLE: disable SCL stretching
\param[out] none
\retval none
*/
void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara)
{
/* configure I2C SCL strerching */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SS);
ctl |= stretchpara;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief whether or not to response to a general call
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] gcallpara:
only one parameter can be selected which is shown as below:
\arg I2C_GCEN_ENABLE: slave will response to a general call
\arg I2C_GCEN_DISABLE: slave will not response to a general call
\param[out] none
\retval none
*/
void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara)
{
/* configure slave response to a general call enable or disable */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_GCEN);
ctl |= gcallpara;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief configure software reset of I2C
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] sreset:
only one parameter can be selected which is shown as below:
\arg I2C_SRESET_SET: I2C is under reset
\arg I2C_SRESET_RESET: I2C is not under reset
\param[out] none
\retval none
*/
void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset)
{
/* modify CTL0 and configure software reset I2C state */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SRESET);
ctl |= sreset;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief configure I2C PEC calculation
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] pecstate:
only one parameter can be selected which is shown as below:
\arg I2C_PEC_ENABLE: PEC calculation on
\arg I2C_PEC_DISABLE: PEC calculation off
\param[out] none
\retval none
*/
void i2c_pec_config(uint32_t i2c_periph, uint32_t pecstate)
{
/* on/off PEC calculation */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_PECEN);
ctl |= pecstate;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief configure whether to transfer PEC value
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] pecpara:
only one parameter can be selected which is shown as below:
\arg I2C_PECTRANS_ENABLE: transfer PEC value
\arg I2C_PECTRANS_DISABLE: not transfer PEC value
\param[out] none
\retval none
*/
void i2c_pec_transfer_config(uint32_t i2c_periph, uint32_t pecpara)
{
/* whether to transfer PEC */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_PECTRANS);
ctl |= pecpara;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief get packet error checking value
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval PEC value
*/
uint8_t i2c_pec_value_get(uint32_t i2c_periph)
{
return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV) >> STAT1_PECV_OFFSET);
}
/*!
\brief configure I2C alert through SMBA pin
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] smbuspara:
only one parameter can be selected which is shown as below:
\arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin
\arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin
\param[out] none
\retval none
*/
void i2c_smbus_alert_config(uint32_t i2c_periph, uint32_t smbuspara)
{
/* configure smubus alert through SMBA pin */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SALT);
ctl |= smbuspara;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief configure I2C ARP protocol in SMBus
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] arpstate:
only one parameter can be selected which is shown as below:
\arg I2C_ARP_ENABLE: enable ARP
\arg I2C_ARP_DISABLE: disable ARP
\param[out] none
\retval none
*/
void i2c_smbus_arp_config(uint32_t i2c_periph, uint32_t arpstate)
{
/* enable or disable I2C ARP protocol*/
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_ARPEN);
ctl |= arpstate;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief disable analog noise filter
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_analog_noise_filter_disable(uint32_t i2c_periph)
{
I2C_FCTL(i2c_periph) |= I2C_FCTL_AFD;
}
/*!
\brief enable analog noise filter
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_analog_noise_filter_enable(uint32_t i2c_periph)
{
I2C_FCTL(i2c_periph) &= ~(I2C_FCTL_AFD);
}
/*!
\brief configure digital noise filter
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] dfilterpara: refer to i2c_digital_filter_enum
only one parameter can be selected which is shown as below:
\arg I2C_DF_DISABLE: disable digital noise filter
\arg I2C_DF_1PCLK: enable digital noise filter and the maximum filtered spiker's length 1 PCLK1
\arg I2C_DF_2PCLK: enable digital noise filter and the maximum filtered spiker's length 2 PCLK1
\arg I2C_DF_3PCLK: enable digital noise filter and the maximum filtered spiker's length 3 PCLK1
\arg I2C_DF_4PCLK: enable digital noise filter and the maximum filtered spiker's length 4 PCLK1
\arg I2C_DF_5PCLK: enable digital noise filter and the maximum filtered spiker's length 5 PCLK1
\arg I2C_DF_6PCLK: enable digital noise filter and the maximum filtered spiker's length 6 PCLK1
\arg I2C_DF_7PCLK: enable digital noise filter and the maximum filtered spiker's length 7 PCLK1
\arg I2C_DF_8PCLK: enable digital noise filter and the maximum filtered spiker's length 8 PCLK1
\arg I2C_DF_9PCLK: enable digital noise filter and the maximum filtered spiker's length 9 PCLK1
\arg I2C_DF_10PCLK: enable digital noise filter and the maximum filtered spiker's length 10 PCLK1
\arg I2C_DF_11CLK: enable digital noise filter and the maximum filtered spiker's length 11 PCLK1
\arg I2C_DF_12CLK: enable digital noise filter and the maximum filtered spiker's length 12 PCLK1
\arg I2C_DF_13PCLK: enable digital noise filter and the maximum filtered spiker's length 13 PCLK1
\arg I2C_DF_14PCLK: enable digital noise filter and the maximum filtered spiker's length 14 PCLK1
\arg I2C_DF_15PCLK: enable digital noise filter and the maximum filtered spiker's length 15 PCLK1
\param[out] none
\retval none
*/
void i2c_digital_noise_filter_config(uint32_t i2c_periph, i2c_digital_filter_enum dfilterpara)
{
I2C_FCTL(i2c_periph) |= dfilterpara;
}
/*!
\brief enable SAM_V interface
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_sam_enable(uint32_t i2c_periph)
{
I2C_SAMCS(i2c_periph) |= I2C_SAMCS_SAMEN;
}
/*!
\brief disable SAM_V interface
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_sam_disable(uint32_t i2c_periph)
{
I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_SAMEN);
}
/*!
\brief enable SAM_V interface timeout detect
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_sam_timeout_enable(uint32_t i2c_periph)
{
I2C_SAMCS(i2c_periph) |= I2C_SAMCS_STOEN;
}
/*!
\brief disable SAM_V interface timeout detect
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[out] none
\retval none
*/
void i2c_sam_timeout_disable(uint32_t i2c_periph)
{
I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_STOEN);
}
/*!
\brief get I2C flag status
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] flag: I2C flags, refer to i2c_flag_enum
only one parameter can be selected which is shown as below:
\arg I2C_FLAG_SBSEND: start condition sent out in master mode
\arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
\arg I2C_FLAG_BTC: byte transmission finishes
\arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode
\arg I2C_FLAG_STPDET: stop condition detected in slave mode
\arg I2C_FLAG_RBNE: I2C_DATA is not empty during receiving
\arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting
\arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus
\arg I2C_FLAG_LOSTARB: arbitration lost in master mode
\arg I2C_FLAG_AERR: acknowledge error
\arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode
\arg I2C_FLAG_PECERR: PEC error when receiving data
\arg I2C_FLAG_SMBTO: timeout signal in SMBus mode
\arg I2C_FLAG_SMBALT: SMBus alert status
\arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode
\arg I2C_FLAG_I2CBSY: busy flag
\arg I2C_FLAG_TR: whether the I2C is a transmitter or a receiver
\arg I2C_FLAG_RXGC: general call address (00h) received
\arg I2C_FLAG_DEFSMB: default address of SMBus device
\arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode
\arg I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode
\arg I2C_FLAG_TFF: txframe fall flag
\arg I2C_FLAG_TFR: txframe rise flag
\arg I2C_FLAG_RFF: rxframe fall flag
\arg I2C_FLAG_RFR: rxframe rise flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag)
{
if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear I2C flag status
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] flag: I2C flags, refer to i2c_flag_enum
only one parameter can be selected which is shown as below:
\arg I2C_FLAG_SMBALT: SMBus alert status
\arg I2C_FLAG_SMBTO: timeout signal in SMBus mode
\arg I2C_FLAG_PECERR: PEC error when receiving data
\arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode
\arg I2C_FLAG_AERR: acknowledge error
\arg I2C_FLAG_LOSTARB: arbitration lost in master mode
\arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus
\arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
\arg I2C_FLAG_TFF: txframe fall flag
\arg I2C_FLAG_TFR: txframe rise flag
\arg I2C_FLAG_RFF: rxframe fall flag
\arg I2C_FLAG_RFR: rxframe rise flag
\param[out] none
\retval none
*/
void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag)
{
if(I2C_FLAG_ADDSEND == flag) {
/* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
I2C_STAT0(i2c_periph);
I2C_STAT1(i2c_periph);
} else {
I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag));
}
}
/*!
\brief enable I2C interrupt
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum
only one parameter can be selected which is shown as below:
\arg I2C_INT_ERR: error interrupt
\arg I2C_INT_EV: event interrupt
\arg I2C_INT_BUF: buffer interrupt
\arg I2C_INT_TFF: txframe fall interrupt
\arg I2C_INT_TFR: txframe rise interrupt
\arg I2C_INT_RFF: rxframe fall interrupt
\arg I2C_INT_RFR: rxframe rise interrupt
\param[out] none
\retval none
*/
void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
{
I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt));
}
/*!
\brief disable I2C interrupt
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum
only one parameter can be selected which is shown as below:
\arg I2C_INT_ERR: error interrupt
\arg I2C_INT_EV: event interrupt
\arg I2C_INT_BUF: buffer interrupt
\arg I2C_INT_TFF: txframe fall interrupt
\arg I2C_INT_TFR: txframe rise interrupt
\arg I2C_INT_RFF: rxframe fall interrupt
\arg I2C_INT_RFR: rxframe rise interrupt
\param[out] none
\retval none
*/
void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
{
I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt));
}
/*!
\brief get I2C interrupt flag status
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
only one parameter can be selected which is shown as below:
\arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag
\arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
\arg I2C_INT_FLAG_BTC: byte transmission finishes interrupt flag
\arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag
\arg I2C_INT_FLAG_STPDET: stop condition detected in slave mode interrupt flag
\arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag
\arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag
\arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
\arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
\arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag
\arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
\arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
\arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
\arg I2C_INT_FLAG_SMBALT: SMBus alert status interrupt flag
\arg I2C_INT_FLAG_TFF: txframe fall interrupt flag
\arg I2C_INT_FLAG_TFR: txframe rise interrupt flag
\arg I2C_INT_FLAG_RFF: rxframe fall interrupt flag
\arg I2C_INT_FLAG_RFR: rxframe rise interrupt flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag)
{
uint32_t intenable = 0U, flagstatus = 0U, bufie;
/* check BUFIE */
bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE;
/* get the interrupt enable bit status */
intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag)));
/* get the corresponding flag bit status */
flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag)));
if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)) {
if(intenable && bufie) {
intenable = 1U;
} else {
intenable = 0U;
}
}
if((0U != flagstatus) && (0U != intenable)) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear I2C interrupt flag status
\param[in] i2c_periph: I2Cx(x=0,1,2)
\param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
only one parameter can be selected which is shown as below:
\arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
\arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
\arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
\arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag
\arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
\arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
\arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
\arg I2C_INT_FLAG_SMBALT: SMBus alert status interrupt flag
\arg I2C_INT_FLAG_TFF: txframe fall interrupt flag
\arg I2C_INT_FLAG_TFR: txframe rise interrupt flag
\arg I2C_INT_FLAG_RFF: rxframe fall interrupt flag
\arg I2C_INT_FLAG_RFR: rxframe rise interrupt flag
\param[out] none
\retval none
*/
void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag)
{
if(I2C_INT_FLAG_ADDSEND == int_flag) {
/* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
I2C_STAT0(i2c_periph);
I2C_STAT1(i2c_periph);
} else {
I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag));
}
}
@@ -0,0 +1,636 @@
/*!
\file gd32f4xx_ipa.c
\brief IPA driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_ipa.h"
#define IPA_DEFAULT_VALUE 0x00000000U
/*!
\brief deinitialize IPA registers
\param[in] none
\param[out] none
\retval none
*/
void ipa_deinit(void)
{
rcu_periph_reset_enable(RCU_IPARST);
rcu_periph_reset_disable(RCU_IPARST);
}
/*!
\brief enable IPA transfer
\param[in] none
\param[out] none
\retval none
*/
void ipa_transfer_enable(void)
{
IPA_CTL |= IPA_CTL_TEN;
}
/*!
\brief enable IPA transfer hang up
\param[in] none
\param[out] none
\retval none
*/
void ipa_transfer_hangup_enable(void)
{
IPA_CTL |= IPA_CTL_THU;
}
/*!
\brief disable IPA transfer hang up
\param[in] none
\param[out] none
\retval none
*/
void ipa_transfer_hangup_disable(void)
{
IPA_CTL &= ~(IPA_CTL_THU);
}
/*!
\brief enable IPA transfer stop
\param[in] none
\param[out] none
\retval none
*/
void ipa_transfer_stop_enable(void)
{
IPA_CTL |= IPA_CTL_TST;
}
/*!
\brief disable IPA transfer stop
\param[in] none
\param[out] none
\retval none
*/
void ipa_transfer_stop_disable(void)
{
IPA_CTL &= ~(IPA_CTL_TST);
}
/*!
\brief enable IPA foreground LUT loading
\param[in] none
\param[out] none
\retval none
*/
void ipa_foreground_lut_loading_enable(void)
{
IPA_FPCTL |= IPA_FPCTL_FLLEN;
}
/*!
\brief enable IPA background LUT loading
\param[in] none
\param[out] none
\retval none
*/
void ipa_background_lut_loading_enable(void)
{
IPA_BPCTL |= IPA_BPCTL_BLLEN;
}
/*!
\brief set pixel format convert mode, the function is invalid when the IPA transfer is enabled
\param[in] pfcm: pixel format convert mode
only one parameter can be selected which is shown as below:
\arg IPA_FGTODE: foreground memory to destination memory without pixel format convert
\arg IPA_FGTODE_PF_CONVERT: foreground memory to destination memory with pixel format convert
\arg IPA_FGBGTODE: blending foreground and background memory to destination memory
\arg IPA_FILL_UP_DE: fill up destination memory with specific color
\param[out] none
\retval none
*/
void ipa_pixel_format_convert_mode_set(uint32_t pfcm)
{
IPA_CTL &= ~(IPA_CTL_PFCM);
IPA_CTL |= pfcm;
}
/*!
\brief initialize the structure of IPA foreground parameter struct with the default values, it is
suggested that call this function after an ipa_foreground_parameter_struct structure is defined
\param[in] none
\param[out] foreground_struct: the data needed to initialize foreground
foreground_memaddr: foreground memory base address
foreground_lineoff: foreground line offset
foreground_prealpha: foreground pre-defined alpha value
foreground_alpha_algorithm: IPA_FG_ALPHA_MODE_0,IPA_FG_ALPHA_MODE_1,IPA_FG_ALPHA_MODE_2
foreground_pf: foreground pixel format(FOREGROUND_PPF_ARGB8888,FOREGROUND_PPF_RGB888,FOREGROUND_PPF_RGB565,
FOREGROUND_PPF_ARG1555,FOREGROUND_PPF_ARGB4444,FOREGROUND_PPF_L8,FOREGROUND_PPF_AL44,
FOREGROUND_PPF_AL88,FOREGROUND_PPF_L4,FOREGROUND_PPF_A8,FOREGROUND_PPF_A4)
foreground_prered: foreground pre-defined red value
foreground_pregreen: foreground pre-defined green value
foreground_preblue: foreground pre-defined blue value
\retval none
*/
void ipa_foreground_struct_para_init(ipa_foreground_parameter_struct *foreground_struct)
{
/* initialize the struct parameters with default values */
foreground_struct->foreground_memaddr = IPA_DEFAULT_VALUE;
foreground_struct->foreground_lineoff = IPA_DEFAULT_VALUE;
foreground_struct->foreground_prealpha = IPA_DEFAULT_VALUE;
foreground_struct->foreground_alpha_algorithm = IPA_FG_ALPHA_MODE_0;
foreground_struct->foreground_pf = FOREGROUND_PPF_ARGB8888;
foreground_struct->foreground_prered = IPA_DEFAULT_VALUE;
foreground_struct->foreground_pregreen = IPA_DEFAULT_VALUE;
foreground_struct->foreground_preblue = IPA_DEFAULT_VALUE;
}
/*!
\brief initialize foreground parameters
\param[in] foreground_struct: the data needed to initialize foreground
foreground_memaddr: foreground memory base address
foreground_lineoff: foreground line offset
foreground_prealpha: foreground pre-defined alpha value
foreground_alpha_algorithm: IPA_FG_ALPHA_MODE_0,IPA_FG_ALPHA_MODE_1,IPA_FG_ALPHA_MODE_2
foreground_pf: foreground pixel format(FOREGROUND_PPF_ARGB8888,FOREGROUND_PPF_RGB888,FOREGROUND_PPF_RGB565,
FOREGROUND_PPF_ARG1555,FOREGROUND_PPF_ARGB4444,FOREGROUND_PPF_L8,FOREGROUND_PPF_AL44,
FOREGROUND_PPF_AL88,FOREGROUND_PPF_L4,FOREGROUND_PPF_A8,FOREGROUND_PPF_A4)
foreground_prered: foreground pre-defined red value
foreground_pregreen: foreground pre-defined green value
foreground_preblue: foreground pre-defined blue value
\param[out] none
\retval none
*/
void ipa_foreground_init(ipa_foreground_parameter_struct *foreground_struct)
{
FlagStatus tempflag = RESET;
if(RESET != (IPA_CTL & IPA_CTL_TEN)) {
tempflag = SET;
/* reset the TEN in order to configure the following bits */
IPA_CTL &= ~IPA_CTL_TEN;
}
/* foreground memory base address configuration */
IPA_FMADDR &= ~(IPA_FMADDR_FMADDR);
IPA_FMADDR = foreground_struct->foreground_memaddr;
/* foreground line offset configuration */
IPA_FLOFF &= ~(IPA_FLOFF_FLOFF);
IPA_FLOFF = foreground_struct->foreground_lineoff;
/* foreground pixel format pre-defined alpha, alpha calculation algorithm configuration */
IPA_FPCTL &= ~(IPA_FPCTL_FPDAV | IPA_FPCTL_FAVCA | IPA_FPCTL_FPF);
IPA_FPCTL |= (foreground_struct->foreground_prealpha << 24U);
IPA_FPCTL |= foreground_struct->foreground_alpha_algorithm;
IPA_FPCTL |= foreground_struct->foreground_pf;
/* foreground pre-defined red green blue configuration */
IPA_FPV &= ~(IPA_FPV_FPDRV | IPA_FPV_FPDGV | IPA_FPV_FPDBV);
IPA_FPV |= ((foreground_struct->foreground_prered << 16U) | (foreground_struct->foreground_pregreen << 8U)
| (foreground_struct->foreground_preblue));
if(SET == tempflag) {
/* restore the state of TEN */
IPA_CTL |= IPA_CTL_TEN;
}
}
/*!
\brief initialize the structure of IPA background parameter struct with the default values, it is
suggested that call this function after an ipa_background_parameter_struct structure is defined
\param[in] none
\param[out] background_struct: the data needed to initialize background
background_memaddr: background memory base address
background_lineoff: background line offset
background_prealpha: background pre-defined alpha value
background_alpha_algorithm: IPA_BG_ALPHA_MODE_0,IPA_BG_ALPHA_MODE_1,IPA_BG_ALPHA_MODE_2
background_pf: background pixel format(BACKGROUND_PPF_ARGB8888,BACKGROUND_PPF_RGB888,BACKGROUND_PPF_RGB565,
BACKGROUND_PPF_ARG1555,BACKGROUND_PPF_ARGB4444,BACKGROUND_PPF_L8,BACKGROUND_PPF_AL44,
BACKGROUND_PPF_AL88,BACKGROUND_PPF_L4,BACKGROUND_PPF_A8,BACKGROUND_PPF_A4)
background_prered: background pre-defined red value
background_pregreen: background pre-defined green value
background_preblue: background pre-defined blue value
\retval none
*/
void ipa_background_struct_para_init(ipa_background_parameter_struct *background_struct)
{
/* initialize the struct parameters with default values */
background_struct->background_memaddr = IPA_DEFAULT_VALUE;
background_struct->background_lineoff = IPA_DEFAULT_VALUE;
background_struct->background_prealpha = IPA_DEFAULT_VALUE;
background_struct->background_alpha_algorithm = IPA_BG_ALPHA_MODE_0;
background_struct->background_pf = BACKGROUND_PPF_ARGB8888;
background_struct->background_prered = IPA_DEFAULT_VALUE;
background_struct->background_pregreen = IPA_DEFAULT_VALUE;
background_struct->background_preblue = IPA_DEFAULT_VALUE;
}
/*!
\brief initialize background parameters
\param[in] background_struct: the data needed to initialize background
background_memaddr: background memory base address
background_lineoff: background line offset
background_prealpha: background pre-defined alpha value
background_alpha_algorithm: IPA_BG_ALPHA_MODE_0,IPA_FG_ALPHA_MODE_1,IPA_FG_ALPHA_MODE_2
background_pf: background pixel format(BACKGROUND_PPF_ARGB8888,BACKGROUND_PPF_RGB888,BACKGROUND_PPF_RGB565,
BACKGROUND_PPF_ARG1555,BACKGROUND_PPF_ARGB4444,BACKGROUND_PPF_L8,BACKGROUND_PPF_AL44,
BACKGROUND_PPF_AL88,BACKGROUND_PPF_L4,BACKGROUND_PPF_A8,BACKGROUND_PPF_A4)
background_prered: background pre-defined red value
background_pregreen: background pre-defined green value
background_preblue: background pre-defined blue value
\param[out] none
\retval none
*/
void ipa_background_init(ipa_background_parameter_struct *background_struct)
{
FlagStatus tempflag = RESET;
if(RESET != (IPA_CTL & IPA_CTL_TEN)) {
tempflag = SET;
/* reset the TEN in order to configure the following bits */
IPA_CTL &= ~IPA_CTL_TEN;
}
/* background memory base address configuration */
IPA_BMADDR &= ~(IPA_BMADDR_BMADDR);
IPA_BMADDR = background_struct->background_memaddr;
/* background line offset configuration */
IPA_BLOFF &= ~(IPA_BLOFF_BLOFF);
IPA_BLOFF = background_struct->background_lineoff;
/* background pixel format pre-defined alpha, alpha calculation algorithm configuration */
IPA_BPCTL &= ~(IPA_BPCTL_BPDAV | IPA_BPCTL_BAVCA | IPA_BPCTL_BPF);
IPA_BPCTL |= (background_struct->background_prealpha << 24U);
IPA_BPCTL |= background_struct->background_alpha_algorithm;
IPA_BPCTL |= background_struct->background_pf;
/* background pre-defined red green blue configuration */
IPA_BPV &= ~(IPA_BPV_BPDRV | IPA_BPV_BPDGV | IPA_BPV_BPDBV);
IPA_BPV |= ((background_struct->background_prered << 16U) | (background_struct->background_pregreen << 8U)
| (background_struct->background_preblue));
if(SET == tempflag) {
/* restore the state of TEN */
IPA_CTL |= IPA_CTL_TEN;
}
}
/*!
\brief initialize the structure of IPA destination parameter struct with the default values, it is
suggested that call this function after an ipa_destination_parameter_struct structure is defined
\param[in] none
\param[out] destination_struct: the data needed to initialize destination parameter
destination_pf: IPA_DPF_ARGB8888,IPA_DPF_RGB888,IPA_DPF_RGB565,IPA_DPF_ARGB1555,
IPA_DPF_ARGB4444,refer to ipa_dpf_enum
destination_lineoff: destination line offset
destination_prealpha: destination pre-defined alpha value
destination_prered: destination pre-defined red value
destination_pregreen: destination pre-defined green value
destination_preblue: destination pre-defined blue value
destination_memaddr: destination memory base address
image_width: width of the image to be processed
image_height: height of the image to be processed
\retval none
*/
void ipa_destination_struct_para_init(ipa_destination_parameter_struct *destination_struct)
{
/* initialize the struct parameters with default values */
destination_struct->destination_pf = IPA_DPF_ARGB8888;
destination_struct->destination_lineoff = IPA_DEFAULT_VALUE;
destination_struct->destination_prealpha = IPA_DEFAULT_VALUE;
destination_struct->destination_prered = IPA_DEFAULT_VALUE;
destination_struct->destination_pregreen = IPA_DEFAULT_VALUE;
destination_struct->destination_preblue = IPA_DEFAULT_VALUE;
destination_struct->destination_memaddr = IPA_DEFAULT_VALUE;
destination_struct->image_width = IPA_DEFAULT_VALUE;
destination_struct->image_height = IPA_DEFAULT_VALUE;
}
/*!
\brief initialize destination parameters
\param[in] destination_struct: the data needed to initialize destination parameters
destination_pf: IPA_DPF_ARGB8888,IPA_DPF_RGB888,IPA_DPF_RGB565,IPA_DPF_ARGB1555,
IPA_DPF_ARGB4444,refer to ipa_dpf_enum
destination_lineoff: destination line offset
destination_prealpha: destination pre-defined alpha value
destination_prered: destination pre-defined red value
destination_pregreen: destination pre-defined green value
destination_preblue: destination pre-defined blue value
destination_memaddr: destination memory base address
image_width: width of the image to be processed
image_height: height of the image to be processed
\param[out] none
\retval none
*/
void ipa_destination_init(ipa_destination_parameter_struct *destination_struct)
{
uint32_t destination_pixelformat;
FlagStatus tempflag = RESET;
if(RESET != (IPA_CTL & IPA_CTL_TEN)) {
tempflag = SET;
/* reset the TEN in order to configure the following bits */
IPA_CTL &= ~IPA_CTL_TEN;
}
/* destination pixel format configuration */
IPA_DPCTL &= ~(IPA_DPCTL_DPF);
IPA_DPCTL = destination_struct->destination_pf;
destination_pixelformat = destination_struct->destination_pf;
/* destination pixel format ARGB8888 */
switch(destination_pixelformat) {
case IPA_DPF_ARGB8888:
IPA_DPV &= ~(IPA_DPV_DPDBV_0 | (IPA_DPV_DPDGV_0) | (IPA_DPV_DPDRV_0) | (IPA_DPV_DPDAV_0));
IPA_DPV = (destination_struct->destination_preblue | (destination_struct->destination_pregreen << 8U)
| (destination_struct->destination_prered << 16U)
| (destination_struct->destination_prealpha << 24U));
break;
/* destination pixel format RGB888 */
case IPA_DPF_RGB888:
IPA_DPV &= ~(IPA_DPV_DPDBV_1 | (IPA_DPV_DPDGV_1) | (IPA_DPV_DPDRV_1));
IPA_DPV = (destination_struct->destination_preblue | (destination_struct->destination_pregreen << 8U)
| (destination_struct->destination_prered << 16U));
break;
/* destination pixel format RGB565 */
case IPA_DPF_RGB565:
IPA_DPV &= ~(IPA_DPV_DPDBV_2 | (IPA_DPV_DPDGV_2) | (IPA_DPV_DPDRV_2));
IPA_DPV = (destination_struct->destination_preblue | (destination_struct->destination_pregreen << 5U)
| (destination_struct->destination_prered << 11U));
break;
/* destination pixel format ARGB1555 */
case IPA_DPF_ARGB1555:
IPA_DPV &= ~(IPA_DPV_DPDBV_3 | (IPA_DPV_DPDGV_3) | (IPA_DPV_DPDRV_3) | (IPA_DPV_DPDAV_3));
IPA_DPV = (destination_struct->destination_preblue | (destination_struct->destination_pregreen << 5U)
| (destination_struct->destination_prered << 10U)
| (destination_struct->destination_prealpha << 15U));
break;
/* destination pixel format ARGB4444 */
case IPA_DPF_ARGB4444:
IPA_DPV &= ~(IPA_DPV_DPDBV_4 | (IPA_DPV_DPDGV_4) | (IPA_DPV_DPDRV_4) | (IPA_DPV_DPDAV_4));
IPA_DPV = (destination_struct->destination_preblue | (destination_struct->destination_pregreen << 4U)
| (destination_struct->destination_prered << 8U)
| (destination_struct->destination_prealpha << 12U));
break;
default:
break;
}
/* destination memory base address configuration */
IPA_DMADDR &= ~(IPA_DMADDR_DMADDR);
IPA_DMADDR = destination_struct->destination_memaddr;
/* destination line offset configuration */
IPA_DLOFF &= ~(IPA_DLOFF_DLOFF);
IPA_DLOFF = destination_struct->destination_lineoff;
/* image size configuration */
IPA_IMS &= ~(IPA_IMS_HEIGHT | IPA_IMS_WIDTH);
IPA_IMS |= ((destination_struct->image_width << 16U) | (destination_struct->image_height));
if(SET == tempflag) {
/* restore the state of TEN */
IPA_CTL |= IPA_CTL_TEN;
}
}
/*!
\brief initialize IPA foreground LUT parameters
\param[in] fg_lut_num: foreground LUT number of pixel
\param[in] fg_lut_pf: foreground LUT pixel format(IPA_LUT_PF_ARGB8888, IPA_LUT_PF_RGB888)
\param[in] fg_lut_addr: foreground LUT memory base address
\param[out] none
\retval none
*/
void ipa_foreground_lut_init(uint8_t fg_lut_num, uint8_t fg_lut_pf, uint32_t fg_lut_addr)
{
FlagStatus tempflag = RESET;
if(RESET != (IPA_FPCTL & IPA_FPCTL_FLLEN)) {
tempflag = SET;
/* reset the FLLEN in order to configure the following bits */
IPA_FPCTL &= ~IPA_FPCTL_FLLEN;
}
/* foreground LUT number of pixel configuration */
IPA_FPCTL |= ((uint32_t)fg_lut_num << 8U);
/* foreground LUT pixel format configuration */
if(IPA_LUT_PF_RGB888 == fg_lut_pf) {
IPA_FPCTL |= IPA_FPCTL_FLPF;
} else {
IPA_FPCTL &= ~(IPA_FPCTL_FLPF);
}
/* foreground LUT memory base address configuration */
IPA_FLMADDR &= ~(IPA_FLMADDR_FLMADDR);
IPA_FLMADDR = fg_lut_addr;
if(SET == tempflag) {
/* restore the state of FLLEN */
IPA_FPCTL |= IPA_FPCTL_FLLEN;
}
}
/*!
\brief initialize IPA background LUT parameters
\param[in] bg_lut_num: background LUT number of pixel
\param[in] bg_lut_pf: background LUT pixel format(IPA_LUT_PF_ARGB8888, IPA_LUT_PF_RGB888)
\param[in] bg_lut_addr: background LUT memory base address
\param[out] none
\retval none
*/
void ipa_background_lut_init(uint8_t bg_lut_num, uint8_t bg_lut_pf, uint32_t bg_lut_addr)
{
FlagStatus tempflag = RESET;
if(RESET != (IPA_BPCTL & IPA_BPCTL_BLLEN)) {
tempflag = SET;
/* reset the BLLEN in order to configure the following bits */
IPA_BPCTL &= ~IPA_BPCTL_BLLEN;
}
/* background LUT number of pixel configuration */
IPA_BPCTL |= ((uint32_t)bg_lut_num << 8U);
/* background LUT pixel format configuration */
if(IPA_LUT_PF_RGB888 == bg_lut_pf) {
IPA_BPCTL |= IPA_BPCTL_BLPF;
} else {
IPA_BPCTL &= ~(IPA_BPCTL_BLPF);
}
/* background LUT memory base address configuration */
IPA_BLMADDR &= ~(IPA_BLMADDR_BLMADDR);
IPA_BLMADDR = bg_lut_addr;
if(SET == tempflag) {
/* restore the state of BLLEN */
IPA_BPCTL |= IPA_BPCTL_BLLEN;
}
}
/*!
\brief configure IPA line mark
\param[in] line_num: line number
\param[out] none
\retval none
*/
void ipa_line_mark_config(uint16_t line_num)
{
IPA_LM &= ~(IPA_LM_LM);
IPA_LM = line_num;
}
/*!
\brief inter-timer enable or disable
\param[in] timer_cfg: IPA_INTER_TIMER_ENABLE,IPA_INTER_TIMER_DISABLE
\param[out] none
\retval none
*/
void ipa_inter_timer_config(uint8_t timer_cfg)
{
if(IPA_INTER_TIMER_ENABLE == timer_cfg) {
IPA_ITCTL |= IPA_ITCTL_ITEN;
} else {
IPA_ITCTL &= ~(IPA_ITCTL_ITEN);
}
}
/*!
\brief configure the number of clock cycles interval
\param[in] clk_num: the number of clock cycles
\param[out] none
\retval none
*/
void ipa_interval_clock_num_config(uint8_t clk_num)
{
/* NCCI[7:0] bits have no meaning if ITEN is '0' */
IPA_ITCTL &= ~(IPA_ITCTL_NCCI);
IPA_ITCTL |= ((uint32_t)clk_num << 8U);
}
/*!
\brief get IPA flag status in IPA_INTF register
\param[in] flag: IPA flags
one or more parameters can be selected which are shown as below:
\arg IPA_FLAG_TAE: transfer access error interrupt flag
\arg IPA_FLAG_FTF: full transfer finish interrupt flag
\arg IPA_FLAG_TLM: transfer line mark interrupt flag
\arg IPA_FLAG_LAC: LUT access conflict interrupt flag
\arg IPA_FLAG_LLF: LUT loading finish interrupt flag
\arg IPA_FLAG_WCF: wrong configuration interrupt flag
\param[out] none
\retval none
*/
FlagStatus ipa_flag_get(uint32_t flag)
{
if(RESET != (IPA_INTF & flag)) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear IPA flag in IPA_INTF register
\param[in] flag: IPA flags
one or more parameters can be selected which are shown as below:
\arg IPA_FLAG_TAE: transfer access error interrupt flag
\arg IPA_FLAG_FTF: full transfer finish interrupt flag
\arg IPA_FLAG_TLM: transfer line mark interrupt flag
\arg IPA_FLAG_LAC: LUT access conflict interrupt flag
\arg IPA_FLAG_LLF: LUT loading finish interrupt flag
\arg IPA_FLAG_WCF: wrong configuration interrupt flag
\param[out] none
\retval none
*/
void ipa_flag_clear(uint32_t flag)
{
IPA_INTC |= (flag);
}
/*!
\brief enable IPA interrupt
\param[in] int_flag: IPA interrupt flags
one or more parameters can be selected which are shown as below:
\arg IPA_INT_TAE: transfer access error interrupt
\arg IPA_INT_FTF: full transfer finish interrupt
\arg IPA_INT_TLM: transfer line mark interrupt
\arg IPA_INT_LAC: LUT access conflict interrupt
\arg IPA_INT_LLF: LUT loading finish interrupt
\arg IPA_INT_WCF: wrong configuration interrupt
\param[out] none
\retval none
*/
void ipa_interrupt_enable(uint32_t int_flag)
{
IPA_CTL |= (int_flag);
}
/*!
\brief disable IPA interrupt
\param[in] int_flag: IPA interrupt flags
one or more parameters can be selected which are shown as below:
\arg IPA_INT_TAE: transfer access error interrupt
\arg IPA_INT_FTF: full transfer finish interrupt
\arg IPA_INT_TLM: transfer line mark interrupt
\arg IPA_INT_LAC: LUT access conflict interrupt
\arg IPA_INT_LLF: LUT loading finish interrupt
\arg IPA_INT_WCF: wrong configuration interrupt
\param[out] none
\retval none
*/
void ipa_interrupt_disable(uint32_t int_flag)
{
IPA_CTL &= ~(int_flag);
}
/*!
\brief get IPA interrupt flag
\param[in] int_flag: IPA interrupt flag flags
one or more parameters can be selected which are shown as below:
\arg IPA_INT_FLAG_TAE: transfer access error interrupt flag
\arg IPA_INT_FLAG_FTF: full transfer finish interrupt flag
\arg IPA_INT_FLAG_TLM: transfer line mark interrupt flag
\arg IPA_INT_FLAG_LAC: LUT access conflict interrupt flag
\arg IPA_INT_FLAG_LLF: LUT loading finish interrupt flag
\arg IPA_INT_FLAG_WCF: wrong configuration interrupt flag
\param[out] none
\retval none
*/
FlagStatus ipa_interrupt_flag_get(uint32_t int_flag)
{
if(0U != (IPA_INTF & int_flag)) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear IPA interrupt flag
\param[in] int_flag: IPA interrupt flag flags
one or more parameters can be selected which are shown as below:
\arg IPA_INT_FLAG_TAE: transfer access error interrupt flag
\arg IPA_INT_FLAG_FTF: full transfer finish interrupt flag
\arg IPA_INT_FLAG_TLM: transfer line mark interrupt flag
\arg IPA_INT_FLAG_LAC: LUT access conflict interrupt flag
\arg IPA_INT_FLAG_LLF: LUT loading finish interrupt flag
\arg IPA_INT_FLAG_WCF: wrong configuration interrupt flag
\param[out] none
\retval none
*/
void ipa_interrupt_flag_clear(uint32_t int_flag)
{
IPA_INTC |= (int_flag);
}
@@ -0,0 +1,124 @@
/*!
\file gd32f4xx_iref.c
\brief IREF driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_iref.h"
/*!
\brief deinitialize IREF
\param[in] none
\param[out] none
\retval none
*/
void iref_deinit(void)
{
rcu_periph_reset_enable(RCU_IREFRST);
rcu_periph_reset_disable(RCU_IREFRST);
}
/*!
\brief enable IREF
\param[in] none
\param[out] none
\retval none
*/
void iref_enable(void)
{
IREF_CTL |= IREF_CTL_CREN;
}
/*!
\brief disable IREF
\param[in] none
\param[out] none
\retval none
*/
void iref_disable(void)
{
IREF_CTL &= ~IREF_CTL_CREN;
}
/*!
\brief set IREF mode
\param[in] step
\arg IREF_MODE_LOW_POWER: 1uA step
\arg IREF_MODE_HIGH_CURRENT: 8uA step
\param[out] none
\retval none
*/
void iref_mode_set(uint32_t step)
{
IREF_CTL &= ~IREF_CTL_SSEL;
IREF_CTL |= step;
}
/*!
\brief set IREF precision_trim_value
\param[in] precisiontrim
\arg IREF_CUR_PRECISION_TRIM_X(x=0..31): (-15+ x)%
\param[out] none
\retval none
*/
void iref_precision_trim_value_set(uint32_t precisiontrim)
{
IREF_CTL &= ~IREF_CTL_CPT;
IREF_CTL |= precisiontrim;
}
/*!
\brief set IREF sink mode
\param[in] sinkmode
\arg IREF_SOURCE_CURRENT : source current.
\arg IREF_SINK_CURRENT: sink current
\param[out] none
\retval none
*/
void iref_sink_set(uint32_t sinkmode)
{
IREF_CTL &= ~IREF_CTL_SCMOD;
IREF_CTL |= sinkmode;
}
/*!
\brief set IREF step data
\param[in] stepdata
\arg IREF_CUR_STEP_DATA_X:(x=0..63): step*x
\param[out] none
\retval none
*/
void iref_step_data_config(uint32_t stepdata)
{
IREF_CTL &= ~IREF_CTL_CSDT;
IREF_CTL |= stepdata;
}
@@ -0,0 +1,172 @@
/*!
\file gd32f4xx_misc.c
\brief MISC driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_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)
{
/* set the priority group value */
SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup;
}
/*!
\brief enable NVIC 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)
{
uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U;
/* 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 |= nvic_irq_sub_priority & (0x0FU >> (0x4U - temp_sub));
temp_priority = temp_priority << 0x04U;
NVIC->IP[nvic_irq] = (uint8_t)temp_priority;
/* enable the selected IRQ */
NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU);
}
/*!
\brief disable NVIC 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->ICER[nvic_irq >> 0x05] = (uint32_t)0x01 << (nvic_irq & (uint8_t)0x1F);
}
/*!
\brief set the NVIC vector table base address
\param[in] nvic_vict_tab: the RAM or FLASH base address
\arg NVIC_VECTTAB_RAM: RAM base address
\are 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_vict_tab, uint32_t offset)
{
SCB->VTOR = nvic_vict_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 lowpower 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)
{
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 lowpower mode only can be
woke up by the enable interrupts
\param[out] none
\retval none
*/
void system_lowpower_reset(uint8_t lowpower_mode)
{
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_HCLK: systick clock source is from HCLK
\arg SYSTICK_CLKSOURCE_HCLK_DIV8: systick clock source is from HCLK/8
\param[out] none
\retval none
*/
void systick_clksource_set(uint32_t systick_clksource)
{
if(SYSTICK_CLKSOURCE_HCLK == systick_clksource) {
/* set the systick clock source from HCLK */
SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;
} else {
/* set the systick clock source from HCLK/8 */
SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8;
}
}
@@ -0,0 +1,410 @@
/*!
\file gd32f4xx_pmu.c
\brief PMU driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_pmu.h"
#include "core_cm4.h"
/*!
\brief reset PMU registers
\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:
\arg PMU_LVDT_0: voltage threshold is 2.1V
\arg PMU_LVDT_1: voltage threshold is 2.3V
\arg PMU_LVDT_2: voltage threshold is 2.4V
\arg PMU_LVDT_3: voltage threshold is 2.6V
\arg PMU_LVDT_4: voltage threshold is 2.7V
\arg PMU_LVDT_5: voltage threshold is 2.9V
\arg PMU_LVDT_6: voltage threshold is 3.0V
\arg PMU_LVDT_7: voltage threshold is 3.1V
\param[out] none
\retval none
*/
void pmu_lvd_select(uint32_t lvdt_n)
{
/* disable LVD */
PMU_CTL &= ~PMU_CTL_LVDEN;
/* clear LVDT bits */
PMU_CTL &= ~PMU_CTL_LVDT;
/* set LVDT bits according to pmu_lvdt_n */
PMU_CTL |= lvdt_n;
/* enable LVD */
PMU_CTL |= PMU_CTL_LVDEN;
}
/*!
\brief disable PMU lvd
\param[in] none
\param[out] none
\retval none
*/
void pmu_lvd_disable(void)
{
/* disable LVD */
PMU_CTL &= ~PMU_CTL_LVDEN;
}
/*!
\brief select LDO output voltage
this bit set by software when the main PLL closed, before closing PLL, change the system clock to IRC16M or HXTAL
\param[in] ldo_output:
\arg PMU_LDOVS_LOW: low-driver mode enable in deep-sleep mode
\arg PMU_LDOVS_MID: mid-driver mode disable in deep-sleep mode
\arg PMU_LDOVS_HIGH: high-driver mode disable in deep-sleep mode
\param[out] none
\retval none
*/
void pmu_ldo_output_select(uint32_t ldo_output)
{
PMU_CTL &= ~PMU_CTL_LDOVS;
PMU_CTL |= ldo_output;
}
/*!
\brief enable high-driver mode
this bit set by software only when IRC16M or HXTAL used as system clock
\param[in] none
\param[out] none
\retval none
*/
void pmu_highdriver_mode_enable(void)
{
PMU_CTL |= PMU_CTL_HDEN;
}
/*!
\brief disable high-driver mode
\param[in] none
\param[out] none
\retval none
*/
void pmu_highdriver_mode_disable(void)
{
PMU_CTL &= ~PMU_CTL_HDEN;
}
/*!
\brief switch high-driver mode
this bit set by software only when IRC16M or HXTAL used as system clock
\param[in] highdr_switch:
\arg PMU_HIGHDR_SWITCH_NONE: disable high-driver mode switch
\arg PMU_HIGHDR_SWITCH_EN: enable high-driver mode switch
\param[out] none
\retval none
*/
void pmu_highdriver_switch_select(uint32_t highdr_switch)
{
/* wait for HDRF flag set */
while(SET != pmu_flag_get(PMU_FLAG_HDRF)) {
}
PMU_CTL &= ~PMU_CTL_HDS;
PMU_CTL |= highdr_switch;
}
/*!
\brief enable low-driver mode in deep-sleep
\param[in] none
\param[out] none
\retval none
*/
void pmu_lowdriver_mode_enable(void)
{
PMU_CTL |= PMU_CTL_LDEN;
}
/*!
\brief disable low-driver mode in deep-sleep
\param[in] none
\param[out] none
\retval none
*/
void pmu_lowdriver_mode_disable(void)
{
PMU_CTL &= ~PMU_CTL_LDEN;
}
/*!
\brief in deep-sleep mode, driver mode when use low power LDO
\param[in] mode:
\arg PMU_NORMALDR_LOWPWR: normal driver when use low power LDO
\arg PMU_LOWDR_LOWPWR: low-driver mode enabled when LDEN is 11 and use low power LDO
\param[out] none
\retval none
*/
void pmu_lowpower_driver_config(uint32_t mode)
{
PMU_CTL &= ~PMU_CTL_LDLP;
PMU_CTL |= mode;
}
/*!
\brief in deep-sleep mode, driver mode when use normal power LDO
\param[in] mode:
\arg PMU_NORMALDR_NORMALPWR: normal driver when use normal power LDO
\arg PMU_LOWDR_NORMALPWR: low-driver mode enabled when LDEN is 11 and use normal power LDO
\param[out] none
\retval none
*/
void pmu_normalpower_driver_config(uint32_t mode)
{
PMU_CTL &= ~PMU_CTL_LDNP;
PMU_CTL |= mode;
}
/*!
\brief PMU work in sleep mode
\param[in] sleepmodecmd:
\arg WFI_CMD: use WFI command
\arg WFE_CMD: use WFE command
\param[out] none
\retval none
*/
void pmu_to_sleepmode(uint8_t sleepmodecmd)
{
/* clear sleepdeep bit of Cortex-M4 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 {
__WFE();
}
}
/*!
\brief PMU work in deep-sleep mode
\param[in] ldo
\arg PMU_LDO_NORMAL: LDO normal work when pmu enter deep-sleep mode
\arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deep-sleep mode
\param[in] lowdrive:
only one parameter can be selected which is shown as below:
\arg PMU_LOWDRIVER_DISABLE: Low-driver mode disable in deep-sleep mode
\arg PMU_LOWDRIVER_ENABLE: Low-driver mode enable in deep-sleep mode
\param[in] deepsleepmodecmd:
\arg WFI_CMD: use WFI command
\arg WFE_CMD: use WFE command
\param[out] none
\retval none
*/
void pmu_to_deepsleepmode(uint32_t ldo, uint32_t lowdrive, uint8_t deepsleepmodecmd)
{
static uint32_t reg_snap[4];
/* clear stbmod and ldolp bits */
PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP | PMU_CTL_LDEN | PMU_CTL_LDNP | PMU_CTL_LDLP));
/* set ldolp bit according to pmu_ldo */
PMU_CTL |= ldo;
/* configure low drive mode in deep-sleep mode */
if(PMU_LOWDRIVER_ENABLE == lowdrive) {
if(PMU_LDO_NORMAL == ldo) {
PMU_CTL |= (uint32_t)(PMU_CTL_LDEN | PMU_CTL_LDNP);
} else {
PMU_CTL |= (uint32_t)(PMU_CTL_LDEN | PMU_CTL_LDLP);
}
}
/* set sleepdeep bit of Cortex-M4 system control register */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
reg_snap[0] = REG32(0xE000E010U);
reg_snap[1] = REG32(0xE000E100U);
reg_snap[2] = REG32(0xE000E104U);
reg_snap[3] = REG32(0xE000E108U);
REG32(0xE000E010U) &= 0x00010004U;
REG32(0xE000E180U) = 0XFF7FF831U;
REG32(0xE000E184U) = 0XBFFFF8FFU;
REG32(0xE000E188U) = 0xFFFFEFFFU;
/* select WFI or WFE command to enter deep-sleep mode */
if(WFI_CMD == deepsleepmodecmd) {
__WFI();
} else {
__SEV();
__WFE();
__WFE();
}
REG32(0xE000E010U) = reg_snap[0];
REG32(0xE000E100U) = reg_snap[1];
REG32(0xE000E104U) = reg_snap[2];
REG32(0xE000E108U) = reg_snap[3];
/* reset sleepdeep bit of Cortex-M4 system control register */
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
}
/*!
\brief pmu work in standby mode
\param[in] none
\param[out] none
\retval none
*/
void pmu_to_standbymode(void)
{
/* set stbmod bit */
PMU_CTL |= PMU_CTL_STBMOD;
/* reset wakeup flag */
PMU_CTL |= PMU_CTL_WURST;
/* set sleepdeep bit of Cortex-M4 system control register */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
REG32(0xE000E010U) &= 0x00010004U;
REG32(0xE000E180U) = 0XFFFFFFF3U;
REG32(0xE000E184U) = 0XFFFFFDFFU;
REG32(0xE000E188U) = 0xFFFFFFFFU;
REG32(0xE000E18CU) = 0xFFFFFFFFU;
/* select WFI command to enter standby mode */
__WFI();
}
/*!
\brief enable PMU wakeup pin
\param[in] none
\param[out] none
\retval none
*/
void pmu_wakeup_pin_enable(void)
{
PMU_CS |= PMU_CS_WUPEN;
}
/*!
\brief disable PMU wakeup pin
\param[in] none
\param[out] none
\retval none
*/
void pmu_wakeup_pin_disable(void)
{
PMU_CS &= ~PMU_CS_WUPEN;
}
/*!
\brief backup SRAM LDO on
\param[in] bkp_ldo:
\arg PMU_BLDOON_OFF: backup SRAM LDO closed
\arg PMU_BLDOON_ON: open the backup SRAM LDO
\param[out] none
\retval none
*/
void pmu_backup_ldo_config(uint32_t bkp_ldo)
{
PMU_CS &= ~PMU_CS_BLDOON;
PMU_CS |= bkp_ldo;
}
/*!
\brief enable write access to the registers in backup domain
\param[in] none
\param[out] none
\retval none
*/
void pmu_backup_write_enable(void)
{
PMU_CTL |= PMU_CTL_BKPWEN;
}
/*!
\brief disable write access to the registers in backup domain
\param[in] none
\param[out] none
\retval none
*/
void pmu_backup_write_disable(void)
{
PMU_CTL &= ~PMU_CTL_BKPWEN;
}
/*!
\brief get flag state
\param[in] flag:
\arg PMU_FLAG_WAKEUP: wakeup flag
\arg PMU_FLAG_STANDBY: standby flag
\arg PMU_FLAG_LVD: lvd flag
\arg PMU_FLAG_BLDORF: backup SRAM LDO ready flag
\arg PMU_FLAG_LDOVSRF: LDO voltage select ready flag
\arg PMU_FLAG_HDRF: high-driver ready flag
\arg PMU_FLAG_HDSRF: high-driver switch ready flag
\arg PMU_FLAG_LDRF: low-driver mode ready flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus pmu_flag_get(uint32_t flag)
{
if(PMU_CS & flag) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear flag bit
\param[in] flag:
\arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag
\arg PMU_FLAG_RESET_STANDBY: reset standby flag
\param[out] none
\retval none
*/
void pmu_flag_clear(uint32_t flag)
{
switch(flag) {
case PMU_FLAG_RESET_WAKEUP:
/* reset wakeup flag */
PMU_CTL |= PMU_CTL_WURST;
break;
case PMU_FLAG_RESET_STANDBY:
/* reset standby flag */
PMU_CTL |= PMU_CTL_STBRST;
break;
default :
break;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,801 @@
/*!
\file gd32f4xx_sdio.c
\brief SDIO driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_sdio.h"
/*!
\brief deinitialize the SDIO
\param[in] none
\param[out] none
\retval none
*/
void sdio_deinit(void)
{
rcu_periph_reset_enable(RCU_SDIORST);
rcu_periph_reset_disable(RCU_SDIORST);
}
/*!
\brief configure the SDIO clock
\param[in] clock_edge: SDIO_CLK clock edge
only one parameter can be selected which is shown as below:
\arg SDIO_SDIOCLKEDGE_RISING: select the rising edge of the SDIOCLK to generate SDIO_CLK
\arg SDIO_SDIOCLKEDGE_FALLING: select the falling edge of the SDIOCLK to generate SDIO_CLK
\param[in] clock_bypass: clock bypass
only one parameter can be selected which is shown as below:
\arg SDIO_CLOCKBYPASS_ENABLE: clock bypass
\arg SDIO_CLOCKBYPASS_DISABLE: no bypass
\param[in] clock_powersave: SDIO_CLK clock dynamic switch on/off for power saving
only one parameter can be selected which is shown as below:
\arg SDIO_CLOCKPWRSAVE_ENABLE: SDIO_CLK closed when bus is idle
\arg SDIO_CLOCKPWRSAVE_DISABLE: SDIO_CLK clock is always on
\param[in] clock_division: clock division, less than 512
\param[out] none
\retval none
*/
void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division)
{
uint32_t clock_config = 0U;
clock_config = SDIO_CLKCTL;
/* reset the CLKEDGE, CLKBYP, CLKPWRSAV, DIV */
clock_config &= ~(SDIO_CLKCTL_CLKEDGE | SDIO_CLKCTL_CLKBYP | SDIO_CLKCTL_CLKPWRSAV | SDIO_CLKCTL_DIV8 | SDIO_CLKCTL_DIV);
/* if the clock division is greater or equal to 256, set the DIV[8] */
if(clock_division >= 256U) {
clock_config |= SDIO_CLKCTL_DIV8;
clock_division -= 256U;
}
/* configure the SDIO_CLKCTL according to the parameters */
clock_config |= (clock_edge | clock_bypass | clock_powersave | clock_division);
SDIO_CLKCTL = clock_config;
}
/*!
\brief enable hardware clock control
\param[in] none
\param[out] none
\retval none
*/
void sdio_hardware_clock_enable(void)
{
SDIO_CLKCTL |= SDIO_CLKCTL_HWCLKEN;
}
/*!
\brief disable hardware clock control
\param[in] none
\param[out] none
\retval none
*/
void sdio_hardware_clock_disable(void)
{
SDIO_CLKCTL &= ~SDIO_CLKCTL_HWCLKEN;
}
/*!
\brief set different SDIO card bus mode
\param[in] bus_mode: SDIO card bus mode
only one parameter can be selected which is shown as below:
\arg SDIO_BUSMODE_1BIT: 1-bit SDIO card bus mode
\arg SDIO_BUSMODE_4BIT: 4-bit SDIO card bus mode
\arg SDIO_BUSMODE_8BIT: 8-bit SDIO card bus mode
\param[out] none
\retval none
*/
void sdio_bus_mode_set(uint32_t bus_mode)
{
/* reset the SDIO card bus mode bits and set according to bus_mode */
SDIO_CLKCTL &= ~SDIO_CLKCTL_BUSMODE;
SDIO_CLKCTL |= bus_mode;
}
/*!
\brief set the SDIO power state
\param[in] power_state: SDIO power state
only one parameter can be selected which is shown as below:
\arg SDIO_POWER_ON: SDIO power on
\arg SDIO_POWER_OFF: SDIO power off
\param[out] none
\retval none
*/
void sdio_power_state_set(uint32_t power_state)
{
SDIO_PWRCTL = power_state;
}
/*!
\brief get the SDIO power state
\param[in] none
\param[out] none
\retval SDIO power state
\arg SDIO_POWER_ON: SDIO power on
\arg SDIO_POWER_OFF: SDIO power off
*/
uint32_t sdio_power_state_get(void)
{
return SDIO_PWRCTL;
}
/*!
\brief enable SDIO_CLK clock output
\param[in] none
\param[out] none
\retval none
*/
void sdio_clock_enable(void)
{
SDIO_CLKCTL |= SDIO_CLKCTL_CLKEN;
}
/*!
\brief disable SDIO_CLK clock output
\param[in] none
\param[out] none
\retval none
*/
void sdio_clock_disable(void)
{
SDIO_CLKCTL &= ~SDIO_CLKCTL_CLKEN;
}
/*!
\brief configure the command and response
\param[in] cmd_index: command index, refer to the related specifications
\param[in] cmd_argument: command argument, refer to the related specifications
\param[in] response_type: response type
only one parameter can be selected which is shown as below:
\arg SDIO_RESPONSETYPE_NO: no response
\arg SDIO_RESPONSETYPE_SHORT: short response
\arg SDIO_RESPONSETYPE_LONG: long response
\param[out] none
\retval none
*/
void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type)
{
uint32_t cmd_config = 0U;
/* disable the CSM */
SDIO_CMDCTL &= ~SDIO_CMDCTL_CSMEN;
/* reset the command index, command argument and response type */
SDIO_CMDAGMT &= ~SDIO_CMDAGMT_CMDAGMT;
SDIO_CMDAGMT = cmd_argument;
cmd_config = SDIO_CMDCTL;
cmd_config &= ~(SDIO_CMDCTL_CMDIDX | SDIO_CMDCTL_CMDRESP);
/* configure SDIO_CMDCTL and SDIO_CMDAGMT according to the parameters */
cmd_config |= (cmd_index | response_type);
SDIO_CMDCTL = cmd_config;
}
/*!
\brief set the command state machine wait type
\param[in] wait_type: wait type
only one parameter can be selected which is shown as below:
\arg SDIO_WAITTYPE_NO: not wait interrupt
\arg SDIO_WAITTYPE_INTERRUPT: wait interrupt
\arg SDIO_WAITTYPE_DATAEND: wait the end of data transfer
\param[out] none
\retval none
*/
void sdio_wait_type_set(uint32_t wait_type)
{
/* reset INTWAIT and WAITDEND */
SDIO_CMDCTL &= ~(SDIO_CMDCTL_INTWAIT | SDIO_CMDCTL_WAITDEND);
/* set the wait type according to wait_type */
SDIO_CMDCTL |= wait_type;
}
/*!
\brief enable the CSM(command state machine)
\param[in] none
\param[out] none
\retval none
*/
void sdio_csm_enable(void)
{
SDIO_CMDCTL |= SDIO_CMDCTL_CSMEN;
}
/*!
\brief disable the CSM(command state machine)
\param[in] none
\param[out] none
\retval none
*/
void sdio_csm_disable(void)
{
SDIO_CMDCTL &= ~SDIO_CMDCTL_CSMEN;
}
/*!
\brief get the last response command index
\param[in] none
\param[out] none
\retval last response command index
*/
uint8_t sdio_command_index_get(void)
{
return (uint8_t)SDIO_RSPCMDIDX;
}
/*!
\brief get the response for the last received command
\param[in] sdio_responsex: SDIO response
only one parameter can be selected which is shown as below:
\arg SDIO_RESPONSE0: card response[31:0]/card response[127:96]
\arg SDIO_RESPONSE1: card response[95:64]
\arg SDIO_RESPONSE2: card response[63:32]
\arg SDIO_RESPONSE3: card response[31:1], plus bit 0
\param[out] none
\retval response for the last received command
*/
uint32_t sdio_response_get(uint32_t sdio_responsex)
{
uint32_t resp_content = 0U;
switch(sdio_responsex) {
case SDIO_RESPONSE0:
resp_content = SDIO_RESP0;
break;
case SDIO_RESPONSE1:
resp_content = SDIO_RESP1;
break;
case SDIO_RESPONSE2:
resp_content = SDIO_RESP2;
break;
case SDIO_RESPONSE3:
resp_content = SDIO_RESP3;
break;
default:
break;
}
return resp_content;
}
/*!
\brief configure the data timeout, data length and data block size
\param[in] data_timeout: data timeout period in card bus clock periods
\param[in] data_length: number of data bytes to be transferred
\param[in] data_blocksize: size of data block for block transfer
only one parameter can be selected which is shown as below:
\arg SDIO_DATABLOCKSIZE_1BYTE: block size = 1 byte
\arg SDIO_DATABLOCKSIZE_2BYTES: block size = 2 bytes
\arg SDIO_DATABLOCKSIZE_4BYTES: block size = 4 bytes
\arg SDIO_DATABLOCKSIZE_8BYTES: block size = 8 bytes
\arg SDIO_DATABLOCKSIZE_16BYTES: block size = 16 bytes
\arg SDIO_DATABLOCKSIZE_32BYTES: block size = 32 bytes
\arg SDIO_DATABLOCKSIZE_64BYTES: block size = 64 bytes
\arg SDIO_DATABLOCKSIZE_128BYTES: block size = 128 bytes
\arg SDIO_DATABLOCKSIZE_256BYTES: block size = 256 bytes
\arg SDIO_DATABLOCKSIZE_512BYTES: block size = 512 bytes
\arg SDIO_DATABLOCKSIZE_1024BYTES: block size = 1024 bytes
\arg SDIO_DATABLOCKSIZE_2048BYTES: block size = 2048 bytes
\arg SDIO_DATABLOCKSIZE_4096BYTES: block size = 4096 bytes
\arg SDIO_DATABLOCKSIZE_8192BYTES: block size = 8192 bytes
\arg SDIO_DATABLOCKSIZE_16384BYTES: block size = 16384 bytes
\param[out] none
\retval none
*/
void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize)
{
/* reset data timeout, data length and data block size */
SDIO_DATATO &= ~SDIO_DATATO_DATATO;
SDIO_DATALEN &= ~SDIO_DATALEN_DATALEN;
SDIO_DATACTL &= ~SDIO_DATACTL_BLKSZ;
/* configure the related parameters of data */
SDIO_DATATO = data_timeout;
SDIO_DATALEN = data_length;
SDIO_DATACTL |= data_blocksize;
}
/*!
\brief configure the data transfer mode and direction
\param[in] transfer_mode: mode of data transfer
only one parameter can be selected which is shown as below:
\arg SDIO_TRANSMODE_BLOCK: block transfer
\arg SDIO_TRANSMODE_STREAM: stream transfer or SDIO multibyte transfer
\param[in] transfer_direction: data transfer direction, read or write
only one parameter can be selected which is shown as below:
\arg SDIO_TRANSDIRECTION_TOCARD: write data to card
\arg SDIO_TRANSDIRECTION_TOSDIO: read data from card
\param[out] none
\retval none
*/
void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction)
{
uint32_t data_trans = 0U;
/* reset the data transfer mode, transfer direction and set according to the parameters */
data_trans = SDIO_DATACTL;
data_trans &= ~(SDIO_DATACTL_TRANSMOD | SDIO_DATACTL_DATADIR);
data_trans |= (transfer_mode | transfer_direction);
SDIO_DATACTL = data_trans;
}
/*!
\brief enable the DSM(data state machine) for data transfer
\param[in] none
\param[out] none
\retval none
*/
void sdio_dsm_enable(void)
{
SDIO_DATACTL |= SDIO_DATACTL_DATAEN;
}
/*!
\brief disable the DSM(data state machine)
\param[in] none
\param[out] none
\retval none
*/
void sdio_dsm_disable(void)
{
SDIO_DATACTL &= ~SDIO_DATACTL_DATAEN;
}
/*!
\brief write data(one word) to the transmit FIFO
\param[in] data: 32-bit data write to card
\param[out] none
\retval none
*/
void sdio_data_write(uint32_t data)
{
SDIO_FIFO = data;
}
/*!
\brief read data(one word) from the receive FIFO
\param[in] none
\param[out] none
\retval received data
*/
uint32_t sdio_data_read(void)
{
return SDIO_FIFO;
}
/*!
\brief get the number of remaining data bytes to be transferred to card
\param[in] none
\param[out] none
\retval number of remaining data bytes to be transferred
*/
uint32_t sdio_data_counter_get(void)
{
return SDIO_DATACNT;
}
/*!
\brief get the number of words remaining to be written or read from FIFO
\param[in] none
\param[out] none
\retval remaining number of words
*/
uint32_t sdio_fifo_counter_get(void)
{
return SDIO_FIFOCNT;
}
/*!
\brief enable the DMA request for SDIO
\param[in] none
\param[out] none
\retval none
*/
void sdio_dma_enable(void)
{
SDIO_DATACTL |= SDIO_DATACTL_DMAEN;
}
/*!
\brief disable the DMA request for SDIO
\param[in] none
\param[out] none
\retval none
*/
void sdio_dma_disable(void)
{
SDIO_DATACTL &= ~SDIO_DATACTL_DMAEN;
}
/*!
\brief get the flags state of SDIO
\param[in] flag: flags state of SDIO
one or more parameters can be selected which are shown as below:
\arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag
\arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag
\arg SDIO_FLAG_CMDTMOUT: command response timeout flag
\arg SDIO_FLAG_DTTMOUT: data timeout flag
\arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag
\arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag
\arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag
\arg SDIO_FLAG_CMDSEND: command sent (no response required) flag
\arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag
\arg SDIO_FLAG_STBITE: start bit error in the bus flag
\arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag
\arg SDIO_FLAG_CMDRUN: command transmission in progress flag
\arg SDIO_FLAG_TXRUN: data transmission in progress flag
\arg SDIO_FLAG_RXRUN: data reception in progress flag
\arg SDIO_FLAG_TFH: transmit FIFO is half empty flag: at least 8 words can be written into the FIFO
\arg SDIO_FLAG_RFH: receive FIFO is half full flag: at least 8 words can be read in the FIFO
\arg SDIO_FLAG_TFF: transmit FIFO is full flag
\arg SDIO_FLAG_RFF: receive FIFO is full flag
\arg SDIO_FLAG_TFE: transmit FIFO is empty flag
\arg SDIO_FLAG_RFE: receive FIFO is empty flag
\arg SDIO_FLAG_TXDTVAL: data is valid in transmit FIFO flag
\arg SDIO_FLAG_RXDTVAL: data is valid in receive FIFO flag
\arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag
\arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus sdio_flag_get(uint32_t flag)
{
FlagStatus temp_flag = RESET;
if(RESET != (SDIO_STAT & flag)) {
temp_flag = SET;
}
return temp_flag;
}
/*!
\brief clear the pending flags of SDIO
\param[in] flag: flags state of SDIO
one or more parameters can be selected which are shown as below:
\arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag
\arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag
\arg SDIO_FLAG_CMDTMOUT: command response timeout flag
\arg SDIO_FLAG_DTTMOUT: data timeout flag
\arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag
\arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag
\arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag
\arg SDIO_FLAG_CMDSEND: command sent (no response required) flag
\arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag
\arg SDIO_FLAG_STBITE: start bit error in the bus flag
\arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag
\arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag
\arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag
\param[out] none
\retval none
*/
void sdio_flag_clear(uint32_t flag)
{
SDIO_INTC = flag;
}
/*!
\brief enable the SDIO interrupt
\param[in] int_flag: interrupt flags state of SDIO
one or more parameters can be selected which are shown as below:
\arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt
\arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt
\arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt
\arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt
\arg SDIO_INT_TXURE: SDIO TXURE interrupt
\arg SDIO_INT_RXORE: SDIO RXORE interrupt
\arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt
\arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt
\arg SDIO_INT_DTEND: SDIO DTEND interrupt
\arg SDIO_INT_STBITE: SDIO STBITE interrupt
\arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt
\arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt
\arg SDIO_INT_TXRUN: SDIO TXRUN interrupt
\arg SDIO_INT_RXRUN: SDIO RXRUN interrupt
\arg SDIO_INT_TFH: SDIO TFH interrupt
\arg SDIO_INT_RFH: SDIO RFH interrupt
\arg SDIO_INT_TFF: SDIO TFF interrupt
\arg SDIO_INT_RFF: SDIO RFF interrupt
\arg SDIO_INT_TFE: SDIO TFE interrupt
\arg SDIO_INT_RFE: SDIO RFE interrupt
\arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt
\arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt
\arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt
\arg SDIO_INT_ATAEND: SDIO ATAEND interrupt
\param[out] none
\retval none
*/
void sdio_interrupt_enable(uint32_t int_flag)
{
SDIO_INTEN |= int_flag;
}
/*!
\brief disable the SDIO interrupt
\param[in] int_flag: interrupt flags state of SDIO
one or more parameters can be selected which are shown as below:
\arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt
\arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt
\arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt
\arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt
\arg SDIO_INT_TXURE: SDIO TXURE interrupt
\arg SDIO_INT_RXORE: SDIO RXORE interrupt
\arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt
\arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt
\arg SDIO_INT_DTEND: SDIO DTEND interrupt
\arg SDIO_INT_STBITE: SDIO STBITE interrupt
\arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt
\arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt
\arg SDIO_INT_TXRUN: SDIO TXRUN interrupt
\arg SDIO_INT_RXRUN: SDIO RXRUN interrupt
\arg SDIO_INT_TFH: SDIO TFH interrupt
\arg SDIO_INT_RFH: SDIO RFH interrupt
\arg SDIO_INT_TFF: SDIO TFF interrupt
\arg SDIO_INT_RFF: SDIO RFF interrupt
\arg SDIO_INT_TFE: SDIO TFE interrupt
\arg SDIO_INT_RFE: SDIO RFE interrupt
\arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt
\arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt
\arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt
\arg SDIO_INT_ATAEND: SDIO ATAEND interrupt
\param[out] none
\retval none
*/
void sdio_interrupt_disable(uint32_t int_flag)
{
SDIO_INTEN &= ~int_flag;
}
/*!
\brief get the interrupt flags state of SDIO
\param[in] int_flag: interrupt flags state of SDIO
one or more parameters can be selected which are shown as below:
\arg SDIO_INT_FLAG_CCRCERR: SDIO CCRCERR interrupt flag
\arg SDIO_INT_FLAG_DTCRCERR: SDIO DTCRCERR interrupt flag
\arg SDIO_INT_FLAG_CMDTMOUT: SDIO CMDTMOUT interrupt flag
\arg SDIO_INT_FLAG_DTTMOUT: SDIO DTTMOUT interrupt flag
\arg SDIO_INT_FLAG_TXURE: SDIO TXURE interrupt flag
\arg SDIO_INT_FLAG_RXORE: SDIO RXORE interrupt flag
\arg SDIO_INT_FLAG_CMDRECV: SDIO CMDRECV interrupt flag
\arg SDIO_INT_FLAG_CMDSEND: SDIO CMDSEND interrupt flag
\arg SDIO_INT_FLAG_DTEND: SDIO DTEND interrupt flag
\arg SDIO_INT_FLAG_STBITE: SDIO STBITE interrupt flag
\arg SDIO_INT_FLAG_DTBLKEND: SDIO DTBLKEND interrupt flag
\arg SDIO_INT_FLAG_CMDRUN: SDIO CMDRUN interrupt flag
\arg SDIO_INT_FLAG_TXRUN: SDIO TXRUN interrupt flag
\arg SDIO_INT_FLAG_RXRUN: SDIO RXRUN interrupt flag
\arg SDIO_INT_FLAG_TFH: SDIO TFH interrupt flag
\arg SDIO_INT_FLAG_RFH: SDIO RFH interrupt flag
\arg SDIO_INT_FLAG_TFF: SDIO TFF interrupt flag
\arg SDIO_INT_FLAG_RFF: SDIO RFF interrupt flag
\arg SDIO_INT_FLAG_TFE: SDIO TFE interrupt flag
\arg SDIO_INT_FLAG_RFE: SDIO RFE interrupt flag
\arg SDIO_INT_FLAG_TXDTVAL: SDIO TXDTVAL interrupt flag
\arg SDIO_INT_FLAG_RXDTVAL: SDIO RXDTVAL interrupt flag
\arg SDIO_INT_FLAG_SDIOINT: SDIO SDIOINT interrupt flag
\arg SDIO_INT_FLAG_ATAEND: SDIO ATAEND interrupt flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus sdio_interrupt_flag_get(uint32_t int_flag)
{
FlagStatus temp_flag = RESET;
if(RESET != (SDIO_STAT & int_flag)) {
temp_flag = SET;
}
return temp_flag;
}
/*!
\brief clear the interrupt pending flags of SDIO
\param[in] int_flag: interrupt flags state of SDIO
one or more parameters can be selected which are shown as below:
\arg SDIO_INT_FLAG_CCRCERR: command response received (CRC check failed) flag
\arg SDIO_INT_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag
\arg SDIO_INT_FLAG_CMDTMOUT: command response timeout flag
\arg SDIO_INT_FLAG_DTTMOUT: data timeout flag
\arg SDIO_INT_FLAG_TXURE: transmit FIFO underrun error occurs flag
\arg SDIO_INT_FLAG_RXORE: received FIFO overrun error occurs flag
\arg SDIO_INT_FLAG_CMDRECV: command response received (CRC check passed) flag
\arg SDIO_INT_FLAG_CMDSEND: command sent (no response required) flag
\arg SDIO_INT_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag
\arg SDIO_INT_FLAG_STBITE: start bit error in the bus flag
\arg SDIO_INT_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag
\arg SDIO_INT_FLAG_SDIOINT: SD I/O interrupt received flag
\arg SDIO_INT_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag
\param[out] none
\retval none
*/
void sdio_interrupt_flag_clear(uint32_t int_flag)
{
SDIO_INTC = int_flag;
}
/*!
\brief enable the read wait mode(SD I/O only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_readwait_enable(void)
{
SDIO_DATACTL |= SDIO_DATACTL_RWEN;
}
/*!
\brief disable the read wait mode(SD I/O only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_readwait_disable(void)
{
SDIO_DATACTL &= ~SDIO_DATACTL_RWEN;
}
/*!
\brief enable the function that stop the read wait process(SD I/O only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_stop_readwait_enable(void)
{
SDIO_DATACTL |= SDIO_DATACTL_RWSTOP;
}
/*!
\brief disable the function that stop the read wait process(SD I/O only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_stop_readwait_disable(void)
{
SDIO_DATACTL &= ~SDIO_DATACTL_RWSTOP;
}
/*!
\brief set the read wait type(SD I/O only)
\param[in] readwait_type: SD I/O read wait type
only one parameter can be selected which is shown as below:
\arg SDIO_READWAITTYPE_CLK: read wait control by stopping SDIO_CLK
\arg SDIO_READWAITTYPE_DAT2: read wait control using SDIO_DAT[2]
\param[out] none
\retval none
*/
void sdio_readwait_type_set(uint32_t readwait_type)
{
if(SDIO_READWAITTYPE_CLK == readwait_type) {
SDIO_DATACTL |= SDIO_DATACTL_RWTYPE;
} else {
SDIO_DATACTL &= ~SDIO_DATACTL_RWTYPE;
}
}
/*!
\brief enable the SD I/O mode specific operation(SD I/O only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_operation_enable(void)
{
SDIO_DATACTL |= SDIO_DATACTL_IOEN;
}
/*!
\brief disable the SD I/O mode specific operation(SD I/O only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_operation_disable(void)
{
SDIO_DATACTL &= ~SDIO_DATACTL_IOEN;
}
/*!
\brief enable the SD I/O suspend operation(SD I/O only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_suspend_enable(void)
{
SDIO_CMDCTL |= SDIO_CMDCTL_SUSPEND;
}
/*!
\brief disable the SD I/O suspend operation(SD I/O only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_suspend_disable(void)
{
SDIO_CMDCTL &= ~SDIO_CMDCTL_SUSPEND;
}
/*!
\brief enable the CE-ATA command(CE-ATA only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_ceata_command_enable(void)
{
SDIO_CMDCTL |= SDIO_CMDCTL_ATAEN;
}
/*!
\brief disable the CE-ATA command(CE-ATA only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_ceata_command_disable(void)
{
SDIO_CMDCTL &= ~SDIO_CMDCTL_ATAEN;
}
/*!
\brief enable the CE-ATA interrupt(CE-ATA only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_ceata_interrupt_enable(void)
{
SDIO_CMDCTL &= ~SDIO_CMDCTL_NINTEN;
}
/*!
\brief disable the CE-ATA interrupt(CE-ATA only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_ceata_interrupt_disable(void)
{
SDIO_CMDCTL |= SDIO_CMDCTL_NINTEN;
}
/*!
\brief enable the CE-ATA command completion signal(CE-ATA only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_ceata_command_completion_enable(void)
{
SDIO_CMDCTL |= SDIO_CMDCTL_ENCMDC;
}
/*!
\brief disable the CE-ATA command completion signal(CE-ATA only)
\param[in] none
\param[out] none
\retval none
*/
void sdio_ceata_command_completion_disable(void)
{
SDIO_CMDCTL &= ~SDIO_CMDCTL_ENCMDC;
}
@@ -0,0 +1,890 @@
/*!
\file gd32f4xx_spi.c
\brief SPI driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_spi.h"
#include "gd32f4xx_rcu.h"
/* SPI/I2S parameter initialization mask */
#define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */
#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */
#define I2S_FULL_DUPLEX_MASK ((uint32_t)0x00000480U) /*!< I2S full duples mode configure parameter initialization mask */
/* default value */
#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /*!< default value of SPI_I2SPSC register */
/*!
\brief deinitialize SPI and I2S
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5),include I2S1_ADD and I2S2_ADD
\param[out] none
\retval none
*/
void spi_i2s_deinit(uint32_t spi_periph)
{
switch(spi_periph) {
case SPI0:
/* reset SPI0 */
rcu_periph_reset_enable(RCU_SPI0RST);
rcu_periph_reset_disable(RCU_SPI0RST);
break;
case SPI1:
/* reset SPI1,I2S1 and I2S1_ADD */
rcu_periph_reset_enable(RCU_SPI1RST);
rcu_periph_reset_disable(RCU_SPI1RST);
break;
case SPI2:
/* reset SPI2,I2S2 and I2S2_ADD */
rcu_periph_reset_enable(RCU_SPI2RST);
rcu_periph_reset_disable(RCU_SPI2RST);
break;
case SPI3:
/* reset SPI3 */
rcu_periph_reset_enable(RCU_SPI3RST);
rcu_periph_reset_disable(RCU_SPI3RST);
break;
case SPI4:
/* reset SPI4 */
rcu_periph_reset_enable(RCU_SPI4RST);
rcu_periph_reset_disable(RCU_SPI4RST);
break;
case SPI5:
/* reset SPI5 */
rcu_periph_reset_enable(RCU_SPI5RST);
rcu_periph_reset_disable(RCU_SPI5RST);
break;
default :
break;
}
}
/*!
\brief initialize the parameters of SPI struct with default values
\param[in] none
\param[out] spi_parameter_struct: the initialized struct spi_parameter_struct pointer
\retval none
*/
void spi_struct_para_init(spi_parameter_struct *spi_struct)
{
/* configure the structure with default value */
spi_struct->device_mode = SPI_SLAVE;
spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_struct->frame_size = SPI_FRAMESIZE_8BIT;
spi_struct->nss = SPI_NSS_HARD;
spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
spi_struct->prescale = SPI_PSC_2;
spi_struct->endian = SPI_ENDIAN_MSB;
}
/*!
\brief initialize SPI parameter
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] spi_struct: SPI parameter initialization stuct members of the structure
and the member values are shown as below:
device_mode: SPI_MASTER, SPI_SLAVE.
trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY,
SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT
frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT
nss: SPI_NSS_SOFT, SPI_NSS_HARD
endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB
clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE
SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE
prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256)
\param[out] none
\retval none
*/
void spi_init(uint32_t spi_periph, spi_parameter_struct *spi_struct)
{
uint32_t reg = 0U;
reg = SPI_CTL0(spi_periph);
reg &= SPI_INIT_MASK;
/* select SPI as master or slave */
reg |= spi_struct->device_mode;
/* select SPI transfer mode */
reg |= spi_struct->trans_mode;
/* select SPI frame size */
reg |= spi_struct->frame_size;
/* select SPI nss use hardware or software */
reg |= spi_struct->nss;
/* select SPI LSB or MSB */
reg |= spi_struct->endian;
/* select SPI polarity and phase */
reg |= spi_struct->clock_polarity_phase;
/* select SPI prescale to adjust transmit speed */
reg |= spi_struct->prescale;
/* write to SPI_CTL0 register */
SPI_CTL0(spi_periph) = (uint32_t)reg;
SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL);
}
/*!
\brief enable SPI
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_enable(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN;
}
/*!
\brief disable SPI
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_disable(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN);
}
/*!
\brief initialize I2S parameter
\param[in] spi_periph: SPIx(x=1,2)
\param[in] i2s_mode: I2S operation mode
only one parameter can be selected which is shown as below:
\arg I2S_MODE_SLAVETX : I2S slave transmit mode
\arg I2S_MODE_SLAVERX : I2S slave receive mode
\arg I2S_MODE_MASTERTX : I2S master transmit mode
\arg I2S_MODE_MASTERRX : I2S master receive mode
\param[in] i2s_standard: I2S standard
only one parameter can be selected which is shown as below:
\arg I2S_STD_PHILLIPS : I2S phillips standard
\arg I2S_STD_MSB : I2S MSB standard
\arg I2S_STD_LSB : I2S LSB standard
\arg I2S_STD_PCMSHORT : I2S PCM short standard
\arg I2S_STD_PCMLONG : I2S PCM long standard
\param[in] i2s_ckpl: I2S idle state clock polarity
only one parameter can be selected which is shown as below:
\arg I2S_CKPL_LOW : I2S clock polarity low level
\arg I2S_CKPL_HIGH : I2S clock polarity high level
\param[out] none
\retval none
*/
void i2s_init(uint32_t spi_periph, uint32_t i2s_mode, uint32_t i2s_standard, uint32_t i2s_ckpl)
{
uint32_t reg = 0U;
reg = SPI_I2SCTL(spi_periph);
reg &= I2S_INIT_MASK;
/* enable I2S mode */
reg |= (uint32_t)SPI_I2SCTL_I2SSEL;
/* select I2S mode */
reg |= (uint32_t)i2s_mode;
/* select I2S standard */
reg |= (uint32_t)i2s_standard;
/* select I2S polarity */
reg |= (uint32_t)i2s_ckpl;
/* write to SPI_I2SCTL register */
SPI_I2SCTL(spi_periph) = (uint32_t)reg;
}
/*!
\brief configure I2S prescale
\param[in] spi_periph: SPIx(x=1,2)
\param[in] i2s_audiosample: I2S audio sample rate
only one parameter can be selected which is shown as below:
\arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz
\arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz
\arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz
\arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz
\arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz
\arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz
\arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz
\arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz
\arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz
\param[in] i2s_frameformat: I2S data length and channel length
only one parameter can be selected which is shown as below:
\arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit
\arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit
\arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit
\arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit
\param[in] i2s_mckout: I2S master clock output
only one parameter can be selected which is shown as below:
\arg I2S_MCKOUT_ENABLE: I2S master clock output enable
\arg I2S_MCKOUT_DISABLE: I2S master clock output disable
\param[out] none
\retval none
*/
void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_frameformat, uint32_t i2s_mckout)
{
uint32_t i2sdiv = 2U, i2sof = 0U;
uint32_t clks = 0U;
uint32_t i2sclock = 0U;
#ifndef I2S_EXTERNAL_CLOCK_IN
uint32_t plli2sm = 0U, plli2sn = 0U, plli2sr = 0U;
#endif /* I2S_EXTERNAL_CLOCK_IN */
/* deinit SPI_I2SPSC register */
SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE;
#ifdef I2S_EXTERNAL_CLOCK_IN
rcu_i2s_clock_config(RCU_I2SSRC_I2S_CKIN);
/* set the I2S clock to the external clock input value */
i2sclock = I2S_EXTERNAL_CLOCK_IN;
#else
/* turn on the oscillator HXTAL */
rcu_osci_on(RCU_HXTAL);
/* wait for oscillator stabilization flags is SET */
rcu_osci_stab_wait(RCU_HXTAL);
/* turn on the PLLI2S */
rcu_osci_on(RCU_PLLI2S_CK);
/* wait for PLLI2S flags is SET */
rcu_osci_stab_wait(RCU_PLLI2S_CK);
/* configure the I2S clock source selection */
rcu_i2s_clock_config(RCU_I2SSRC_PLLI2S);
/* get the RCU_PLL_PLLPSC value */
plli2sm = (uint32_t)(RCU_PLL & RCU_PLL_PLLPSC);
/* get the RCU_PLLI2S_PLLI2SN value */
plli2sn = (uint32_t)((RCU_PLLI2S & RCU_PLLI2S_PLLI2SN) >> 6);
/* get the RCU_PLLI2S_PLLI2SR value */
plli2sr = (uint32_t)((RCU_PLLI2S & RCU_PLLI2S_PLLI2SR) >> 28);
if((RCU_PLL & RCU_PLL_PLLSEL) == RCU_PLLSRC_HXTAL) {
/* get the I2S source clock value */
i2sclock = (uint32_t)(((HXTAL_VALUE / plli2sm) * plli2sn) / plli2sr);
} else {
/* get the I2S source clock value */
i2sclock = (uint32_t)(((IRC16M_VALUE / plli2sm) * plli2sn) / plli2sr);
}
#endif /* I2S_EXTERNAL_CLOCK_IN */
/* config the prescaler depending on the mclk output state, the frame format and audio sample rate */
if(I2S_MCKOUT_ENABLE == i2s_mckout) {
clks = (uint32_t)(((i2sclock / 256U) * 10U) / i2s_audiosample);
} else {
if(I2S_FRAMEFORMAT_DT16B_CH16B == i2s_frameformat) {
clks = (uint32_t)(((i2sclock / 32U) * 10U) / i2s_audiosample);
} else {
clks = (uint32_t)(((i2sclock / 64U) * 10U) / i2s_audiosample);
}
}
/* remove the floating point */
clks = (clks + 5U) / 10U;
i2sof = (clks & 0x00000001U);
i2sdiv = ((clks - i2sof) / 2U);
i2sof = (i2sof << 8U);
/* set the default values */
if((i2sdiv < 2U) || (i2sdiv > 255U)) {
i2sdiv = 2U;
i2sof = 0U;
}
/* configure SPI_I2SPSC */
SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | i2s_mckout);
/* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */
SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN));
/* configure data frame format */
SPI_I2SCTL(spi_periph) |= (uint32_t)i2s_frameformat;
}
/*!
\brief enable I2S
\param[in] spi_periph: SPIx(x=1,2)
\param[out] none
\retval none
*/
void i2s_enable(uint32_t spi_periph)
{
SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN;
}
/*!
\brief disable I2S
\param[in] spi_periph: SPIx(x=1,2)
\param[out] none
\retval none
*/
void i2s_disable(uint32_t spi_periph)
{
SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN);
}
/*!
\brief enable SPI nss output
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_nss_output_enable(uint32_t spi_periph)
{
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV;
}
/*!
\brief disable SPI nss output
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_nss_output_disable(uint32_t spi_periph)
{
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV);
}
/*!
\brief SPI nss pin high level in software mode
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_nss_internal_high(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS;
}
/*!
\brief SPI nss pin low level in software mode
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_nss_internal_low(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS);
}
/*!
\brief enable SPI DMA send or receive
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] spi_dma: SPI DMA mode
only one parameter can be selected which is shown as below:
\arg SPI_DMA_TRANSMIT: SPI transmit data use DMA
\arg SPI_DMA_RECEIVE: SPI receive data use DMA
\param[out] none
\retval none
*/
void spi_dma_enable(uint32_t spi_periph, uint8_t spi_dma)
{
if(SPI_DMA_TRANSMIT == spi_dma) {
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN;
} else {
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN;
}
}
/*!
\brief diable SPI DMA send or receive
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] spi_dma: SPI DMA mode
only one parameter can be selected which is shown as below:
\arg SPI_DMA_TRANSMIT: SPI transmit data use DMA
\arg SPI_DMA_RECEIVE: SPI receive data use DMA
\param[out] none
\retval none
*/
void spi_dma_disable(uint32_t spi_periph, uint8_t spi_dma)
{
if(SPI_DMA_TRANSMIT == spi_dma) {
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN);
} else {
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN);
}
}
/*!
\brief configure SPI/I2S data frame format
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] frame_format: SPI frame size
only one parameter can be selected which is shown as below:
\arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits
\arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits
\param[out] none
\retval none
*/
void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format)
{
/* clear SPI_CTL0_FF16 bit */
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16);
/* configure SPI_CTL0_FF16 bit */
SPI_CTL0(spi_periph) |= (uint32_t)frame_format;
}
/*!
\brief SPI transmit data
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] data: 16-bit data
\param[out] none
\retval none
*/
void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data)
{
SPI_DATA(spi_periph) = (uint32_t)data;
}
/*!
\brief SPI receive data
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval 16-bit data
*/
uint16_t spi_i2s_data_receive(uint32_t spi_periph)
{
return ((uint16_t)SPI_DATA(spi_periph));
}
/*!
\brief configure SPI bidirectional transfer direction
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] transfer_direction: SPI transfer direction
only one parameter can be selected which is shown as below:
\arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode
\arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode
\retval none
*/
void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction)
{
if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction) {
/* set the transmit only mode */
SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT;
} else {
/* set the receive only mode */
SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE;
}
}
/*!
\brief configure i2s full duplex mode
\param[in] i2s_add_periph: I2Sx_ADD(x=1,2)
\param[in] i2s_mode:
\arg I2S_MODE_SLAVETX : I2S slave transmit mode
\arg I2S_MODE_SLAVERX : I2S slave receive mode
\arg I2S_MODE_MASTERTX : I2S master transmit mode
\arg I2S_MODE_MASTERRX : I2S master receive mode
\param[in] i2s_standard:
\arg I2S_STD_PHILLIPS : I2S phillips standard
\arg I2S_STD_MSB : I2S MSB standard
\arg I2S_STD_LSB : I2S LSB standard
\arg I2S_STD_PCMSHORT : I2S PCM short standard
\arg I2S_STD_PCMLONG : I2S PCM long standard
\param[in] i2s_ckpl:
\arg I2S_CKPL_LOW : I2S clock polarity low level
\arg I2S_CKPL_HIGH : I2S clock polarity high level
\param[in] i2s_frameformat:
\arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit
\arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit
\arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit
\arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit
\param[out] none
\retval none
*/
void i2s_full_duplex_mode_config(uint32_t i2s_add_periph, uint32_t i2s_mode, uint32_t i2s_standard,
uint32_t i2s_ckpl, uint32_t i2s_frameformat)
{
uint32_t reg = 0U, tmp = 0U;
reg = I2S_ADD_I2SCTL(i2s_add_periph);
reg &= I2S_FULL_DUPLEX_MASK;
/* get the mode of the extra I2S module I2Sx_ADD */
if((I2S_MODE_MASTERTX == i2s_mode) || (I2S_MODE_SLAVETX == i2s_mode)) {
tmp = I2S_MODE_SLAVERX;
} else {
tmp = I2S_MODE_SLAVETX;
}
/* enable I2S mode */
reg |= (uint32_t)SPI_I2SCTL_I2SSEL;
/* select I2S mode */
reg |= (uint32_t)tmp;
/* select I2S standard */
reg |= (uint32_t)i2s_standard;
/* select I2S polarity */
reg |= (uint32_t)i2s_ckpl;
/* configure data frame format */
reg |= (uint32_t)i2s_frameformat;
/* write to SPI_I2SCTL register */
I2S_ADD_I2SCTL(i2s_add_periph) = (uint32_t)reg;
}
/*!
\brief clear SPI/I2S format error flag status
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] flag: SPI/I2S frame format error flag
\arg SPI_FLAG_FERR: only for SPI work in TI mode
\arg I2S_FLAG_FERR: for I2S
\param[out] none
\retval none
*/
void spi_i2s_format_error_clear(uint32_t spi_periph, uint32_t flag)
{
SPI_STAT(spi_periph) = (uint32_t)(~flag);
}
/*!
\brief set SPI CRC polynomial
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] crc_poly: CRC polynomial value
\param[out] none
\retval none
*/
void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly)
{
/* set SPI CRC polynomial */
SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly;
}
/*!
\brief get SPI CRC polynomial
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval 16-bit CRC polynomial
*/
uint16_t spi_crc_polynomial_get(uint32_t spi_periph)
{
return ((uint16_t)SPI_CRCPOLY(spi_periph));
}
/*!
\brief turn on SPI CRC function
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_crc_on(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
}
/*!
\brief turn off SPI CRC function
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_crc_off(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN);
}
/*!
\brief SPI next data is CRC value
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_crc_next(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT;
}
/*!
\brief get SPI CRC send value or receive value
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] spi_crc: SPI crc value
only one parameter can be selected which is shown as below:
\arg SPI_CRC_TX: get transmit crc value
\arg SPI_CRC_RX: get receive crc value
\param[out] none
\retval 16-bit CRC value
*/
uint16_t spi_crc_get(uint32_t spi_periph, uint8_t spi_crc)
{
if(SPI_CRC_TX == spi_crc) {
return ((uint16_t)(SPI_TCRC(spi_periph)));
} else {
return ((uint16_t)(SPI_RCRC(spi_periph)));
}
}
/*!
\brief clear SPI CRC error flag status
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_crc_error_clear(uint32_t spi_periph)
{
SPI_STAT(spi_periph) = (uint32_t)(~SPI_FLAG_CRCERR);
}
/*!
\brief enable SPI TI mode
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_ti_mode_enable(uint32_t spi_periph)
{
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TMOD;
}
/*!
\brief disable SPI TI mode
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[out] none
\retval none
*/
void spi_ti_mode_disable(uint32_t spi_periph)
{
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TMOD);
}
/*!
\brief enable quad wire SPI
\param[in] spi_periph: SPIx(only x=5)
\param[out] none
\retval none
*/
void spi_quad_enable(uint32_t spi_periph)
{
SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD;
}
/*!
\brief disable quad wire SPI
\param[in] spi_periph: SPIx(only x=5)
\param[out] none
\retval none
*/
void spi_quad_disable(uint32_t spi_periph)
{
SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD);
}
/*!
\brief enable quad wire SPI write
\param[in] spi_periph: SPIx(only x=5)
\param[out] none
\retval none
*/
void spi_quad_write_enable(uint32_t spi_periph)
{
SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD);
}
/*!
\brief enable quad wire SPI read
\param[in] spi_periph: SPIx(only x=5)
\param[out] none
\retval none
*/
void spi_quad_read_enable(uint32_t spi_periph)
{
SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QRD;
}
/*!
\brief enable SPI_IO2 and SPI_IO3 pin output
\param[in] spi_periph: SPIx(only x=5)
\param[out] none
\retval none
*/
void spi_quad_io23_output_enable(uint32_t spi_periph)
{
SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV;
}
/*!
\brief disable SPI_IO2 and SPI_IO3 pin output
\param[in] spi_periph: SPIx(only x=5)
\param[out] none
\retval none
*/
void spi_quad_io23_output_disable(uint32_t spi_periph)
{
SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV);
}
/*!
\brief get SPI and I2S flag status
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] spi_i2s_flag: SPI/I2S flag status
only one parameter can be selected which are shown as below:
\arg SPI_FLAG_TBE: transmit buffer empty flag
\arg SPI_FLAG_RBNE: receive buffer not empty flag
\arg SPI_FLAG_TRANS: transmit on-going flag
\arg SPI_FLAG_RXORERR: receive overrun error flag
\arg SPI_FLAG_CONFERR: mode config error flag
\arg SPI_FLAG_CRCERR: CRC error flag
\arg SPI_FLAG_FERR: format error flag
\arg I2S_FLAG_TBE: transmit buffer empty flag
\arg I2S_FLAG_RBNE: receive buffer not empty flag
\arg I2S_FLAG_TRANS: transmit on-going flag
\arg I2S_FLAG_RXORERR: overrun error flag
\arg I2S_FLAG_TXURERR: underrun error flag
\arg I2S_FLAG_CH: channel side flag
\arg I2S_FLAG_FERR: format error flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag)
{
if(SPI_STAT(spi_periph) & flag) {
return SET;
} else {
return RESET;
}
}
/*!
\brief enable SPI and I2S interrupt
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] spi_i2s_int: SPI/I2S interrupt
only one parameter can be selected which is shown as below:
\arg SPI_I2S_INT_TBE: transmit buffer empty interrupt
\arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt
\arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
transmission underrun error and format error interrupt
\param[out] none
\retval none
*/
void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt)
{
switch(interrupt) {
/* SPI/I2S transmit buffer empty interrupt */
case SPI_I2S_INT_TBE:
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE;
break;
/* SPI/I2S receive buffer not empty interrupt */
case SPI_I2S_INT_RBNE:
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE;
break;
/* SPI/I2S error */
case SPI_I2S_INT_ERR:
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE;
break;
default:
break;
}
}
/*!
\brief disable SPI and I2S interrupt
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] spi_i2s_int: SPI/I2S interrupt
only one parameter can be selected which is shown as below:
\arg SPI_I2S_INT_TBE: transmit buffer empty interrupt
\arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt
\arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
transmission underrun error and format error interrupt
\param[out] none
\retval none
*/
void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt)
{
switch(interrupt) {
/* SPI/I2S transmit buffer empty interrupt */
case SPI_I2S_INT_TBE :
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE);
break;
/* SPI/I2S receive buffer not empty interrupt */
case SPI_I2S_INT_RBNE :
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE);
break;
/* SPI/I2S error */
case SPI_I2S_INT_ERR :
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE);
break;
default :
break;
}
}
/*!
\brief get SPI and I2S interrupt flag status
\param[in] spi_periph: SPIx(x=0,1,2,3,4,5)
\param[in] spi_i2s_int: SPI/I2S interrupt flag status
only one parameter can be selected which are shown as below:
\arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag
\arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag
\arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag
\arg SPI_INT_FLAG_CONFERR: config error interrupt flag
\arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag
\arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag
\arg SPI_I2S_INT_FLAG_FERR: format error interrupt flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
{
uint32_t reg1 = SPI_STAT(spi_periph);
uint32_t reg2 = SPI_CTL1(spi_periph);
switch(interrupt) {
/* SPI/I2S transmit buffer empty interrupt */
case SPI_I2S_INT_FLAG_TBE :
reg1 = reg1 & SPI_STAT_TBE;
reg2 = reg2 & SPI_CTL1_TBEIE;
break;
/* SPI/I2S receive buffer not empty interrupt */
case SPI_I2S_INT_FLAG_RBNE :
reg1 = reg1 & SPI_STAT_RBNE;
reg2 = reg2 & SPI_CTL1_RBNEIE;
break;
/* SPI/I2S overrun interrupt */
case SPI_I2S_INT_FLAG_RXORERR :
reg1 = reg1 & SPI_STAT_RXORERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* SPI config error interrupt */
case SPI_INT_FLAG_CONFERR :
reg1 = reg1 & SPI_STAT_CONFERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* SPI CRC error interrupt */
case SPI_INT_FLAG_CRCERR :
reg1 = reg1 & SPI_STAT_CRCERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* I2S underrun error interrupt */
case I2S_INT_FLAG_TXURERR :
reg1 = reg1 & SPI_STAT_TXURERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* SPI/I2S format error interrupt */
case SPI_I2S_INT_FLAG_FERR :
reg1 = reg1 & SPI_STAT_FERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
default :
break;
}
/*get SPI/I2S interrupt flag status */
if(reg1 && reg2) {
return SET;
} else {
return RESET;
}
}
@@ -0,0 +1,202 @@
/*!
\file gd32f4xx_syscfg.c
\brief SYSCFG driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_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 configure the boot mode
\param[in] syscfg_bootmode: selects the memory remapping
only one parameter can be selected which is shown as below:
\arg SYSCFG_BOOTMODE_FLASH: main flash memory (0x08000000~0x083BFFFF) is mapped at address 0x00000000
\arg SYSCFG_BOOTMODE_BOOTLOADER: boot loader (0x1FFF0000 - 0x1FFF77FF) is mapped at address 0x00000000
\arg SYSCFG_BOOTMODE_EXMC_SRAM: SRAM/NOR 0 and 1 of EXMC (0x60000000~0x67FFFFFF) is mapped at address 0x00000000
\arg SYSCFG_BOOTMODE_SRAM: SRAM0 of on-chip SRAM (0x20000000~0x2001BFFF) is mapped at address 0x00000000
\arg SYSCFG_BOOTMODE_EXMC_SDRAM: SDRAM bank0 of EXMC (0xC0000000~0xC7FFFFFF) is mapped at address 0x00000000
\param[out] none
\retval none
*/
void syscfg_bootmode_config(uint8_t syscfg_bootmode)
{
/* reset the SYSCFG_CFG0_BOOT_MODE bit and set according to syscfg_bootmode */
SYSCFG_CFG0 &= ~SYSCFG_CFG0_BOOT_MODE;
SYSCFG_CFG0 |= (uint32_t)syscfg_bootmode;
}
/*!
\brief FMC memory mapping swap
\param[in] syscfg_fmc_swap: selects the interal flash bank swapping
only one parameter can be selected which is shown as below:
\arg SYSCFG_FMC_SWP_BANK0: bank 0 is mapped at address 0x08000000 and bank 1 is mapped at address 0x08100000
\arg SYSCFG_FMC_SWP_BANK1: bank 1 is mapped at address 0x08000000 and bank 0 is mapped at address 0x08100000
\param[out] none
\retval none
*/
void syscfg_fmc_swap_config(uint32_t syscfg_fmc_swap)
{
uint32_t reg;
reg = SYSCFG_CFG0;
/* reset the FMC_SWP bit and set according to syscfg_fmc_swap */
reg &= ~SYSCFG_CFG0_FMC_SWP;
SYSCFG_CFG0 = (reg | syscfg_fmc_swap);
}
/*!
\brief EXMC memory mapping swap
\param[in] syscfg_exmc_swap: selects the memories in EXMC swapping
only one parameter can be selected which is shown as below:
\arg SYSCFG_EXMC_SWP_ENABLE: SDRAM bank 0 and bank 1 are swapped with NAND bank 1 and PC card
\arg SYSCFG_EXMC_SWP_DISABLE: no memory mapping swap
\param[out] none
\retval none
*/
void syscfg_exmc_swap_config(uint32_t syscfg_exmc_swap)
{
uint32_t reg;
reg = SYSCFG_CFG0;
/* reset the SYSCFG_CFG0_EXMC_SWP bits and set according to syscfg_exmc_swap */
reg &= ~SYSCFG_CFG0_EXMC_SWP;
SYSCFG_CFG0 = (reg | syscfg_exmc_swap);
}
/*!
\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,I): 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(x = 0..15): 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));
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 configure the PHY interface for the ethernet MAC
\param[in] syscfg_enet_phy_interface: specifies the media interface mode.
only one parameter can be selected which is shown as below:
\arg SYSCFG_ENET_PHY_MII: MII mode is selected
\arg SYSCFG_ENET_PHY_RMII: RMII mode is selected
\param[out] none
\retval none
*/
void syscfg_enet_phy_interface_config(uint32_t syscfg_enet_phy_interface)
{
uint32_t reg;
reg = SYSCFG_CFG1;
/* reset the ENET_PHY_SEL bit and set according to syscfg_enet_phy_interface */
reg &= ~SYSCFG_CFG1_ENET_PHY_SEL;
SYSCFG_CFG1 = (reg | syscfg_enet_phy_interface);
}
/*!
\brief configure the I/O compensation cell
\param[in] syscfg_compensation: specifies the I/O compensation cell mode
only one parameter can be selected which is shown as below:
\arg SYSCFG_COMPENSATION_ENABLE: I/O compensation cell is enabled
\arg SYSCFG_COMPENSATION_DISABLE: I/O compensation cell is disabled
\param[out] none
\retval none
*/
void syscfg_compensation_config(uint32_t syscfg_compensation)
{
uint32_t reg;
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_compensation);
}
/*!
\brief checks whether the I/O compensation cell ready flag is set or not
\param[in] none
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus syscfg_flag_get(void)
{
if(((uint32_t)RESET) != (SYSCFG_CPSCTL & SYSCFG_CPSCTL_CPS_RDY)) {
return SET;
} else {
return RESET;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,596 @@
/*!
\file gd32f4xx_tli.c
\brief TLI driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_tli.h"
#define TLI_DEFAULT_VALUE 0x00000000U
#define TLI_OPAQUE_VALUE 0x000000FFU
/*!
\brief deinitialize TLI registers
\param[in] none
\param[out] none
\retval none
*/
void tli_deinit(void)
{
rcu_periph_reset_enable(RCU_TLIRST);
rcu_periph_reset_disable(RCU_TLIRST);
}
/*!
\brief initialize the parameters of TLI parameter structure with the default values, it is suggested
that call this function after a tli_parameter_struct structure is defined
\param[in] none
\param[out] tli_struct: the data needed to initialize TLI
synpsz_vpsz: size of the vertical synchronous pulse
synpsz_hpsz: size of the horizontal synchronous pulse
backpsz_vbpsz: size of the vertical back porch plus synchronous pulse
backpsz_hbpsz: size of the horizontal back porch plus synchronous pulse
activesz_vasz: size of the vertical active area width plus back porch and synchronous pulse
activesz_hasz: size of the horizontal active area width plus back porch and synchronous pulse
totalsz_vtsz: vertical total size of the display, including active area, back porch, synchronous
totalsz_htsz: vorizontal total size of the display, including active area, back porch, synchronous
backcolor_red: background value red
backcolor_green: background value green
backcolor_blue: background value blue
signalpolarity_hs: TLI_HSYN_ACTLIVE_LOW,TLI_HSYN_ACTLIVE_HIGH
signalpolarity_vs: TLI_VSYN_ACTLIVE_LOW,TLI_VSYN_ACTLIVE_HIGH
signalpolarity_de: TLI_DE_ACTLIVE_LOW,TLI_DE_ACTLIVE_HIGH
signalpolarity_pixelck: TLI_PIXEL_CLOCK_TLI,TLI_PIXEL_CLOCK_INVERTEDTLI
\retval none
*/
void tli_struct_para_init(tli_parameter_struct *tli_struct)
{
/* initialize the struct parameters with default values */
tli_struct->synpsz_vpsz = TLI_DEFAULT_VALUE;
tli_struct->synpsz_hpsz = TLI_DEFAULT_VALUE;
tli_struct->backpsz_vbpsz = TLI_DEFAULT_VALUE;
tli_struct->backpsz_hbpsz = TLI_DEFAULT_VALUE;
tli_struct->activesz_vasz = TLI_DEFAULT_VALUE;
tli_struct->activesz_hasz = TLI_DEFAULT_VALUE;
tli_struct->totalsz_vtsz = TLI_DEFAULT_VALUE;
tli_struct->totalsz_htsz = TLI_DEFAULT_VALUE;
tli_struct->backcolor_red = TLI_DEFAULT_VALUE;
tli_struct->backcolor_green = TLI_DEFAULT_VALUE;
tli_struct->backcolor_blue = TLI_DEFAULT_VALUE;
tli_struct->signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW;
tli_struct->signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW;
tli_struct->signalpolarity_de = TLI_DE_ACTLIVE_LOW;
tli_struct->signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI;
}
/*!
\brief initialize TLI display timing parameters
\param[in] tli_struct: the data needed to initialize TLI
synpsz_vpsz: size of the vertical synchronous pulse
synpsz_hpsz: size of the horizontal synchronous pulse
backpsz_vbpsz: size of the vertical back porch plus synchronous pulse
backpsz_hbpsz: size of the horizontal back porch plus synchronous pulse
activesz_vasz: size of the vertical active area width plus back porch and synchronous pulse
activesz_hasz: size of the horizontal active area width plus back porch and synchronous pulse
totalsz_vtsz: vertical total size of the display, including active area, back porch, synchronous
totalsz_htsz: vorizontal total size of the display, including active area, back porch, synchronous
backcolor_red: background value red
backcolor_green: background value green
backcolor_blue: background value blue
signalpolarity_hs: TLI_HSYN_ACTLIVE_LOW,TLI_HSYN_ACTLIVE_HIGH
signalpolarity_vs: TLI_VSYN_ACTLIVE_LOW,TLI_VSYN_ACTLIVE_HIGH
signalpolarity_de: TLI_DE_ACTLIVE_LOW,TLI_DE_ACTLIVE_HIGH
signalpolarity_pixelck: TLI_PIXEL_CLOCK_TLI,TLI_PIXEL_CLOCK_INVERTEDTLI
\param[out] none
\retval none
*/
void tli_init(tli_parameter_struct *tli_struct)
{
/* synchronous pulse size configuration */
TLI_SPSZ &= ~(TLI_SPSZ_VPSZ | TLI_SPSZ_HPSZ);
TLI_SPSZ = (uint32_t)((uint32_t)tli_struct->synpsz_vpsz | ((uint32_t)tli_struct->synpsz_hpsz << 16U));
/* back-porch size configuration */
TLI_BPSZ &= ~(TLI_BPSZ_VBPSZ | TLI_BPSZ_HBPSZ);
TLI_BPSZ = (uint32_t)((uint32_t)tli_struct->backpsz_vbpsz | ((uint32_t)tli_struct->backpsz_hbpsz << 16U));
/* active size configuration */
TLI_ASZ &= ~(TLI_ASZ_VASZ | TLI_ASZ_HASZ);
TLI_ASZ = (tli_struct->activesz_vasz | (tli_struct->activesz_hasz << 16U));
/* total size configuration */
TLI_TSZ &= ~(TLI_TSZ_VTSZ | TLI_TSZ_HTSZ);
TLI_TSZ = (tli_struct->totalsz_vtsz | (tli_struct->totalsz_htsz << 16U));
/* background color configuration */
TLI_BGC &= ~(TLI_BGC_BVB | (TLI_BGC_BVG) | (TLI_BGC_BVR));
TLI_BGC = (tli_struct->backcolor_blue | (tli_struct->backcolor_green << 8U) | (tli_struct->backcolor_red << 16U));
TLI_CTL &= ~(TLI_CTL_HPPS | TLI_CTL_VPPS | TLI_CTL_DEPS | TLI_CTL_CLKPS);
TLI_CTL |= (tli_struct->signalpolarity_hs | tli_struct->signalpolarity_vs | \
tli_struct->signalpolarity_de | tli_struct->signalpolarity_pixelck);
}
/*!
\brief configure TLI dither function
\param[in] dither_stat
only one parameter can be selected which is shown as below:
\arg TLI_DITHER_ENABLE
\arg TLI_DITHER_DISABLE
\param[out] none
\retval none
*/
void tli_dither_config(uint8_t dither_stat)
{
if(TLI_DITHER_ENABLE == dither_stat) {
TLI_CTL |= TLI_CTL_DFEN;
} else {
TLI_CTL &= ~(TLI_CTL_DFEN);
}
}
/*!
\brief enable TLI
\param[in] none
\param[out] none
\retval none
*/
void tli_enable(void)
{
TLI_CTL |= TLI_CTL_TLIEN;
}
/*!
\brief disable TLI
\param[in] none
\param[out] none
\retval none
*/
void tli_disable(void)
{
TLI_CTL &= ~(TLI_CTL_TLIEN);
}
/*!
\brief configure TLI reload mode
\param[in] reload_mod
only one parameter can be selected which is shown as below:
\arg TLI_FRAME_BLANK_RELOAD_EN
\arg TLI_REQUEST_RELOAD_EN
\param[out] none
\retval none
*/
void tli_reload_config(uint8_t reload_mod)
{
if(TLI_FRAME_BLANK_RELOAD_EN == reload_mod) {
/* the layer configuration will be reloaded at frame blank */
TLI_RL |= TLI_RL_FBR;
} else {
/* the layer configuration will be reloaded after this bit sets */
TLI_RL |= TLI_RL_RQR;
}
}
/*!
\brief initialize the parameters of TLI layer structure with the default values, it is suggested
that call this function after a tli_layer_parameter_struct structure is defined
\param[in] none
\param[out] layer_struct: TLI Layer parameter struct
layer_window_rightpos: window right position
layer_window_leftpos: window left position
layer_window_bottompos: window bottom position
layer_window_toppos: window top position
layer_ppf: LAYER_PPF_ARGB8888,LAYER_PPF_RGB888,LAYER_PPF_RGB565,
LAYER_PPF_ARG1555,LAYER_PPF_ARGB4444,LAYER_PPF_L8,
LAYER_PPF_AL44,LAYER_PPF_AL88
layer_sa: specified alpha
layer_default_alpha: the default color alpha
layer_default_red: the default color red
layer_default_green: the default color green
layer_default_blue: the default color blue
layer_acf1: LAYER_ACF1_SA,LAYER_ACF1_PASA
layer_acf2: LAYER_ACF2_SA,LAYER_ACF2_PASA
layer_frame_bufaddr: frame buffer base address
layer_frame_buf_stride_offset: frame buffer stride offset
layer_frame_line_length: frame line length
layer_frame_total_line_number: frame total line number
\retval none
*/
void tli_layer_struct_para_init(tli_layer_parameter_struct *layer_struct)
{
/* initialize the struct parameters with default values */
layer_struct->layer_window_rightpos = TLI_DEFAULT_VALUE;
layer_struct->layer_window_leftpos = TLI_DEFAULT_VALUE;
layer_struct->layer_window_bottompos = TLI_DEFAULT_VALUE;
layer_struct->layer_window_toppos = TLI_DEFAULT_VALUE;
layer_struct->layer_ppf = LAYER_PPF_ARGB8888;
layer_struct->layer_sa = TLI_OPAQUE_VALUE;
layer_struct->layer_default_alpha = TLI_DEFAULT_VALUE;
layer_struct->layer_default_red = TLI_DEFAULT_VALUE;
layer_struct->layer_default_green = TLI_DEFAULT_VALUE;
layer_struct->layer_default_blue = TLI_DEFAULT_VALUE;
layer_struct->layer_acf1 = LAYER_ACF1_PASA;
layer_struct->layer_acf2 = LAYER_ACF2_PASA;
layer_struct->layer_frame_bufaddr = TLI_DEFAULT_VALUE;
layer_struct->layer_frame_buf_stride_offset = TLI_DEFAULT_VALUE;
layer_struct->layer_frame_line_length = TLI_DEFAULT_VALUE;
layer_struct->layer_frame_total_line_number = TLI_DEFAULT_VALUE;
}
/*!
\brief initialize TLI layer
\param[in] layerx: LAYERx(x=0,1)
\param[in] layer_struct: TLI Layer parameter struct
layer_window_rightpos: window right position
layer_window_leftpos: window left position
layer_window_bottompos: window bottom position
layer_window_toppos: window top position
layer_ppf: LAYER_PPF_ARGB8888,LAYER_PPF_RGB888,LAYER_PPF_RGB565,
LAYER_PPF_ARG1555,LAYER_PPF_ARGB4444,LAYER_PPF_L8,
LAYER_PPF_AL44,LAYER_PPF_AL88
layer_sa: specified alpha
layer_default_alpha: the default color alpha
layer_default_red: the default color red
layer_default_green: the default color green
layer_default_blue: the default color blue
layer_acf1: LAYER_ACF1_SA,LAYER_ACF1_PASA
layer_acf2: LAYER_ACF2_SA,LAYER_ACF2_PASA
layer_frame_bufaddr: frame buffer base address
layer_frame_buf_stride_offset: frame buffer stride offset
layer_frame_line_length: frame line length
layer_frame_total_line_number: frame total line number
\param[out] none
\retval none
*/
void tli_layer_init(uint32_t layerx, tli_layer_parameter_struct *layer_struct)
{
/* configure layer window horizontal position */
TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP | (TLI_LxHPOS_WRP));
TLI_LxHPOS(layerx) = (uint32_t)((uint32_t)layer_struct->layer_window_leftpos | ((uint32_t)layer_struct->layer_window_rightpos << 16U));
/* configure layer window vertical position */
TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP | (TLI_LxVPOS_WBP));
TLI_LxVPOS(layerx) = (uint32_t)((uint32_t)layer_struct->layer_window_toppos | ((uint32_t)layer_struct->layer_window_bottompos << 16U));
/* configure layer packeted pixel format */
TLI_LxPPF(layerx) &= ~(TLI_LxPPF_PPF);
TLI_LxPPF(layerx) = layer_struct->layer_ppf;
/* configure layer specified alpha */
TLI_LxSA(layerx) &= ~(TLI_LxSA_SA);
TLI_LxSA(layerx) = layer_struct->layer_sa;
/* configure layer default color */
TLI_LxDC(layerx) &= ~(TLI_LxDC_DCB | (TLI_LxDC_DCG) | (TLI_LxDC_DCR) | (TLI_LxDC_DCA));
TLI_LxDC(layerx) = (uint32_t)((uint32_t)layer_struct->layer_default_blue | ((uint32_t)layer_struct->layer_default_green << 8U)
| ((uint32_t)layer_struct->layer_default_red << 16U)
| ((uint32_t)layer_struct->layer_default_alpha << 24U));
/* configure layer alpha calculation factors */
TLI_LxBLEND(layerx) &= ~(TLI_LxBLEND_ACF2 | (TLI_LxBLEND_ACF1));
TLI_LxBLEND(layerx) = ((layer_struct->layer_acf2) | (layer_struct->layer_acf1));
/* configure layer frame buffer base address */
TLI_LxFBADDR(layerx) &= ~(TLI_LxFBADDR_FBADD);
TLI_LxFBADDR(layerx) = (layer_struct->layer_frame_bufaddr);
/* configure layer frame line length */
TLI_LxFLLEN(layerx) &= ~(TLI_LxFLLEN_FLL | (TLI_LxFLLEN_STDOFF));
TLI_LxFLLEN(layerx) = (uint32_t)((uint32_t)layer_struct->layer_frame_line_length | ((uint32_t)layer_struct->layer_frame_buf_stride_offset << 16U));
/* configure layer frame total line number */
TLI_LxFTLN(layerx) &= ~(TLI_LxFTLN_FTLN);
TLI_LxFTLN(layerx) = (uint32_t)(layer_struct->layer_frame_total_line_number);
}
/*!
\brief reconfigure window position
\param[in] layerx: LAYERx(x=0,1)
\param[in] offset_x: new horizontal offset
\param[in] offset_y: new vertical offset
\param[out] none
\retval none
*/
void tli_layer_window_offset_modify(uint32_t layerx, uint16_t offset_x, uint16_t offset_y)
{
/* configure window start position */
uint32_t layer_ppf, line_num, hstart, vstart;
uint32_t line_length = 0U;
TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP | (TLI_LxHPOS_WRP));
TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP | (TLI_LxVPOS_WBP));
hstart = (uint32_t)offset_x + (((TLI_BPSZ & TLI_BPSZ_HBPSZ) >> 16U) + 1U);
vstart = (uint32_t)offset_y + ((TLI_BPSZ & TLI_BPSZ_VBPSZ) + 1U);
line_num = (TLI_LxFTLN(layerx) & TLI_LxFTLN_FTLN);
layer_ppf = (TLI_LxPPF(layerx) & TLI_LxPPF_PPF);
/* the bytes of a line equal TLI_LxFLLEN_FLL bits value minus 3 */
switch(layer_ppf) {
case LAYER_PPF_ARGB8888:
/* each pixel includes 4bytes, when pixel format is ARGB8888 */
line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL) - 3U) / 4U);
break;
case LAYER_PPF_RGB888:
/* each pixel includes 3bytes, when pixel format is RGB888 */
line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL) - 3U) / 3U);
break;
case LAYER_PPF_RGB565:
case LAYER_PPF_ARGB1555:
case LAYER_PPF_ARGB4444:
case LAYER_PPF_AL88:
/* each pixel includes 2bytes, when pixel format is RGB565,ARG1555,ARGB4444 or AL88 */
line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL) - 3U) / 2U);
break;
case LAYER_PPF_L8:
case LAYER_PPF_AL44:
/* each pixel includes 1byte, when pixel format is L8 or AL44 */
line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL) - 3U));
break;
default:
break;
}
/* reconfigure window position */
TLI_LxHPOS(layerx) = (hstart | ((hstart + line_length - 1U) << 16U));
TLI_LxVPOS(layerx) = (vstart | ((vstart + line_num - 1U) << 16U));
}
/*!
\brief initialize the parameters of TLI layer LUT structure with the default values, it is suggested
that call this function after a tli_layer_lut_parameter_struct structure is defined
\param[in] none
\param[out] lut_struct: TLI layer LUT parameter struct
layer_table_addr: look up table write address
layer_lut_channel_red: red channel of a LUT entry
layer_lut_channel_green: green channel of a LUT entry
layer_lut_channel_blue: blue channel of a LUT entry
\retval none
*/
void tli_lut_struct_para_init(tli_layer_lut_parameter_struct *lut_struct)
{
/* initialize the struct parameters with default values */
lut_struct->layer_table_addr = TLI_DEFAULT_VALUE;
lut_struct->layer_lut_channel_red = TLI_DEFAULT_VALUE;
lut_struct->layer_lut_channel_green = TLI_DEFAULT_VALUE;
lut_struct->layer_lut_channel_blue = TLI_DEFAULT_VALUE;
}
/*!
\brief initialize TLI layer LUT
\param[in] layerx: LAYERx(x=0,1)
\param[in] lut_struct: TLI layer LUT parameter struct
layer_table_addr: look up table write address
layer_lut_channel_red: red channel of a LUT entry
layer_lut_channel_green: green channel of a LUT entry
layer_lut_channel_blue: blue channel of a LUT entry
\param[out] none
\retval none
*/
void tli_lut_init(uint32_t layerx, tli_layer_lut_parameter_struct *lut_struct)
{
TLI_LxLUT(layerx) = (uint32_t)(((uint32_t)lut_struct->layer_lut_channel_blue) | ((uint32_t)lut_struct->layer_lut_channel_green << 8U)
| ((uint32_t)lut_struct->layer_lut_channel_red << 16U
| ((uint32_t)lut_struct->layer_table_addr << 24U)));
}
/*!
\brief initialize TLI layer color key
\param[in] layerx: LAYERx(x=0,1)
\param[in] redkey: color key red
\param[in] greenkey: color key green
\param[in] bluekey: color key blue
\param[out] none
\retval none
*/
void tli_color_key_init(uint32_t layerx, uint8_t redkey, uint8_t greenkey, uint8_t bluekey)
{
TLI_LxCKEY(layerx) = (((uint32_t)bluekey) | ((uint32_t)greenkey << 8U) | ((uint32_t)redkey << 16U));
}
/*!
\brief enable TLI layer
\param[in] layerx: LAYERx(x=0,1)
\param[out] none
\retval none
*/
void tli_layer_enable(uint32_t layerx)
{
TLI_LxCTL(layerx) |= TLI_LxCTL_LEN;
}
/*!
\brief disable TLI layer
\param[in] layerx: LAYERx(x=0,1)
\param[out] none
\retval none
*/
void tli_layer_disable(uint32_t layerx)
{
TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LEN);
}
/*!
\brief enable TLI layer color keying
\param[in] layerx: LAYERx(x=0,1)
\param[out] none
\retval none
*/
void tli_color_key_enable(uint32_t layerx)
{
TLI_LxCTL(layerx) |= TLI_LxCTL_CKEYEN;
}
/*!
\brief disable TLI layer color keying
\param[in] layerx: LAYERx(x=0,1)
\param[out] none
\retval none
*/
void tli_color_key_disable(uint32_t layerx)
{
TLI_LxCTL(layerx) &= ~(TLI_LxCTL_CKEYEN);
}
/*!
\brief enable TLI layer LUT
\param[in] layerx: LAYERx(x=0,1)
\param[out] none
\retval none
*/
void tli_lut_enable(uint32_t layerx)
{
TLI_LxCTL(layerx) |= TLI_LxCTL_LUTEN;
}
/*!
\brief disable TLI layer LUT
\param[in] layerx: LAYERx(x=0,1)
\param[out] none
\retval none
*/
void tli_lut_disable(uint32_t layerx)
{
TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LUTEN);
}
/*!
\brief set line mark value
\param[in] line_num: line number
\param[out] none
\retval none
*/
void tli_line_mark_set(uint16_t line_num)
{
TLI_LM &= ~(TLI_LM_LM);
TLI_LM = (uint32_t)line_num;
}
/*!
\brief get current displayed position
\param[in] none
\param[out] none
\retval position of current pixel
*/
uint32_t tli_current_pos_get(void)
{
return TLI_CPPOS;
}
/*!
\brief enable TLI interrupt
\param[in] int_flag: TLI interrupt flags
one or more parameters can be selected which are shown as below:
\arg TLI_INT_LM: line mark interrupt
\arg TLI_INT_FE: FIFO error interrupt
\arg TLI_INT_TE: transaction error interrupt
\arg TLI_INT_LCR: layer configuration reloaded interrupt
\param[out] none
\retval none
*/
void tli_interrupt_enable(uint32_t int_flag)
{
TLI_INTEN |= (int_flag);
}
/*!
\brief disable TLI interrupt
\param[in] int_flag: TLI interrupt flags
one or more parameters can be selected which are shown as below:
\arg TLI_INT_LM: line mark interrupt
\arg TLI_INT_FE: FIFO error interrupt
\arg TLI_INT_TE: transaction error interrupt
\arg TLI_INT_LCR: layer configuration reloaded interrupt
\param[out] none
\retval none
*/
void tli_interrupt_disable(uint32_t int_flag)
{
TLI_INTEN &= ~(int_flag);
}
/*!
\brief get TLI interrupt flag
\param[in] int_flag: TLI interrupt flags
one or more parameters can be selected which are shown as below:
\arg TLI_INT_FLAG_LM: line mark interrupt flag
\arg TLI_INT_FLAG_FE: FIFO error interrupt flag
\arg TLI_INT_FLAG_TE: transaction error interrupt flag
\arg TLI_INT_FLAG_LCR: layer configuration reloaded interrupt flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus tli_interrupt_flag_get(uint32_t int_flag)
{
uint32_t state;
state = TLI_INTF;
if(state & int_flag) {
state = TLI_INTEN;
/* check whether the corresponding bit in TLI_INTEN is set or not */
if(state & int_flag) {
return SET;
}
}
return RESET;
}
/*!
\brief clear TLI interrupt flag
\param[in] int_flag: TLI interrupt flags
one or more parameters can be selected which are shown as below:
\arg TLI_INT_FLAG_LM: line mark interrupt flag
\arg TLI_INT_FLAG_FE: FIFO error interrupt flag
\arg TLI_INT_FLAG_TE: transaction error interrupt flag
\arg TLI_INT_FLAG_LCR: layer configuration reloaded interrupt flag
\param[out] none
\retval none
*/
void tli_interrupt_flag_clear(uint32_t int_flag)
{
TLI_INTC |= (int_flag);
}
/*!
\brief get TLI flag or state in TLI_INTF register or TLI_STAT register
\param[in] flag: TLI flags or states
only one parameter can be selected which is shown as below:
\arg TLI_FLAG_VDE: current VDE state
\arg TLI_FLAG_HDE: current HDE state
\arg TLI_FLAG_VS: current VS status of the TLI
\arg TLI_FLAG_HS: current HS status of the TLI
\arg TLI_FLAG_LM: line mark interrupt flag
\arg TLI_FLAG_FE: FIFO error interrupt flag
\arg TLI_FLAG_TE: transaction error interrupt flag
\arg TLI_FLAG_LCR: layer configuration reloaded interrupt flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus tli_flag_get(uint32_t flag)
{
uint32_t stat;
/* choose which register to get flag or state */
if(flag >> 31U) {
stat = TLI_INTF;
} else {
stat = TLI_STAT;
}
if(flag & stat) {
return SET;
} else {
return RESET;
}
}
@@ -0,0 +1,153 @@
/*!
\file gd32f4xx_trng.c
\brief TRNG driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_trng.h"
/*!
\brief reset 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 TRNG
\param[in] none
\param[out] none
\retval none
*/
void trng_enable(void)
{
TRNG_CTL |= TRNG_CTL_TRNGEN;
}
/*!
\brief disable TRNG
\param[in] none
\param[out] none
\retval none
*/
void trng_disable(void)
{
TRNG_CTL &= ~TRNG_CTL_TRNGEN;
}
/*!
\brief get the true random data
\param[in] none
\param[out] none
\retval uint32_t: 0x0-0xFFFFFFFF
*/
uint32_t trng_get_true_random_data(void)
{
return (TRNG_DATA);
}
/*!
\brief enable TRNG interrupt
\param[in] none
\param[out] none
\retval none
*/
void trng_interrupt_enable(void)
{
TRNG_CTL |= TRNG_CTL_TRNGIE;
}
/*!
\brief disable TRNG interrupt
\param[in] none
\param[out] none
\retval none
*/
void trng_interrupt_disable(void)
{
TRNG_CTL &= ~TRNG_CTL_TRNGIE;
}
/*!
\brief get TRNG flag status
\param[in] flag: TRNG flag
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)
{
if(RESET != (TRNG_STAT & flag)) {
return SET;
} else {
return RESET;
}
}
/*!
\brief get TRNG interrupt flag status
\param[in] int_flag: TRNG interrupt flag
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)
{
if(RESET != (TRNG_STAT & int_flag)) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear TRNG interrupt flag status
\param[in] int_flag: TRNG interrupt flag
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;
}
@@ -0,0 +1,982 @@
/*!
\file gd32f4xx_usart.c
\brief USART driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_usart.h"
/* USART register bit offset */
#define GP_GUAT_OFFSET ((uint32_t)8U) /* bit offset of GUAT in USART_GP */
#define CTL3_SCRTNUM_OFFSET ((uint32_t)1U) /* bit offset of SCRTNUM in USART_CTL3 */
#define RT_BL_OFFSET ((uint32_t)24U) /* bit offset of BL in USART_RT */
/*!
\brief reset USART/UART
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_deinit(uint32_t usart_periph)
{
switch(usart_periph) {
case USART0:
rcu_periph_reset_enable(RCU_USART0RST);
rcu_periph_reset_disable(RCU_USART0RST);
break;
case USART1:
rcu_periph_reset_enable(RCU_USART1RST);
rcu_periph_reset_disable(RCU_USART1RST);
break;
case USART2:
rcu_periph_reset_enable(RCU_USART2RST);
rcu_periph_reset_disable(RCU_USART2RST);
break;
case USART5:
rcu_periph_reset_enable(RCU_USART5RST);
rcu_periph_reset_disable(RCU_USART5RST);
break;
case UART3:
rcu_periph_reset_enable(RCU_UART3RST);
rcu_periph_reset_disable(RCU_UART3RST);
break;
case UART4:
rcu_periph_reset_enable(RCU_UART4RST);
rcu_periph_reset_disable(RCU_UART4RST);
break;
case UART6:
rcu_periph_reset_enable(RCU_UART6RST);
rcu_periph_reset_disable(RCU_UART6RST);
break;
case UART7:
rcu_periph_reset_enable(RCU_UART7RST);
rcu_periph_reset_disable(RCU_UART7RST);
break;
default:
break;
}
}
/*!
\brief configure USART baud rate value
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] baudval: baud rate value
\param[out] none
\retval none
*/
void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval)
{
uint32_t uclk = 0U, intdiv = 0U, fradiv = 0U, udiv = 0U;
switch(usart_periph) {
/* get clock frequency */
case USART0:
uclk = rcu_clock_freq_get(CK_APB2);
break;
case USART5:
uclk = rcu_clock_freq_get(CK_APB2);
break;
case USART1:
uclk = rcu_clock_freq_get(CK_APB1);
break;
case USART2:
uclk = rcu_clock_freq_get(CK_APB1);
break;
case UART3:
uclk = rcu_clock_freq_get(CK_APB1);
break;
case UART4:
uclk = rcu_clock_freq_get(CK_APB1);
break;
case UART6:
uclk = rcu_clock_freq_get(CK_APB1);
break;
case UART7:
uclk = rcu_clock_freq_get(CK_APB1);
break;
default:
break;
}
if(USART_CTL0(usart_periph) & USART_CTL0_OVSMOD) {
/* when oversampling by 8, configure the value of USART_BAUD */
udiv = ((2U * uclk) + baudval / 2U) / baudval;
intdiv = udiv & 0xfff0U;
fradiv = (udiv >> 1U) & 0x7U;
USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv));
} else {
/* when oversampling by 16, configure the value of USART_BAUD */
udiv = (uclk + baudval / 2U) / baudval;
intdiv = udiv & 0xfff0U;
fradiv = udiv & 0xfU;
USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv));
}
}
/*!
\brief configure USART parity function
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] paritycfg: configure USART parity
only one parameter can be selected which is shown as below:
\arg USART_PM_NONE: no parity
\arg USART_PM_EVEN: even parity
\arg USART_PM_ODD: odd parity
\param[out] none
\retval none
*/
void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg)
{
/* clear USART_CTL0 PM,PCEN Bits */
USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN);
/* configure USART parity mode */
USART_CTL0(usart_periph) |= paritycfg ;
}
/*!
\brief configure USART word length
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] wlen: USART word length configure
only one parameter can be selected which is shown as below:
\arg USART_WL_8BIT: 8 bits
\arg USART_WL_9BIT: 9 bits
\param[out] none
\retval none
*/
void usart_word_length_set(uint32_t usart_periph, uint32_t wlen)
{
/* clear USART_CTL0 WL bit */
USART_CTL0(usart_periph) &= ~USART_CTL0_WL;
/* configure USART word length */
USART_CTL0(usart_periph) |= wlen;
}
/*!
\brief configure USART stop bit length
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] stblen: USART stop bit configure
only one parameter can be selected which is shown as below:
\arg USART_STB_1BIT: 1 bit
\arg USART_STB_0_5BIT: 0.5 bit(not available for UARTx(x=3,4,6,7))
\arg USART_STB_2BIT: 2 bits
\arg USART_STB_1_5BIT: 1.5 bits(not available for UARTx(x=3,4,6,7))
\param[out] none
\retval none
*/
void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen)
{
/* clear USART_CTL1 STB bits */
USART_CTL1(usart_periph) &= ~USART_CTL1_STB;
/* configure USART stop bits */
USART_CTL1(usart_periph) |= stblen;
}
/*!
\brief enable USART
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_enable(uint32_t usart_periph)
{
USART_CTL0(usart_periph) |= USART_CTL0_UEN;
}
/*!
\brief disable USART
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_disable(uint32_t usart_periph)
{
USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN);
}
/*!
\brief configure USART transmitter
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] txconfig: enable or disable USART transmitter
only one parameter can be selected which is shown as below:
\arg USART_TRANSMIT_ENABLE: enable USART transmission
\arg USART_TRANSMIT_DISABLE: enable USART transmission
\param[out] none
\retval none
*/
void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig)
{
uint32_t ctl = 0U;
ctl = USART_CTL0(usart_periph);
ctl &= ~USART_CTL0_TEN;
ctl |= txconfig;
/* configure transfer mode */
USART_CTL0(usart_periph) = ctl;
}
/*!
\brief configure USART receiver
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] rxconfig: enable or disable USART receiver
only one parameter can be selected which is shown as below:
\arg USART_RECEIVE_ENABLE: enable USART reception
\arg USART_RECEIVE_DISABLE: disable USART reception
\param[out] none
\retval none
*/
void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig)
{
uint32_t ctl = 0U;
ctl = USART_CTL0(usart_periph);
ctl &= ~USART_CTL0_REN;
ctl |= rxconfig;
/* configure transfer mode */
USART_CTL0(usart_periph) = ctl;
}
/*!
\brief data is transmitted/received with the LSB/MSB first
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[in] msbf: LSB/MSB
only one parameter can be selected which is shown as below:
\arg USART_MSBF_LSB: LSB first
\arg USART_MSBF_MSB: MSB first
\param[out] none
\retval none
*/
void usart_data_first_config(uint32_t usart_periph, uint32_t msbf)
{
uint32_t ctl = 0U;
ctl = USART_CTL3(usart_periph);
ctl &= ~(USART_CTL3_MSBF);
ctl |= msbf;
/* configure data transmitted/received mode */
USART_CTL3(usart_periph) = ctl;
}
/*!
\brief configure USART inversion
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[in] invertpara: refer to enum USART_INVERT_CONFIG
only one parameter can be selected which is shown as below:
\arg USART_DINV_ENABLE: data bit level inversion
\arg USART_DINV_DISABLE: data bit level not inversion
\arg USART_TXPIN_ENABLE: TX pin level inversion
\arg USART_TXPIN_DISABLE: TX pin level not inversion
\arg USART_RXPIN_ENABLE: RX pin level inversion
\arg USART_RXPIN_DISABLE: RX pin level not inversion
\param[out] none
\retval none
*/
void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara)
{
/* inverted or not the specified siginal */
switch(invertpara) {
case USART_DINV_ENABLE:
USART_CTL3(usart_periph) |= USART_CTL3_DINV;
break;
case USART_TXPIN_ENABLE:
USART_CTL3(usart_periph) |= USART_CTL3_TINV;
break;
case USART_RXPIN_ENABLE:
USART_CTL3(usart_periph) |= USART_CTL3_RINV;
break;
case USART_DINV_DISABLE:
USART_CTL3(usart_periph) &= ~(USART_CTL3_DINV);
break;
case USART_TXPIN_DISABLE:
USART_CTL3(usart_periph) &= ~(USART_CTL3_TINV);
break;
case USART_RXPIN_DISABLE:
USART_CTL3(usart_periph) &= ~(USART_CTL3_RINV);
break;
default:
break;
}
}
/*!
\brief configure the USART oversample mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] oversamp: oversample value
only one parameter can be selected which is shown as below:
\arg USART_OVSMOD_8: 8 bits
\arg USART_OVSMOD_16: 16 bits
\param[out] none
\retval none
*/
void usart_oversample_config(uint32_t usart_periph, uint32_t oversamp)
{
/* clear OVSMOD bit */
USART_CTL0(usart_periph) &= ~(USART_CTL0_OVSMOD);
USART_CTL0(usart_periph) |= oversamp;
}
/*!
\brief configure sample bit method
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] obsm: sample bit
only one parameter can be selected which is shown as below:
\arg USART_OSB_1bit: 1 bit
\arg USART_OSB_3bit: 3 bits
\param[out] none
\retval none
*/
void usart_sample_bit_config(uint32_t usart_periph, uint32_t obsm)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_OSB);
USART_CTL2(usart_periph) |= obsm;
}
/*!
\brief enable receiver timeout of USART
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[out] none
\retval none
*/
void usart_receiver_timeout_enable(uint32_t usart_periph)
{
USART_CTL3(usart_periph) |= USART_CTL3_RTEN;
}
/*!
\brief disable receiver timeout of USART
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[out] none
\retval none
*/
void usart_receiver_timeout_disable(uint32_t usart_periph)
{
USART_CTL3(usart_periph) &= ~(USART_CTL3_RTEN);
}
/*!
\brief set the receiver timeout threshold of USART
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[in] rtimeout: 0-0x00FFFFFF
\param[out] none
\retval none
*/
void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout)
{
USART_RT(usart_periph) &= ~(USART_RT_RT);
USART_RT(usart_periph) |= rtimeout;
}
/*!
\brief USART transmit data function
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] data: data of transmission
\param[out] none
\retval none
*/
void usart_data_transmit(uint32_t usart_periph, uint16_t data)
{
USART_DATA(usart_periph) = USART_DATA_DATA & (uint32_t)data;
}
/*!
\brief USART receive data function
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval data of received
*/
uint16_t usart_data_receive(uint32_t usart_periph)
{
return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U));
}
/*!
\brief configure the address of the USART in wake up by address match mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] addr: address of USART/UART
\param[out] none
\retval none
*/
void usart_address_config(uint32_t usart_periph, uint8_t addr)
{
USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR);
USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & (uint32_t)addr);
}
/*!
\brief enable mute mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_mute_mode_enable(uint32_t usart_periph)
{
USART_CTL0(usart_periph) |= USART_CTL0_RWU;
}
/*!
\brief disable mute mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_mute_mode_disable(uint32_t usart_periph)
{
USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU);
}
/*!
\brief configure wakeup method in mute mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] wmehtod: two method be used to enter or exit the mute mode
only one parameter can be selected which is shown as below:
\arg USART_WM_IDLE: idle line
\arg USART_WM_ADDR: address mask
\param[out] none
\retval none
*/
void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmehtod)
{
USART_CTL0(usart_periph) &= ~(USART_CTL0_WM);
USART_CTL0(usart_periph) |= wmehtod;
}
/*!
\brief enable LIN mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_lin_mode_enable(uint32_t usart_periph)
{
USART_CTL1(usart_periph) |= USART_CTL1_LMEN;
}
/*!
\brief disable LIN mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_lin_mode_disable(uint32_t usart_periph)
{
USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN);
}
/*!
\brief configure lin break frame length
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] lblen: lin break frame length
only one parameter can be selected which is shown as below:
\arg USART_LBLEN_10B: 10 bits
\arg USART_LBLEN_11B: 11 bits
\param[out] none
\retval none
*/
void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen)
{
USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN);
USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen);
}
/*!
\brief send break frame
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_send_break(uint32_t usart_periph)
{
USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD;
}
/*!
\brief enable half duplex mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_halfduplex_enable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) |= USART_CTL2_HDEN;
}
/*!
\brief disable half duplex mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_halfduplex_disable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN);
}
/*!
\brief enable CK pin in synchronous mode
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[out] none
\retval none
*/
void usart_synchronous_clock_enable(uint32_t usart_periph)
{
USART_CTL1(usart_periph) |= USART_CTL1_CKEN;
}
/*!
\brief disable CK pin in synchronous mode
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[out] none
\retval none
*/
void usart_synchronous_clock_disable(uint32_t usart_periph)
{
USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN);
}
/*!
\brief configure USART synchronous mode parameters
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[in] clen: CK length
only one parameter can be selected which is shown as below:
\arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame
\arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame
\param[in] cph: clock phase
only one parameter can be selected which is shown as below:
\arg USART_CPH_1CK: first clock transition is the first data capture edge
\arg USART_CPH_2CK: second clock transition is the first data capture edge
\param[in] cpl: clock polarity
only one parameter can be selected which is shown as below:
\arg USART_CPL_LOW: steady low value on CK pin
\arg USART_CPL_HIGH: steady high value on CK pin
\param[out] none
\retval none
*/
void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl)
{
USART_CTL1(usart_periph) &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL);
USART_CTL1(usart_periph) |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl);
}
/*!
\brief configure guard time value in smartcard mode
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[in] guat: guard time value, 0-0xFF
\param[out] none
\retval none
*/
void usart_guard_time_config(uint32_t usart_periph, uint8_t guat)
{
USART_GP(usart_periph) &= ~(USART_GP_GUAT);
USART_GP(usart_periph) |= (USART_GP_GUAT & ((uint32_t)guat << GP_GUAT_OFFSET));
}
/*!
\brief enable smartcard mode
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[out] none
\retval none
*/
void usart_smartcard_mode_enable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) |= USART_CTL2_SCEN;
}
/*!
\brief disable smartcard mode
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[out] none
\retval none
*/
void usart_smartcard_mode_disable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN);
}
/*!
\brief enable NACK in smartcard mode
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[out] none
\retval none
*/
void usart_smartcard_mode_nack_enable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) |= USART_CTL2_NKEN;
}
/*!
\brief disable NACK in smartcard mode
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[out] none
\retval none
*/
void usart_smartcard_mode_nack_disable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN);
}
/*!
\brief configure smartcard auto-retry number
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[in] scrtnum: smartcard auto-retry number
\param[out] none
\retval none
*/
void usart_smartcard_autoretry_config(uint32_t usart_periph, uint8_t scrtnum)
{
USART_CTL3(usart_periph) &= ~(USART_CTL3_SCRTNUM);
USART_CTL3(usart_periph) |= (USART_CTL3_SCRTNUM & ((uint32_t)scrtnum << CTL3_SCRTNUM_OFFSET));
}
/*!
\brief configure block length in Smartcard T=1 reception
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[in] bl: block length
\param[out] none
\retval none
*/
void usart_block_length_config(uint32_t usart_periph, uint8_t bl)
{
USART_RT(usart_periph) &= ~(USART_RT_BL);
USART_RT(usart_periph) |= (USART_RT_BL & ((uint32_t)bl << RT_BL_OFFSET));
}
/*!
\brief enable IrDA mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_irda_mode_enable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) |= USART_CTL2_IREN;
}
/*!
\brief disable IrDA mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[out] none
\retval none
*/
void usart_irda_mode_disable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN);
}
/*!
\brief configure the peripheral clock prescaler in USART IrDA low-power mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] psc: 0-0xFF
\param[out] none
\retval none
*/
void usart_prescaler_config(uint32_t usart_periph, uint8_t psc)
{
USART_GP(usart_periph) &= ~(USART_GP_PSC);
USART_GP(usart_periph) |= (uint32_t)psc;
}
/*!
\brief configure IrDA low-power
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] irlp: IrDA low-power or normal
only one parameter can be selected which is shown as below:
\arg USART_IRLP_LOW: low-power
\arg USART_IRLP_NORMAL: normal
\param[out] none
\retval none
*/
void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP);
USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp);
}
/*!
\brief configure hardware flow control RTS
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[in] rtsconfig: enable or disable RTS
only one parameter can be selected which is shown as below:
\arg USART_RTS_ENABLE: enable RTS
\arg USART_RTS_DISABLE: disable RTS
\param[out] none
\retval none
*/
void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_RTSEN);
USART_CTL2(usart_periph) |= (USART_CTL2_RTSEN & rtsconfig);
}
/*!
\brief configure hardware flow control CTS
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[in] ctsconfig: enable or disable CTS
only one parameter can be selected which is shown as below:
\arg USART_CTS_ENABLE: enable CTS
\arg USART_CTS_DISABLE: disable CTS
\param[out] none
\retval none
*/
void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_CTSEN);
USART_CTL2(usart_periph) |= (USART_CTL2_CTSEN & ctsconfig);
}
/*!
\brief configure break frame coherence mode
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[in] bcm:
only one parameter can be selected which is shown as below:
\arg USART_BCM_NONE: no parity error is detected
\arg USART_BCM_EN: parity error is detected
\param[out] none
\retval none
*/
void usart_break_frame_coherence_config(uint32_t usart_periph, uint32_t bcm)
{
USART_CHC(usart_periph) &= ~(USART_CHC_BCM);
USART_CHC(usart_periph) |= (USART_CHC_BCM & bcm);
}
/*!
\brief configure parity check coherence mode
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] pcm:
only one parameter can be selected which is shown as below:
\arg USART_PCM_NONE: not check parity
\arg USART_PCM_EN: check the parity
\param[out] none
\retval none
*/
void usart_parity_check_coherence_config(uint32_t usart_periph, uint32_t pcm)
{
USART_CHC(usart_periph) &= ~(USART_CHC_PCM);
USART_CHC(usart_periph) |= (USART_CHC_PCM & pcm);
}
/*!
\brief configure hardware flow control coherence mode
\param[in] usart_periph: USARTx(x=0,1,2,5)
\param[in] hcm:
only one parameter can be selected which is shown as below:
\arg USART_HCM_NONE: nRTS signal equals to the rxne status register
\arg USART_HCM_EN: nRTS signal is set when the last data bit has been sampled
\param[out] none
\retval none
*/
void usart_hardware_flow_coherence_config(uint32_t usart_periph, uint32_t hcm)
{
USART_CHC(usart_periph) &= ~(USART_CHC_HCM);
USART_CHC(usart_periph) |= (USART_CHC_HCM & hcm);
}
/*!
\brief configure USART DMA reception
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] dmacmd: enable or disable DMA for reception
only one parameter can be selected which is shown as below:
\arg USART_RECEIVE_DMA_ENABLE: DMA enable for reception
\arg USART_RECEIVE_DMA_DISABLE: DMA disable for reception
\param[out] none
\retval none
*/
void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_DENR);
USART_CTL2(usart_periph) |= (USART_CTL2_DENR & dmacmd);
}
/*!
\brief configure USART DMA transmission
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] dmacmd: enable or disable DMA for transmission
only one parameter can be selected which is shown as below:
\arg USART_TRANSMIT_DMA_ENABLE: DMA enable for transmission
\arg USART_TRANSMIT_DMA_DISABLE: DMA disable for transmission
\param[out] none
\retval none
*/
void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_DENT);
USART_CTL2(usart_periph) |= (USART_CTL2_DENT & dmacmd);
}
/*!
\brief get flag in STAT0/STAT1/CHC register
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] flag: USART flags, refer to usart_flag_enum
only one parameter can be selected which is shown as below:
\arg USART_FLAG_CTS: CTS change flag
\arg USART_FLAG_LBD: LIN break detected flag
\arg USART_FLAG_TBE: transmit data buffer empty
\arg USART_FLAG_TC: transmission complete
\arg USART_FLAG_RBNE: read data buffer not empty
\arg USART_FLAG_IDLE: IDLE frame detected flag
\arg USART_FLAG_ORERR: overrun error
\arg USART_FLAG_NERR: noise error flag
\arg USART_FLAG_FERR: frame error flag
\arg USART_FLAG_PERR: parity error flag
\arg USART_FLAG_BSY: busy flag
\arg USART_FLAG_EB: end of block flag
\arg USART_FLAG_RT: receiver timeout flag
\arg USART_FLAG_EPERR: early parity error flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag)
{
if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear flag in STAT0/STAT1/CHC register
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] flag: USART flags, refer to usart_flag_enum
only one parameter can be selected which is shown as below:
\arg USART_FLAG_CTS: CTS change flag
\arg USART_FLAG_LBD: LIN break detected flag
\arg USART_FLAG_TC: transmission complete
\arg USART_FLAG_RBNE: read data buffer not empty
\arg USART_FLAG_EB: end of block flag
\arg USART_FLAG_RT: receiver timeout flag
\arg USART_FLAG_EPERR: early parity error flag
\param[out] none
\retval none
*/
void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag)
{
if (USART_FLAG_EPERR == flag) {
USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag));
} else {
USART_REG_VAL(usart_periph, flag) = ~BIT(USART_BIT_POS(flag));
}
}
/*!
\brief enable USART interrupt
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] interrupt: USART interrupts, refer to usart_interrupt_enum
only one parameter can be selected which is shown as below:
\arg USART_INT_PERR: parity error interrupt
\arg USART_INT_TBE: transmitter buffer empty interrupt
\arg USART_INT_TC: transmission complete interrupt
\arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt
\arg USART_INT_IDLE: IDLE line detected interrupt
\arg USART_INT_LBD: LIN break detected interrupt
\arg USART_INT_ERR: error interrupt
\arg USART_INT_CTS: CTS interrupt
\arg USART_INT_RT: interrupt enable bit of receive timeout event
\arg USART_INT_EB: interrupt enable bit of end of block event
\param[out] none
\retval none
*/
void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt)
{
USART_REG_VAL(usart_periph, interrupt) |= BIT(USART_BIT_POS(interrupt));
}
/*!
\brief disable USART interrupt
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] interrupt: USART interrupts, refer to usart_interrupt_enum
only one parameter can be selected which is shown as below:
\arg USART_INT_PERR: parity error interrupt
\arg USART_INT_TBE: transmitter buffer empty interrupt
\arg USART_INT_TC: transmission complete interrupt
\arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt
\arg USART_INT_IDLE: IDLE line detected interrupt
\arg USART_INT_LBD: LIN break detected interrupt
\arg USART_INT_ERR: error interrupt
\arg USART_INT_CTS: CTS interrupt
\arg USART_INT_RT: interrupt enable bit of receive timeout event
\arg USART_INT_EB: interrupt enable bit of end of block event
\param[out] none
\retval none
*/
void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt)
{
USART_REG_VAL(usart_periph, interrupt) &= ~BIT(USART_BIT_POS(interrupt));
}
/*!
\brief get USART interrupt and flag status
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] int_flag: USART interrupt flags, refer to usart_interrupt_flag_enum
only one parameter can be selected which is shown as below:
\arg USART_INT_FLAG_PERR: parity error interrupt and flag
\arg USART_INT_FLAG_TBE: transmitter buffer empty interrupt and flag
\arg USART_INT_FLAG_TC: transmission complete interrupt and flag
\arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag
\arg USART_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag
\arg USART_INT_FLAG_IDLE: IDLE line detected interrupt and flag
\arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag
\arg USART_INT_FLAG_CTS: CTS interrupt and flag
\arg USART_INT_FLAG_ERR_ORERR: error interrupt and overrun error
\arg USART_INT_FLAG_ERR_NERR: error interrupt and noise error flag
\arg USART_INT_FLAG_ERR_FERR: error interrupt and frame error flag
\arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag
\arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag)
{
uint32_t intenable = 0U, flagstatus = 0U;
/* get the interrupt enable bit status */
intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag)));
/* get the corresponding flag bit status */
flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag)));
if((0U != flagstatus) && (0U != intenable)) {
return SET;
} else {
return RESET;
}
}
/*!
\brief clear USART interrupt flag in STAT0/STAT1 register
\param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7)
\param[in] int_flag: USART interrupt flags, refer to usart_interrupt_flag_enum
only one parameter can be selected which is shown as below:
\arg USART_INT_FLAG_CTS: CTS change flag
\arg USART_INT_FLAG_LBD: LIN break detected flag
\arg USART_INT_FLAG_TC: transmission complete
\arg USART_INT_FLAG_RBNE: read data buffer not empty
\arg USART_INT_FLAG_EB: end of block flag
\arg USART_INT_FLAG_RT: receiver timeout flag
\param[out] none
\retval none
*/
void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag)
{
USART_REG_VAL2(usart_periph, int_flag) &= ~BIT(USART_BIT_POS2(int_flag));
}
@@ -0,0 +1,126 @@
/*!
\file gd32f4xx_wwdgt.c
\brief WWDGT driver
\version 2024-12-20, V3.3.1, firmware for GD32F4xx
*/
/*
Copyright (c) 2024, 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 "gd32f4xx_wwdgt.h"
/*!
\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 window watchdog timer counter
\param[in] none
\param[out] none
\retval none
*/
void wwdgt_enable(void)
{
WWDGT_CTL |= WWDGT_CTL_WDGTEN;
}
/*!
\brief configure the window watchdog timer counter value
\param[in] counter_value: 0x00 - 0x7F
\param[out] none
\retval none
*/
void wwdgt_counter_update(uint16_t counter_value)
{
WWDGT_CTL = (uint32_t)(CTL_CNT(counter_value));
}
/*!
\brief configure counter value, window value, and prescaler divider value
\param[in] counter: 0x00 - 0x7F
\param[in] window: 0x00 - 0x7F
\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 = (PCLK1/4096)/1
\arg WWDGT_CFG_PSC_DIV2: the time base of window watchdog counter = (PCLK1/4096)/2
\arg WWDGT_CFG_PSC_DIV4: the time base of window watchdog counter = (PCLK1/4096)/4
\arg WWDGT_CFG_PSC_DIV8: the time base of window watchdog counter = (PCLK1/4096)/8
\param[out] none
\retval none
*/
void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler)
{
/* configure WIN and PSC bits, configure CNT bit */
WWDGT_CTL = (uint32_t)(CTL_CNT(counter));
WWDGT_CFG = (uint32_t)(CFG_WIN(window) | prescaler);
}
/*!
\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);
}
/*!
\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;
}