Initial commit: CCU621_M firmware project with BLE debug link support.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,276 @@
|
||||
/*!
|
||||
\file gd32h7xx_cpdm.c
|
||||
\brief CPDM driver
|
||||
|
||||
\version 2025-01-24, V1.4.0, firmware for GD32H7xx
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32h7xx_cpdm.h"
|
||||
|
||||
#define CPDM_CPSEL_MASK ((uint32_t)0xFFFFFFF0U) /*!< CPDM output clock phase seclection mask */
|
||||
#define CPDM_DLSTCNT_MASK ((uint32_t)0xFFFF80FFU) /*!< CPDM delay step count for a uint delay UINT mask */
|
||||
#define CPDM_DLLENF_MASK ((uint32_t)0x80000000U) /*!< CPDM delay line length valid flag mask */
|
||||
#define CPDM_DLLEN_MASK ((uint32_t)0x0FFF0000U) /*!< CPDM delay line length mask */
|
||||
|
||||
#define CPDM_DLLEN_OFFSET ((uint32_t)16U) /*!< CPDM delay line length offset */
|
||||
#define CPDM_DLSTCNT_OFFSET ((uint32_t)8U) /*!< CPDM delay step count for a uint delay UINT offset */
|
||||
#define CPDM_DLLEN_11 ((uint32_t)0x04000000U) /*!< CPDM delay line length bit 11 */
|
||||
#define CPDM_DLLEN_10 ((uint32_t)0x08000000U) /*!< CPDM delay line length bit 10 */
|
||||
#define CPDM_DLLEN_10_0_MASK ((uint32_t)0x7FFU) /*!< CPDM delay line length bit 10 to bit 0 mask */
|
||||
|
||||
#define CPDM_MAX_TIMEOUT ((uint32_t)0x0000FFFFU) /*!< count to judge of CPDM timeout */
|
||||
|
||||
/*!
|
||||
\brief enable CPDM
|
||||
\param[in] cpdm_periph: the clock phase delay module of SDIO
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CPDM_SDIO0: clock phase delay module of SDIO0
|
||||
\arg CPDM_SDIO1: clock phase delay module of SDIO1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cpdm_enable(uint32_t cpdm_periph)
|
||||
{
|
||||
/* enable CPDM */
|
||||
CPDM_CTL(cpdm_periph) |= (uint32_t)CPDM_CTL_CPDMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable CPDM
|
||||
\param[in] cpdm_periph: the clock phase delay module of SDIO
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CPDM_SDIO0: clock phase delay module of SDIO0
|
||||
\arg CPDM_SDIO1: clock phase delay module of SDIO1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cpdm_disable(uint32_t cpdm_periph)
|
||||
{
|
||||
/* disable CPDM */
|
||||
CPDM_CTL(cpdm_periph) &= ~(uint32_t)CPDM_CTL_CPDMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable CPDM delay line sample module
|
||||
\param[in] cpdm_periph: the clock phase delay module of SDIO
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CPDM_SDIO0: clock phase delay module of SDIO0
|
||||
\arg CPDM_SDIO1: clock phase delay module of SDIO1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cpdm_delayline_sample_enable(uint32_t cpdm_periph)
|
||||
{
|
||||
/* enable CPDM delay line sample module */
|
||||
CPDM_CTL(cpdm_periph) |= (uint32_t)CPDM_CTL_DLSEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable CPDM delay line sample module
|
||||
\param[in] cpdm_periph: the clock phase delay module of SDIO
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CPDM_SDIO0: clock phase delay module of SDIO0
|
||||
\arg CPDM_SDIO1: clock phase delay module of SDIO1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cpdm_delayline_sample_disable(uint32_t cpdm_periph)
|
||||
{
|
||||
/* disable CPDM delay line sample module */
|
||||
CPDM_CTL(cpdm_periph) &= ~(uint32_t)CPDM_CTL_DLSEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select CPDM output clock phase
|
||||
\param[in] cpdm_periph: the clock phase delay module of SDIO
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CPDM_SDIO0: clock phase delay module of SDIO0
|
||||
\arg CPDM_SDIO1: clock phase delay module of SDIO1
|
||||
\param[in] output_clock_phase: the output clock phase, refer to cpdm_output_phase_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_0: output clock phase = input clock
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_1: output clock phase = input clock + 1 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_2: output clock phase = input clock + 2 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_3: output clock phase = input clock + 3 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_4: output clock phase = input clock + 4 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_5: output clock phase = input clock + 5 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_6: output clock phase = input clock + 6 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_7: output clock phase = input clock + 7 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_8: output clock phase = input clock + 8 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_9: output clock phase = input clock + 9 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_10: output clock phase = input clock + 10 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_11: output clock phase = input clock + 11 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_12: output clock phase = input clock + 12 * UNIT delay
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cpdm_output_clock_phase_select(uint32_t cpdm_periph, cpdm_output_phase_enum output_clock_phase)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
|
||||
reg = CPDM_CFG(cpdm_periph);
|
||||
reg &= CPDM_CPSEL_MASK;
|
||||
/* select CPDM output clock phase */
|
||||
reg |= output_clock_phase;
|
||||
CPDM_CFG(cpdm_periph) = (uint32_t)reg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure CPDM delay step
|
||||
\param[in] cpdm_periph: the clock phase delay module of SDIO
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CPDM_SDIO0: clock phase delay module of SDIO0
|
||||
\arg CPDM_SDIO1: clock phase delay module of SDIO1
|
||||
\param[in] delay_step: 0 ~ 127
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void cpdm_delay_step_config(uint32_t cpdm_periph, uint8_t delay_step)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
|
||||
reg = CPDM_CFG(cpdm_periph);
|
||||
reg &= CPDM_DLSTCNT_MASK;
|
||||
/* configure delay step */
|
||||
reg |= ((uint32_t)delay_step << CPDM_DLSTCNT_OFFSET);
|
||||
CPDM_CFG(cpdm_periph) = (uint32_t)reg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get delay line length valid flag
|
||||
\param[in] cpdm_periph: the clock phase delay module of SDIO
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CPDM_SDIO0: clock phase delay module of SDIO0
|
||||
\arg CPDM_SDIO1: clock phase delay module of SDIO1
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus cpdm_delayline_length_valid_flag_get(uint32_t cpdm_periph)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
|
||||
reg = CPDM_CFG(cpdm_periph);
|
||||
if(reg & CPDM_DLLENF_MASK) {
|
||||
return SET;
|
||||
} else {
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get delay line length
|
||||
\param[in] cpdm_periph: the clock phase delay module of SDIO
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CPDM_SDIO0: clock phase delay module of SDIO0
|
||||
\arg CPDM_SDIO1: clock phase delay module of SDIO1
|
||||
\param[out] none
|
||||
\retval the value of delay line length, 0x00~0xFFF
|
||||
*/
|
||||
uint16_t cpdm_delayline_length_get(uint32_t cpdm_periph)
|
||||
{
|
||||
return (uint16_t)((CPDM_CFG(cpdm_periph) & CPDM_DLLEN_MASK) >> CPDM_DLLEN_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure CPDM clock output
|
||||
\param[in] cpdm_periph: the clock phase delay module of SDIO
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CPDM_SDIO0: clock phase delay module of SDIO0
|
||||
\arg CPDM_SDIO1: clock phase delay module of SDIO1
|
||||
\param[in] output_clock_phase: the output clock phase, refer to cpdm_output_phase_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_0: output clock phase = input clock
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_1: output clock phase = input clock + 1 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_2: output clock phase = input clock + 2 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_3: output clock phase = input clock + 3 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_4: output clock phase = input clock + 4 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_5: output clock phase = input clock + 5 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_6: output clock phase = input clock + 6 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_7: output clock phase = input clock + 7 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_8: output clock phase = input clock + 8 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_9: output clock phase = input clock + 9 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_10: output clock phase = input clock + 10 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_11: output clock phase = input clock + 11 * UNIT delay
|
||||
\arg CPDM_OUTPUT_PHASE_SELECTION_12: output clock phase = input clock + 12 * UNIT delay
|
||||
\param[out] none
|
||||
\retval ErrStatus: SUCCESS or ERROR
|
||||
*/
|
||||
ErrStatus cpdm_clock_output(uint32_t cpdm_periph, cpdm_output_phase_enum output_clock_phase)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
uint32_t reg_cfg = 0U;
|
||||
uint32_t delay_count = 0U;
|
||||
uint32_t timeout = 0U;
|
||||
|
||||
/* enable CPDM and delay line sample module */
|
||||
CPDM_CTL(cpdm_periph) = 0U;
|
||||
CPDM_CTL(cpdm_periph) = CPDM_CTL_CPDMEN | CPDM_CTL_DLSEN;
|
||||
/* configure CPDM output clock phase to the max value (12) */
|
||||
reg = CPDM_CFG(cpdm_periph);
|
||||
reg &= CPDM_CPSEL_MASK;
|
||||
reg |= CPDM_MAX_PHASE;
|
||||
CPDM_CFG(cpdm_periph) = (uint32_t)reg;
|
||||
|
||||
for(delay_count = 0U; delay_count <= CPDM_MAX_DELAY_STEP_COUNT; delay_count++) {
|
||||
reg = CPDM_CFG(cpdm_periph);
|
||||
reg &= CPDM_DLSTCNT_MASK;
|
||||
/* configure delay line step count */
|
||||
reg |= delay_count << CPDM_DLSTCNT_OFFSET;
|
||||
CPDM_CFG(cpdm_periph) = (uint32_t)reg;
|
||||
|
||||
while(RESET == (CPDM_CFG(cpdm_periph) & CPDM_CFG_DLLENF)) {
|
||||
timeout++;
|
||||
|
||||
if(timeout > CPDM_MAX_TIMEOUT)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
reg_cfg = CPDM_CFG(cpdm_periph);
|
||||
if((((reg_cfg >> CPDM_DLLEN_OFFSET) & CPDM_DLLEN_10_0_MASK) > 0U) &&
|
||||
((RESET == (reg_cfg & CPDM_DLLEN_11)) || (RESET == (reg_cfg & CPDM_DLLEN_10)))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* enable CPDM and delay line sample module */
|
||||
CPDM_CTL(cpdm_periph) = 0U;
|
||||
CPDM_CTL(cpdm_periph) = CPDM_CTL_CPDMEN | CPDM_CTL_DLSEN;
|
||||
/* select the output clock phase */
|
||||
reg = CPDM_CFG(cpdm_periph);
|
||||
reg &= CPDM_CPSEL_MASK;
|
||||
reg |= output_clock_phase;
|
||||
CPDM_CFG(cpdm_periph) = (uint32_t)reg;
|
||||
/* disable delay line sample module */
|
||||
CPDM_CTL(cpdm_periph) = CPDM_CTL_CPDMEN;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user