feat: 添加GD32E508 DCU应用工程的初始结构
- 新增完整的CMSIS解决方案配置,包含AC6/GCC/IAR/CLANG编译器支持 - 添加项目配置文件,定义了设备层、系统层、应用层的模块结构 - 配置ARM::CMSIS和GigaDevice::GD32E50x_DFP软件包依赖 - 创建多层代码架构:应用入口(main)、系统层(sys)、设备层(device) - 实现任务管理系统,包含任务调度器和任务执行器分离设计 - 集成ADC、CANFD、定时器、串口、温度采样等核心功能模块 - 添加详细的README文档说明项目结构和代码组织方式 - 配置AC6链接脚本和运行时环境文件 - 设置Git忽略规则以排除编译产物和临时文件
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
Stack seal size definition
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
|
||||
#define __STACKSEAL_SIZE 8
|
||||
#else
|
||||
#define __STACKSEAL_SIZE 0
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Scatter File Definitions definition
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
LR_ROM0 __ROM0_BASE __ROM0_SIZE {
|
||||
|
||||
ER_ROM0 __ROM0_BASE __ROM0_SIZE {
|
||||
*.o (RESET, +First)
|
||||
*(InRoot$$Sections)
|
||||
*(+RO +XO)
|
||||
}
|
||||
|
||||
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
|
||||
ER_CMSE_VENEER AlignExpr(+0, 32) (__ROM0_SIZE - AlignExpr(ImageLength(ER_ROM0), 32)) {
|
||||
*(Veneer$$CMSE)
|
||||
}
|
||||
#endif
|
||||
|
||||
RW_NOINIT __RAM0_BASE UNINIT (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE) {
|
||||
*.o(.bss.noinit)
|
||||
*.o(.bss.noinit.*)
|
||||
}
|
||||
|
||||
RW_RAM0 AlignExpr(+0, 8) (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE - AlignExpr(ImageLength(RW_NOINIT), 8)) {
|
||||
*(+RW +ZI)
|
||||
}
|
||||
|
||||
#if __HEAP_SIZE > 0
|
||||
ARM_LIB_HEAP (AlignExpr(+0, 8)) EMPTY __HEAP_SIZE { ; Reserve empty region for heap
|
||||
}
|
||||
#endif
|
||||
|
||||
ARM_LIB_STACK (__RAM0_BASE + __RAM0_SIZE - __STACKSEAL_SIZE) EMPTY -__STACK_SIZE { ; Reserve empty region for stack
|
||||
}
|
||||
|
||||
#if __STACKSEAL_SIZE > 0
|
||||
STACKSEAL +0 EMPTY __STACKSEAL_SIZE { ; Reserve empty region for stack seal immediately after stack
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __RAM1_SIZE > 0
|
||||
RW_RAM1 __RAM1_BASE __RAM1_SIZE {
|
||||
.ANY (+RW +ZI)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __RAM2_SIZE > 0
|
||||
RW_RAM2 __RAM2_BASE __RAM2_SIZE {
|
||||
.ANY (+RW +ZI)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __RAM3_SIZE > 0
|
||||
RW_RAM3 __RAM3_BASE __RAM3_SIZE {
|
||||
.ANY (+RW +ZI)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if __ROM1_SIZE > 0
|
||||
LR_ROM1 __ROM1_BASE __ROM1_SIZE {
|
||||
ER_ROM1 +0 __ROM1_SIZE {
|
||||
.ANY (+RO +XO)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __ROM2_SIZE > 0
|
||||
LR_ROM2 __ROM2_BASE __ROM2_SIZE {
|
||||
ER_ROM2 +0 __ROM2_SIZE {
|
||||
.ANY (+RO +XO)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __ROM3_SIZE > 0
|
||||
LR_ROM3 __ROM3_BASE __ROM3_SIZE {
|
||||
ER_ROM3 +0 __ROM3_SIZE {
|
||||
.ANY (+RO +XO)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,239 @@
|
||||
/*!
|
||||
\file gd32e50x_crc.c
|
||||
\brief CRC driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_crc.h"
|
||||
|
||||
/*!
|
||||
\brief deinitialize CRC calculation unit
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_deinit(void)
|
||||
{
|
||||
CRC_IDATA = (uint32_t)0xFFFFFFFFU;
|
||||
CRC_DATA = (uint32_t)0xFFFFFFFFU;
|
||||
CRC_FDATA = (uint32_t)0x00000000U;
|
||||
CRC_POLY = (uint32_t)0x04C11DB7U;
|
||||
CRC_CTL = CRC_CTL_RST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset data register to the value of initializaiton data register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_data_register_reset(void)
|
||||
{
|
||||
CRC_CTL |= (uint32_t)CRC_CTL_RST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the reverse operation of output data
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_reverse_output_data_enable(void)
|
||||
{
|
||||
CRC_CTL &= (uint32_t)(~ CRC_CTL_REV_O);
|
||||
CRC_CTL |= (uint32_t)CRC_CTL_REV_O;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the reverse operation of output data
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_reverse_output_data_disable(void)
|
||||
{
|
||||
CRC_CTL &= (uint32_t)(~ CRC_CTL_REV_O);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the CRC input data function
|
||||
\param[in] data_reverse: specify input data reverse function
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CRC_INPUT_DATA_NOT: input data is not reversed
|
||||
\arg CRC_INPUT_DATA_BYTE: input data is reversed on 8 bits
|
||||
\arg CRC_INPUT_DATA_HALFWORD: input data is reversed on 16 bits
|
||||
\arg CRC_INPUT_DATA_WORD: input data is reversed on 32 bits
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_input_data_reverse_config(uint32_t data_reverse)
|
||||
{
|
||||
CRC_CTL &= (uint32_t)(~CRC_CTL_REV_I);
|
||||
CRC_CTL |= (uint32_t)data_reverse;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the data register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval 32-bit value of the data register
|
||||
*/
|
||||
uint32_t crc_data_register_read(void)
|
||||
{
|
||||
uint32_t data;
|
||||
data = CRC_DATA;
|
||||
return (data);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the free data register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval 8-bit value of the free data register
|
||||
*/
|
||||
uint8_t crc_free_data_register_read(void)
|
||||
{
|
||||
uint8_t fdata;
|
||||
fdata = (uint8_t)CRC_FDATA;
|
||||
return (fdata);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write the free data register
|
||||
\param[in] free_data: specify 8-bit data
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_free_data_register_write(uint8_t free_data)
|
||||
{
|
||||
CRC_FDATA = (uint32_t)free_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write the initializaiton data register
|
||||
\param[in] init_data: specify 32-bit data
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_init_data_register_write(uint32_t init_data)
|
||||
{
|
||||
CRC_IDATA = (uint32_t)init_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the CRC size of polynomial function
|
||||
\param[in] poly_size: size of polynomial
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CRC_CTL_PS_32: 32-bit polynomial for CRC calculation
|
||||
\arg CRC_CTL_PS_16: 16-bit polynomial for CRC calculation
|
||||
\arg CRC_CTL_PS_8: 8-bit polynomial for CRC calculation
|
||||
\arg CRC_CTL_PS_7: 7-bit polynomial for CRC calculation
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_polynomial_size_set(uint32_t poly_size)
|
||||
{
|
||||
CRC_CTL &= (uint32_t)(~(CRC_CTL_PS));
|
||||
CRC_CTL |= (uint32_t)poly_size;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the CRC polynomial value function
|
||||
\param[in] poly: configurable polynomial value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_polynomial_set(uint32_t poly)
|
||||
{
|
||||
CRC_POLY &= (uint32_t)(~CRC_POLY_POLY);
|
||||
CRC_POLY = poly;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief CRC calculate single data
|
||||
\param[in] sdata: specify input data data
|
||||
\param[in] data_format: input data format
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg INPUT_FORMAT_WORD: input data in word format
|
||||
\arg INPUT_FORMAT_HALFWORD: input data in half-word format
|
||||
\arg INPUT_FORMAT_BYTE: input data in byte format
|
||||
\param[out] none
|
||||
\retval CRC calculate value
|
||||
*/
|
||||
uint32_t crc_single_data_calculate(uint32_t sdata, uint8_t data_format)
|
||||
{
|
||||
if(INPUT_FORMAT_WORD == data_format){
|
||||
REG32(CRC) = sdata;
|
||||
}else if(INPUT_FORMAT_HALFWORD == data_format){
|
||||
REG16(CRC) = (uint16_t)sdata;
|
||||
}else{
|
||||
REG8(CRC) = (uint8_t)sdata;
|
||||
}
|
||||
|
||||
return(CRC_DATA);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief CRC calculate a data array
|
||||
\param[in] array: pointer to the input data array
|
||||
\param[in] size: size of the array
|
||||
\param[in] data_format: input data format
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg INPUT_FORMAT_WORD: input data in word format
|
||||
\arg INPUT_FORMAT_HALFWORD: input data in half-word format
|
||||
\arg INPUT_FORMAT_BYTE: input data in byte format
|
||||
\param[out] none
|
||||
\retval CRC calculate value
|
||||
*/
|
||||
uint32_t crc_block_data_calculate(void *array, uint32_t size, uint8_t data_format)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t data = (uint32_t)array;
|
||||
|
||||
if(INPUT_FORMAT_WORD == data_format) {
|
||||
for(index = 0U; index < size; index++) {
|
||||
REG32(CRC) = *(uint32_t *)data;
|
||||
data += 4U;
|
||||
}
|
||||
} else if(INPUT_FORMAT_HALFWORD == data_format) {
|
||||
for(index = 0U; index < size; index++) {
|
||||
REG16(CRC) = *(uint16_t *)data;
|
||||
data += 2U;
|
||||
}
|
||||
} else {
|
||||
for(index = 0U; index < size; index++) {
|
||||
REG8(CRC) = *(uint8_t *)data;
|
||||
data += 1U;
|
||||
}
|
||||
}
|
||||
|
||||
return (CRC_DATA);
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/*!
|
||||
\file gd32e50x_crc.c
|
||||
\brief CRC driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_crc.h"
|
||||
|
||||
/*!
|
||||
\brief deinitialize CRC calculation unit
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_deinit(void)
|
||||
{
|
||||
CRC_IDATA = (uint32_t)0xFFFFFFFFU;
|
||||
CRC_DATA = (uint32_t)0xFFFFFFFFU;
|
||||
CRC_FDATA = (uint32_t)0x00000000U;
|
||||
CRC_POLY = (uint32_t)0x04C11DB7U;
|
||||
CRC_CTL = CRC_CTL_RST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset data register to the value of initializaiton data register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_data_register_reset(void)
|
||||
{
|
||||
CRC_CTL |= (uint32_t)CRC_CTL_RST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the reverse operation of output data
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_reverse_output_data_enable(void)
|
||||
{
|
||||
CRC_CTL &= (uint32_t)(~ CRC_CTL_REV_O);
|
||||
CRC_CTL |= (uint32_t)CRC_CTL_REV_O;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the reverse operation of output data
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_reverse_output_data_disable(void)
|
||||
{
|
||||
CRC_CTL &= (uint32_t)(~ CRC_CTL_REV_O);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the CRC input data function
|
||||
\param[in] data_reverse: specify input data reverse function
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CRC_INPUT_DATA_NOT: input data is not reversed
|
||||
\arg CRC_INPUT_DATA_BYTE: input data is reversed on 8 bits
|
||||
\arg CRC_INPUT_DATA_HALFWORD: input data is reversed on 16 bits
|
||||
\arg CRC_INPUT_DATA_WORD: input data is reversed on 32 bits
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_input_data_reverse_config(uint32_t data_reverse)
|
||||
{
|
||||
CRC_CTL &= (uint32_t)(~CRC_CTL_REV_I);
|
||||
CRC_CTL |= (uint32_t)data_reverse;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the data register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval 32-bit value of the data register
|
||||
*/
|
||||
uint32_t crc_data_register_read(void)
|
||||
{
|
||||
uint32_t data;
|
||||
data = CRC_DATA;
|
||||
return (data);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the free data register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval 8-bit value of the free data register
|
||||
*/
|
||||
uint8_t crc_free_data_register_read(void)
|
||||
{
|
||||
uint8_t fdata;
|
||||
fdata = (uint8_t)CRC_FDATA;
|
||||
return (fdata);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write the free data register
|
||||
\param[in] free_data: specify 8-bit data
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_free_data_register_write(uint8_t free_data)
|
||||
{
|
||||
CRC_FDATA = (uint32_t)free_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write the initializaiton data register
|
||||
\param[in] init_data: specify 32-bit data
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_init_data_register_write(uint32_t init_data)
|
||||
{
|
||||
CRC_IDATA = (uint32_t)init_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the CRC size of polynomial function
|
||||
\param[in] poly_size: size of polynomial
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CRC_CTL_PS_32: 32-bit polynomial for CRC calculation
|
||||
\arg CRC_CTL_PS_16: 16-bit polynomial for CRC calculation
|
||||
\arg CRC_CTL_PS_8: 8-bit polynomial for CRC calculation
|
||||
\arg CRC_CTL_PS_7: 7-bit polynomial for CRC calculation
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_polynomial_size_set(uint32_t poly_size)
|
||||
{
|
||||
CRC_CTL &= (uint32_t)(~(CRC_CTL_PS));
|
||||
CRC_CTL |= (uint32_t)poly_size;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the CRC polynomial value function
|
||||
\param[in] poly: configurable polynomial value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_polynomial_set(uint32_t poly)
|
||||
{
|
||||
CRC_POLY &= (uint32_t)(~CRC_POLY_POLY);
|
||||
CRC_POLY = poly;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief CRC calculate single data
|
||||
\param[in] sdata: specify input data data
|
||||
\param[in] data_format: input data format
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg INPUT_FORMAT_WORD: input data in word format
|
||||
\arg INPUT_FORMAT_HALFWORD: input data in half-word format
|
||||
\arg INPUT_FORMAT_BYTE: input data in byte format
|
||||
\param[out] none
|
||||
\retval CRC calculate value
|
||||
*/
|
||||
uint32_t crc_single_data_calculate(uint32_t sdata, uint8_t data_format)
|
||||
{
|
||||
if(INPUT_FORMAT_WORD == data_format){
|
||||
REG32(CRC) = sdata;
|
||||
}else if(INPUT_FORMAT_HALFWORD == data_format){
|
||||
REG16(CRC) = (uint16_t)sdata;
|
||||
}else{
|
||||
REG8(CRC) = (uint8_t)sdata;
|
||||
}
|
||||
|
||||
return(CRC_DATA);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief CRC calculate a data array
|
||||
\param[in] array: pointer to the input data array
|
||||
\param[in] size: size of the array
|
||||
\param[in] data_format: input data format
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg INPUT_FORMAT_WORD: input data in word format
|
||||
\arg INPUT_FORMAT_HALFWORD: input data in half-word format
|
||||
\arg INPUT_FORMAT_BYTE: input data in byte format
|
||||
\param[out] none
|
||||
\retval CRC calculate value
|
||||
*/
|
||||
uint32_t crc_block_data_calculate(void *array, uint32_t size, uint8_t data_format)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t data = (uint32_t)array;
|
||||
|
||||
if(INPUT_FORMAT_WORD == data_format) {
|
||||
for(index = 0U; index < size; index++) {
|
||||
REG32(CRC) = *(uint32_t *)data;
|
||||
data += 4U;
|
||||
}
|
||||
} else if(INPUT_FORMAT_HALFWORD == data_format) {
|
||||
for(index = 0U; index < size; index++) {
|
||||
REG16(CRC) = *(uint16_t *)data;
|
||||
data += 2U;
|
||||
}
|
||||
} else {
|
||||
for(index = 0U; index < size; index++) {
|
||||
REG8(CRC) = *(uint8_t *)data;
|
||||
data += 1U;
|
||||
}
|
||||
}
|
||||
|
||||
return (CRC_DATA);
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*!
|
||||
\file gd32e50x_dbg.c
|
||||
\brief DBG driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_dbg.h"
|
||||
|
||||
#define DBG_RESET_VAL ((uint32_t)0x00000000U) /*!< DBG reset value */
|
||||
|
||||
/*!
|
||||
\brief deinitialize the DBG
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_deinit(void)
|
||||
{
|
||||
DBG_CTL = 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:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode
|
||||
\arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode
|
||||
\arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_low_power_enable(uint32_t dbg_low_power)
|
||||
{
|
||||
DBG_CTL |= dbg_low_power;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable low power behavior when the mcu is in debug mode
|
||||
\param[in] dbg_low_power:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_LOW_POWER_SLEEP: do not keep debugger connection during sleep mode
|
||||
\arg DBG_LOW_POWER_DEEPSLEEP: do not keep debugger connection during deepsleep mode
|
||||
\arg DBG_LOW_POWER_STANDBY: do not keep debugger connection during standby mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_low_power_disable(uint32_t dbg_low_power)
|
||||
{
|
||||
DBG_CTL &= ~dbg_low_power;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable peripheral behavior when the mcu is in debug mode
|
||||
\param[in] dbg_periph: refer to dbg_periph_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DBG_FWDGT_HOLD : hold FWDGT counter when core is halted
|
||||
\arg DBG_WWDGT_HOLD : hold WWDGT counter when core is halted
|
||||
\arg DBG_CANx_HOLD (x=0,1,2 CAN2 is only available for CL series, CANx are not available for GD32EPRT series): hold CANx receive register counter when core is halted
|
||||
\arg DBG_I2Cx_HOLD (x=0,1,2): hold I2Cx smbus timeout when core is halted
|
||||
\arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13, TIMER8..13 are not available for GD32EPRT series): hold TIMERx counter when core is halted
|
||||
\arg DBG_SHRTIMER_HOLD : hold SHRTIMER counter when core is halted, except for GD32EPRT series
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_periph_enable(dbg_periph_enum dbg_periph)
|
||||
{
|
||||
DBG_REG_VAL(dbg_periph) |= BIT(DBG_BIT_POS(dbg_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable peripheral behavior when the mcu is in debug mode
|
||||
\param[in] dbg_periph: refer to dbg_periph_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DBG_FWDGT_HOLD : hold FWDGT counter when core is halted
|
||||
\arg DBG_WWDGT_HOLD : hold WWDGT counter when core is halted
|
||||
\arg DBG_CANx_HOLD (x=0,1,2 CAN2 is only available for CL series, CANx are not available for GD32EPRT series): hold CANx receive register counter when core is halted
|
||||
\arg DBG_I2Cx_HOLD (x=0,1,2): hold I2Cx smbus timeout when core is halted
|
||||
\arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for GD32EPRT series): hold TIMERx counter when core is halted
|
||||
\arg DBG_SHRTIMER_HOLD : hold SHRTIMER counter when core is halted, except for GD32EPRT series
|
||||
\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_CTL |= DBG_CTL_TRACE_IOEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable trace pin assignment
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_trace_pin_disable(void)
|
||||
{
|
||||
DBG_CTL &= ~DBG_CTL_TRACE_IOEN;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/*!
|
||||
\file gd32e50x_dbg.c
|
||||
\brief DBG driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_dbg.h"
|
||||
|
||||
#define DBG_RESET_VAL ((uint32_t)0x00000000U) /*!< DBG reset value */
|
||||
|
||||
/*!
|
||||
\brief deinitialize the DBG
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_deinit(void)
|
||||
{
|
||||
DBG_CTL = 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:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode
|
||||
\arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode
|
||||
\arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_low_power_enable(uint32_t dbg_low_power)
|
||||
{
|
||||
DBG_CTL |= dbg_low_power;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable low power behavior when the mcu is in debug mode
|
||||
\param[in] dbg_low_power:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_LOW_POWER_SLEEP: do not keep debugger connection during sleep mode
|
||||
\arg DBG_LOW_POWER_DEEPSLEEP: do not keep debugger connection during deepsleep mode
|
||||
\arg DBG_LOW_POWER_STANDBY: do not keep debugger connection during standby mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_low_power_disable(uint32_t dbg_low_power)
|
||||
{
|
||||
DBG_CTL &= ~dbg_low_power;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable peripheral behavior when the mcu is in debug mode
|
||||
\param[in] dbg_periph: refer to dbg_periph_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DBG_FWDGT_HOLD : hold FWDGT counter when core is halted
|
||||
\arg DBG_WWDGT_HOLD : hold WWDGT counter when core is halted
|
||||
\arg DBG_CANx_HOLD (x=0,1,2 CAN2 is only available for CL series, CANx are not available for GD32EPRT series): hold CANx receive register counter when core is halted
|
||||
\arg DBG_I2Cx_HOLD (x=0,1,2): hold I2Cx smbus timeout when core is halted
|
||||
\arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13, TIMER8..13 are not available for GD32EPRT series): hold TIMERx counter when core is halted
|
||||
\arg DBG_SHRTIMER_HOLD : hold SHRTIMER counter when core is halted, except for GD32EPRT series
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_periph_enable(dbg_periph_enum dbg_periph)
|
||||
{
|
||||
DBG_REG_VAL(dbg_periph) |= BIT(DBG_BIT_POS(dbg_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable peripheral behavior when the mcu is in debug mode
|
||||
\param[in] dbg_periph: refer to dbg_periph_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DBG_FWDGT_HOLD : hold FWDGT counter when core is halted
|
||||
\arg DBG_WWDGT_HOLD : hold WWDGT counter when core is halted
|
||||
\arg DBG_CANx_HOLD (x=0,1,2 CAN2 is only available for CL series, CANx are not available for GD32EPRT series): hold CANx receive register counter when core is halted
|
||||
\arg DBG_I2Cx_HOLD (x=0,1,2): hold I2Cx smbus timeout when core is halted
|
||||
\arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for GD32EPRT series): hold TIMERx counter when core is halted
|
||||
\arg DBG_SHRTIMER_HOLD : hold SHRTIMER counter when core is halted, except for GD32EPRT series
|
||||
\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_CTL |= DBG_CTL_TRACE_IOEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable trace pin assignment
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_trace_pin_disable(void)
|
||||
{
|
||||
DBG_CTL &= ~DBG_CTL_TRACE_IOEN;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,752 @@
|
||||
/*!
|
||||
\file gd32e50x_dma.c
|
||||
\brief DMA driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_dma.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DMA_WRONG_HANDLE while(1){}
|
||||
|
||||
/* check whether peripheral matches channels or not */
|
||||
static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx);
|
||||
|
||||
/*!
|
||||
\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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* 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_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
|
||||
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the parameters of DMA struct with the default values
|
||||
\param[in] init_struct: the initialization data needed to initialize DMA channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_struct_para_init(dma_parameter_struct* init_struct)
|
||||
{
|
||||
if(NULL == init_struct){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* 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->memory_addr = 0U;
|
||||
init_struct->memory_width = 0U;
|
||||
init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE;
|
||||
init_struct->number = 0U;
|
||||
init_struct->direction = DMA_PERIPHERAL_TO_MEMORY;
|
||||
init_struct->priority = DMA_PRIORITY_LOW;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel is initialized
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] init_struct: the data needed to initialize DMA channel
|
||||
periph_addr: peripheral base address
|
||||
periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT
|
||||
periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE
|
||||
memory_addr: memory 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
|
||||
direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL
|
||||
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_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct* init_struct)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(NULL == init_struct){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* configure peripheral base address */
|
||||
DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
|
||||
|
||||
/* configure memory base address */
|
||||
DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr;
|
||||
|
||||
/* configure the number of remaining data to be transferred */
|
||||
DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK);
|
||||
|
||||
/* configure peripheral transfer width,memory transfer width and priority */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO);
|
||||
ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority);
|
||||
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{
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/* 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 the direction of data transfer */
|
||||
if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
|
||||
}else{
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable memory to memory mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable memory to memory mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\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)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHPADDR(dma_periph, channelx) = address;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set DMA memory 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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] address: memory base address
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHMADDR(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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] number: the number of remaining data to be transferred by the DMA, 0x00000000-0x0000FFFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval uint32_t: the number of remaining data to be transferred by the DMA, 0x00000000-0x0000FFFF
|
||||
*/
|
||||
uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\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;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* 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 data size of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] mwidth: transfer data width of memory
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit
|
||||
\arg DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit
|
||||
\arg DMA_MEMORY_WIDTH_32BIT: transfer data width 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 mwidth)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* acquire DMA_CHxCTL register */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
/* assign regiser */
|
||||
ctl &= ~DMA_CHXCTL_MWIDTH;
|
||||
ctl |= mwidth;
|
||||
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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] pwidth: transfer data width of peripheral
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit
|
||||
\arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit
|
||||
\arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data width 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 pwidth)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* acquire DMA_CHxCTL register */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
/* assign regiser */
|
||||
ctl &= ~DMA_CHXCTL_PWIDTH;
|
||||
ctl |= pwidth;
|
||||
DMA_CHCTL(dma_periph, channelx) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable next address increasement algorithm of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable next address increasement algorithm of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable next address increasement algorithm of peripheral
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable next address increasement algorithm of peripheral
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] direction: specify the direction of data transfer
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory
|
||||
\arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
if(DMA_PERIPHERAL_TO_MEMORY == direction){
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
|
||||
}else {
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check 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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_FLAG_FTF: full transfer finish flag of channel
|
||||
\arg DMA_FLAG_HTF: half transfer finish flag of channel
|
||||
\arg DMA_FLAG_ERR: error flag of channel
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
FlagStatus reval;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){
|
||||
reval = SET;
|
||||
}else{
|
||||
reval = RESET;
|
||||
}
|
||||
|
||||
return reval;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear a DMA channel flag
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel to clear flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_FLAG_FTF: full transfer finish flag of channel
|
||||
\arg DMA_FLAG_HTF: half transfer finish flag of channel
|
||||
\arg DMA_FLAG_ERR: error flag of channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_INTC(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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] source: specify which interrupt to enbale
|
||||
one or more parameters can be selected which are shown as below
|
||||
\arg DMA_INT_FTF: channel full transfer finish interrupt
|
||||
\arg DMA_INT_HTF: channel half transfer finish interrupt
|
||||
\arg DMA_INT_ERR: channel error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] source: specify which interrupt to disbale
|
||||
one or more parameters can be selected which are shown as below
|
||||
\arg DMA_INT_FTF: channel full transfer finish interrupt
|
||||
\arg DMA_INT_HTF: channel half transfer finish interrupt
|
||||
\arg DMA_INT_ERR: channel error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~source;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check DMA flag and interrupt enable bit 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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_ERR: error interrupt flag of channel
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
switch(flag){
|
||||
case DMA_INT_FLAG_FTF:
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE;
|
||||
break;
|
||||
case DMA_INT_FLAG_HTF:
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
|
||||
break;
|
||||
case DMA_INT_FLAG_ERR:
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE;
|
||||
break;
|
||||
default:
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
if(interrupt_flag && interrupt_enable){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear a DMA channel flag
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel to clear flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_INT_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_ERR: error interrupt flag of channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check whether peripheral and channels match
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_CHx(x=0..6)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
ErrStatus val = SUCCESS;
|
||||
|
||||
if(DMA1 == dma_periph){
|
||||
/* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */
|
||||
if(channelx > DMA_CH4){
|
||||
val = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
@@ -0,0 +1,752 @@
|
||||
/*!
|
||||
\file gd32e50x_dma.c
|
||||
\brief DMA driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_dma.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DMA_WRONG_HANDLE while(1){}
|
||||
|
||||
/* check whether peripheral matches channels or not */
|
||||
static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx);
|
||||
|
||||
/*!
|
||||
\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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* 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_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
|
||||
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the parameters of DMA struct with the default values
|
||||
\param[in] init_struct: the initialization data needed to initialize DMA channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_struct_para_init(dma_parameter_struct* init_struct)
|
||||
{
|
||||
if(NULL == init_struct){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* 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->memory_addr = 0U;
|
||||
init_struct->memory_width = 0U;
|
||||
init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE;
|
||||
init_struct->number = 0U;
|
||||
init_struct->direction = DMA_PERIPHERAL_TO_MEMORY;
|
||||
init_struct->priority = DMA_PRIORITY_LOW;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel is initialized
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] init_struct: the data needed to initialize DMA channel
|
||||
periph_addr: peripheral base address
|
||||
periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT
|
||||
periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE
|
||||
memory_addr: memory 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
|
||||
direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL
|
||||
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_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct* init_struct)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(NULL == init_struct){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* configure peripheral base address */
|
||||
DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
|
||||
|
||||
/* configure memory base address */
|
||||
DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr;
|
||||
|
||||
/* configure the number of remaining data to be transferred */
|
||||
DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK);
|
||||
|
||||
/* configure peripheral transfer width,memory transfer width and priority */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO);
|
||||
ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority);
|
||||
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{
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/* 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 the direction of data transfer */
|
||||
if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
|
||||
}else{
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable memory to memory mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable memory to memory mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\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)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHPADDR(dma_periph, channelx) = address;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set DMA memory 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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] address: memory base address
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHMADDR(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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] number: the number of remaining data to be transferred by the DMA, 0x00000000-0x0000FFFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval uint32_t: the number of remaining data to be transferred by the DMA, 0x00000000-0x0000FFFF
|
||||
*/
|
||||
uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\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;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* 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 data size of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] mwidth: transfer data width of memory
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit
|
||||
\arg DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit
|
||||
\arg DMA_MEMORY_WIDTH_32BIT: transfer data width 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 mwidth)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* acquire DMA_CHxCTL register */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
/* assign regiser */
|
||||
ctl &= ~DMA_CHXCTL_MWIDTH;
|
||||
ctl |= mwidth;
|
||||
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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] pwidth: transfer data width of peripheral
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit
|
||||
\arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit
|
||||
\arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data width 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 pwidth)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* acquire DMA_CHxCTL register */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
/* assign regiser */
|
||||
ctl &= ~DMA_CHXCTL_PWIDTH;
|
||||
ctl |= pwidth;
|
||||
DMA_CHCTL(dma_periph, channelx) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable next address increasement algorithm of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable next address increasement algorithm of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable next address increasement algorithm of peripheral
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable next address increasement algorithm of peripheral
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] direction: specify the direction of data transfer
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory
|
||||
\arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
if(DMA_PERIPHERAL_TO_MEMORY == direction){
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
|
||||
}else {
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check 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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_FLAG_FTF: full transfer finish flag of channel
|
||||
\arg DMA_FLAG_HTF: half transfer finish flag of channel
|
||||
\arg DMA_FLAG_ERR: error flag of channel
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
FlagStatus reval;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){
|
||||
reval = SET;
|
||||
}else{
|
||||
reval = RESET;
|
||||
}
|
||||
|
||||
return reval;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear a DMA channel flag
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel to clear flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_FLAG_FTF: full transfer finish flag of channel
|
||||
\arg DMA_FLAG_HTF: half transfer finish flag of channel
|
||||
\arg DMA_FLAG_ERR: error flag of channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_INTC(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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] source: specify which interrupt to enbale
|
||||
one or more parameters can be selected which are shown as below
|
||||
\arg DMA_INT_FTF: channel full transfer finish interrupt
|
||||
\arg DMA_INT_HTF: channel half transfer finish interrupt
|
||||
\arg DMA_INT_ERR: channel error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] source: specify which interrupt to disbale
|
||||
one or more parameters can be selected which are shown as below
|
||||
\arg DMA_INT_FTF: channel full transfer finish interrupt
|
||||
\arg DMA_INT_HTF: channel half transfer finish interrupt
|
||||
\arg DMA_INT_ERR: channel error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~source;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check DMA flag and interrupt enable bit 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
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_ERR: error interrupt flag of channel
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
switch(flag){
|
||||
case DMA_INT_FLAG_FTF:
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE;
|
||||
break;
|
||||
case DMA_INT_FLAG_HTF:
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
|
||||
break;
|
||||
case DMA_INT_FLAG_ERR:
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE;
|
||||
break;
|
||||
default:
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
if(interrupt_flag && interrupt_enable){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear a DMA channel flag
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel to clear flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_INT_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_ERR: error interrupt flag of channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check whether peripheral and channels match
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specify which DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_CHx(x=0..6)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
ErrStatus val = SUCCESS;
|
||||
|
||||
if(DMA1 == dma_periph){
|
||||
/* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */
|
||||
if(channelx > DMA_CH4){
|
||||
val = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/*!
|
||||
\file gd32e50x_exti.c
|
||||
\brief EXTI driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_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..21): 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..21): 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..21): 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..21): 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..21): 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..21): 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..21): 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..21): 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..21): 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..21): 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..21): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_interrupt_flag_clear(exti_line_enum linex)
|
||||
{
|
||||
EXTI_PD = (uint32_t)linex;
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/*!
|
||||
\file gd32e50x_exti.c
|
||||
\brief EXTI driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_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..21): 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..21): 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..21): 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..21): 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..21): 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..21): 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..21): 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..21): 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..21): 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..21): 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..21): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_interrupt_flag_clear(exti_line_enum linex)
|
||||
{
|
||||
EXTI_PD = (uint32_t)linex;
|
||||
}
|
||||
@@ -0,0 +1,875 @@
|
||||
/*!
|
||||
\file gd32e50x_fmc.c
|
||||
\brief FMC driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_fmc.h"
|
||||
|
||||
/* FMC mask */
|
||||
#define LOW_8BITS_MASK ((uint32_t)0x000000FFU)
|
||||
#define HIGH_8BITS_MASK ((uint32_t)0x0000FF00U)
|
||||
#define LOW_8BITS_MASK1 ((uint32_t)0x00FF0000U)
|
||||
#define HIGH_8BITS_MASK1 ((uint32_t)0xFF000000U)
|
||||
#define LOW_16BITS_MASK ((uint32_t)0x0000FFFFU)
|
||||
#define HIGH_16BITS_MASK ((uint32_t)0xFFFF0000U)
|
||||
|
||||
/* USER of option bytes mask */
|
||||
#define OB_USER_MASK ((uint8_t)0x38U)
|
||||
|
||||
/* default offset */
|
||||
#define FMC_OBSTAT_USER_OFFSET 2U
|
||||
#define FMC_OBSTAT_DATA_OFFSET 10U
|
||||
|
||||
/* return the FMC state */
|
||||
static fmc_state_enum fmc_state_get(void);
|
||||
/* check FMC ready or not */
|
||||
static fmc_state_enum fmc_ready_wait(uint32_t timeout);
|
||||
|
||||
/*!
|
||||
\brief unlock the main FMC operation
|
||||
it is better to used in pairs with fmc_lock
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_unlock(void)
|
||||
{
|
||||
if(RESET != (FMC_CTL & FMC_CTL_LK)){
|
||||
/* write the FMC unlock key */
|
||||
FMC_KEY = UNLOCK_KEY0;
|
||||
FMC_KEY = UNLOCK_KEY1;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief lock the main FMC operation
|
||||
it is better to used in pairs with fmc_unlock after an operation
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_lock(void)
|
||||
{
|
||||
/* set the LK bit */
|
||||
FMC_CTL |= FMC_CTL_LK;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set the wait state
|
||||
\param[in] wscnt: wait state
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_WAIT_STATE_0: 0 wait state added
|
||||
\arg FMC_WAIT_STATE_1: 1 wait state added
|
||||
\arg FMC_WAIT_STATE_2: 2 wait state added
|
||||
\arg FMC_WAIT_STATE_3: 3 wait state added
|
||||
\arg FMC_WAIT_STATE_4: 4 wait state added
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_wscnt_set(uint32_t wscnt)
|
||||
{
|
||||
uint32_t ws;
|
||||
|
||||
ws = FMC_WS;
|
||||
|
||||
/* set the wait state counter value */
|
||||
ws &= ~FMC_WS_WSCNT;
|
||||
FMC_WS = (ws | wscnt);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable pre-fetch
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_prefetch_enable(void)
|
||||
{
|
||||
FMC_WS |= FMC_WS_PFEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable pre-fetch
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_prefetch_disable(void)
|
||||
{
|
||||
FMC_WS &= ~FMC_WS_PFEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable IBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_ibus_enable(void)
|
||||
{
|
||||
FMC_WS |= FMC_WS_ICEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable IBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_ibus_disable(void)
|
||||
{
|
||||
FMC_WS &= ~FMC_WS_ICEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset IBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_ibus_reset(void)
|
||||
{
|
||||
FMC_WS |= FMC_WS_ICRST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_dbus_enable(void)
|
||||
{
|
||||
FMC_WS |= FMC_WS_DCEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_dbus_disable(void)
|
||||
{
|
||||
FMC_WS &= ~FMC_WS_DCEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset DBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_dbus_reset(void)
|
||||
{
|
||||
FMC_WS |= FMC_WS_DCRST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief FMC erase page
|
||||
\param[in] page_address: target page address
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
*/
|
||||
fmc_state_enum fmc_page_erase(uint32_t page_address)
|
||||
{
|
||||
fmc_state_enum fmc_state;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start page erase */
|
||||
FMC_CTL |= FMC_CTL_PER;
|
||||
FMC_ADDR = page_address;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
/* reset the PER bit */
|
||||
FMC_CTL &= ~FMC_CTL_PER;
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief FMC erase whole chip
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
*/
|
||||
fmc_state_enum fmc_mass_erase(void)
|
||||
{
|
||||
fmc_state_enum fmc_state;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start chip erase */
|
||||
FMC_CTL |= FMC_CTL_MER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
/* reset the MER bit */
|
||||
FMC_CTL &= ~FMC_CTL_MER;
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief FMC program a word at the corresponding address
|
||||
\param[in] address: address to program
|
||||
\param[in] data: word to program
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
*/
|
||||
fmc_state_enum fmc_word_program(uint32_t address, uint32_t data)
|
||||
{
|
||||
fmc_state_enum fmc_state;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* set the PG bit to start program */
|
||||
FMC_CTL |= FMC_CTL_PG;
|
||||
REG32(address) = data;
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
/* reset the PG bit */
|
||||
FMC_CTL &= ~FMC_CTL_PG;
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief unlock the option bytes operation
|
||||
it is better to used in pairs with ob_lock
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ob_unlock(void)
|
||||
{
|
||||
if(RESET == (FMC_CTL & FMC_CTL_OBWEN)){
|
||||
/* write the FMC ob unlock key */
|
||||
FMC_OBKEY = UNLOCK_KEY0;
|
||||
FMC_OBKEY = UNLOCK_KEY1;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief lock the option bytes operation
|
||||
it is better to used in pairs with ob_unlock after an operation
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ob_lock(void)
|
||||
{
|
||||
/* reset the OBWEN bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBWEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief erase the option bytes
|
||||
programmer must ensure FMC & option bytes are both unlocked before calling this function
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
\arg FMC_OB_HSPC: high security protection
|
||||
*/
|
||||
fmc_state_enum ob_erase(void)
|
||||
{
|
||||
uint32_t temp_spc;
|
||||
fmc_state_enum fmc_state;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
temp_spc = OB_SPC_USER;
|
||||
|
||||
/* check the option bytes security protection value */
|
||||
if((RESET != ob_security_protection_flag_get()) && (FMC_HSPC == (temp_spc & LOW_8BITS_MASK))){
|
||||
fmc_state = FMC_OB_HSPC;
|
||||
}
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start erase the option bytes */
|
||||
FMC_CTL |= FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* reset the OBER bit and enable the option bytes programming */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
/* set the OBPG bit */
|
||||
FMC_CTL |= FMC_CTL_OBPG;
|
||||
/* restore the last get option bytes security protection code */
|
||||
OB_SPC_USER = (temp_spc & LOW_8BITS_MASK) | LOW_8BITS_MASK1;
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
/* reset the OBPG bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBPG;
|
||||
}else{
|
||||
/* reset the OBER bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
}
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable write protection
|
||||
programmer must ensure FMC & option bytes are both unlocked before calling this function
|
||||
\param[in] ob_wp: specify sector to be write protected
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg OB_WP_NONE: disable all write protection
|
||||
\arg OB_WP_x(x=0..31): write protect specify sector
|
||||
\arg OB_WP_ALL: write protect all sector
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
\arg FMC_OB_HSPC: high security protection
|
||||
*/
|
||||
fmc_state_enum ob_write_protection_enable(uint32_t ob_wp)
|
||||
{
|
||||
uint32_t temp_spc;
|
||||
uint8_t i;
|
||||
uint32_t op_byte[4];
|
||||
|
||||
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
temp_spc = OB_SPC_USER;
|
||||
|
||||
/* check the option bytes security protection value */
|
||||
if((RESET != ob_security_protection_flag_get()) && (FMC_HSPC == (temp_spc & LOW_8BITS_MASK))){
|
||||
fmc_state = FMC_OB_HSPC;
|
||||
}
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
op_byte[i] = OP_BYTE(i);
|
||||
}
|
||||
|
||||
ob_wp = (uint32_t)(~ob_wp);
|
||||
op_byte[2] = (ob_wp & LOW_8BITS_MASK) | ((ob_wp & HIGH_8BITS_MASK) << 8);
|
||||
op_byte[3] = ((ob_wp & LOW_8BITS_MASK1) >> 16) | ((ob_wp & HIGH_8BITS_MASK1) >> 8);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start erase the option byte */
|
||||
FMC_CTL |= FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* reset the OBER bit and enable the option bytes programming */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_OBPG;
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
OP_BYTE(i) = op_byte[i];
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
if(FMC_READY != fmc_state){
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* reset the OBPG bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBPG;
|
||||
}else{
|
||||
/* reset the OBER bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure security protection
|
||||
programmer must ensure FMC & option bytes are both unlocked before calling this function
|
||||
\param[in] ob_spc: specify security protection
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_NSPC: no security protection
|
||||
\arg FMC_LSPC: low security protection
|
||||
\arg FMC_HSPC: high security protection
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
\arg FMC_OB_HSPC: high security protection
|
||||
*/
|
||||
fmc_state_enum ob_security_protection_config(uint8_t ob_spc)
|
||||
{
|
||||
uint32_t temp_spc;
|
||||
uint8_t i;
|
||||
uint32_t op_byte[4];
|
||||
|
||||
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
temp_spc = OB_SPC_USER & LOW_16BITS_MASK;
|
||||
|
||||
/* check the option bytes security protection value */
|
||||
if((RESET != ob_security_protection_flag_get()) && (FMC_HSPC == (temp_spc & LOW_8BITS_MASK))){
|
||||
fmc_state = FMC_OB_HSPC;
|
||||
}
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
op_byte[i] = OP_BYTE(i);
|
||||
}
|
||||
op_byte[0] = ((uint32_t)(ob_spc)) | ((op_byte[0] & HIGH_16BITS_MASK));
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start erase the option bytes */
|
||||
FMC_CTL |= FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* reset the OBER bit and enable the option bytes programming */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_OBPG;
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
OP_BYTE(i) = op_byte[i];
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
if(FMC_READY != fmc_state){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset the OBPG bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBPG;
|
||||
}else{
|
||||
/* reset the OBER bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief program option bytes USER
|
||||
programmer must ensure FMC & option bytes are both unlocked before calling this function
|
||||
\param[in] ob_fwdgt: option bytes free watchdog value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg OB_FWDGT_SW: software free watchdog
|
||||
\arg OB_FWDGT_HW: hardware free watchdog
|
||||
\param[in] ob_deepsleep: option bytes deepsleep reset value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode
|
||||
\arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode
|
||||
\param[in] ob_stdby:option bytes standby reset value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg OB_STDBY_NRST: no reset when entering standby mode
|
||||
\arg OB_STDBY_RST: generate a reset instead of entering standby mode
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
\arg FMC_OB_HSPC: high security protection
|
||||
*/
|
||||
fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby)
|
||||
{
|
||||
uint32_t temp_spc;
|
||||
uint8_t temp;
|
||||
uint8_t i;
|
||||
uint32_t op_byte[4];
|
||||
|
||||
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
temp_spc = OB_SPC_USER;
|
||||
|
||||
/* check the option bytes security protection value */
|
||||
if((RESET != ob_security_protection_flag_get()) && (FMC_HSPC == (temp_spc & LOW_8BITS_MASK))){
|
||||
fmc_state = FMC_OB_HSPC;
|
||||
}
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
op_byte[i] = OP_BYTE(i);
|
||||
}
|
||||
temp = ((uint8_t)((uint8_t)(((uint8_t)(ob_fwdgt) | ob_deepsleep) | ob_stdby)) | (OB_USER_MASK));
|
||||
op_byte[0] = ((uint32_t)(temp) << 16U) | ((op_byte[0] & LOW_16BITS_MASK));
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start erase the option bytes */
|
||||
FMC_CTL |= FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
if(FMC_READY == fmc_state){
|
||||
/* reset the OBER bit and enable the option bytes programming */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_OBPG;
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
OP_BYTE(i) = op_byte[i];
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
if(FMC_READY != fmc_state){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset the OBPG bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBPG;
|
||||
}else{
|
||||
/* reset the OBER bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
}
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief program option bytes DATA
|
||||
\param[in] data: the byte to be programmed
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
\arg FMC_OB_HSPC: high security protection
|
||||
*/
|
||||
fmc_state_enum ob_data_program(uint16_t ob_data)
|
||||
{
|
||||
uint32_t temp_spc;
|
||||
uint8_t i;
|
||||
uint32_t op_byte[4];
|
||||
|
||||
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
temp_spc = OB_SPC_USER;
|
||||
|
||||
/* check the option bytes security protection value */
|
||||
if((RESET != ob_security_protection_flag_get()) && (FMC_HSPC == (temp_spc & LOW_8BITS_MASK))){
|
||||
fmc_state = FMC_OB_HSPC;
|
||||
}
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
op_byte[i] = OP_BYTE(i);
|
||||
}
|
||||
op_byte[1] = (uint32_t)((ob_data & LOW_8BITS_MASK) | ((ob_data & HIGH_8BITS_MASK) << 8));
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start erase the option bytes */
|
||||
FMC_CTL |= FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* reset the OBER bit and enable the option bytes programming */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_OBPG;
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
OP_BYTE(i) = op_byte[i];
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
if(FMC_READY != fmc_state){
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* reset the OBPG bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBPG;
|
||||
}else{
|
||||
/* reset the OBER bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the value of option bytes USER
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the option bytes USER value
|
||||
*/
|
||||
uint8_t ob_user_get(void)
|
||||
{
|
||||
/* return the FMC user option bytes value */
|
||||
return (uint8_t)(FMC_OBSTAT >> FMC_OBSTAT_USER_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the value of option bytes DATA
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the option bytes DATA value
|
||||
*/
|
||||
uint16_t ob_data_get(void)
|
||||
{
|
||||
return (uint16_t)(FMC_OBSTAT >> FMC_OBSTAT_DATA_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the value of option bytes write protection
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the write protection option bytes value
|
||||
*/
|
||||
uint32_t ob_write_protection_get(void)
|
||||
{
|
||||
/* return the FMC write protection option bytes value */
|
||||
return FMC_WP;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the FMC option bytes security protection state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus ob_security_protection_flag_get(void)
|
||||
{
|
||||
FlagStatus spc_state = RESET;
|
||||
|
||||
if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){
|
||||
spc_state = SET;
|
||||
}else{
|
||||
spc_state = RESET;
|
||||
}
|
||||
return spc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get FMC flag status
|
||||
\param[in] flag: FMC flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_FLAG_BUSY: FMC busy flag
|
||||
\arg FMC_FLAG_PGERR: FMC program error flag
|
||||
\arg FMC_FLAG_PGAERR: FMC program alignment error flag
|
||||
\arg FMC_FLAG_WPERR: FMC erase/program protection error flag
|
||||
\arg FMC_FLAG_END: FMC end of operation flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus fmc_flag_get(uint32_t flag)
|
||||
{
|
||||
FlagStatus status = RESET;
|
||||
|
||||
if(FMC_STAT & flag){
|
||||
status = SET;
|
||||
}
|
||||
/* return the state of corresponding FMC flag */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear the FMC flag
|
||||
\param[in] flag: FMC flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_FLAG_PGERR: FMC program error flag
|
||||
\arg FMC_FLAG_PGAERR: FMC program alignment error flag
|
||||
\arg FMC_FLAG_WPERR: FMC erase/program protection error flag
|
||||
\arg FMC_FLAG_END: FMC end of operation flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_flag_clear(uint32_t flag)
|
||||
{
|
||||
/* clear the flags */
|
||||
FMC_STAT = flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable FMC interrupt
|
||||
\param[in] interrupt: the FMC interrupt
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_INT_END: FMC end of operation interrupt
|
||||
\arg FMC_INT_ERR: FMC error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_interrupt_enable(uint32_t interrupt)
|
||||
{
|
||||
FMC_CTL |= interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable FMC interrupt
|
||||
\param[in] interrupt: the FMC interrupt
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_INT_END: FMC end of operation interrupt
|
||||
\arg FMC_INT_ERR: FMC error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_interrupt_disable(uint32_t interrupt)
|
||||
{
|
||||
FMC_CTL &= ~(uint32_t)interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get FMC interrupt flag
|
||||
\param[in] flag: FMC interrupt flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_INT_FLAG_PGERR: FMC operation error interrupt flag
|
||||
\arg FMC_INT_FLAG_PGAERR: FMC program alignment error interrupt flag
|
||||
\arg FMC_INT_FLAG_WPERR: FMC erase/program protection error interrupt flag
|
||||
\arg FMC_INT_FLAG_END: FMC end of operation interrupt flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus fmc_interrupt_flag_get(uint32_t flag)
|
||||
{
|
||||
FlagStatus status = RESET;
|
||||
|
||||
if(FMC_STAT & flag){
|
||||
status = SET;
|
||||
}
|
||||
/* return the state of corresponding FMC flag */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear FMC interrupt flag
|
||||
\param[in] flag: FMC interrupt flag
|
||||
one or more parameters can be selected which is shown as below:
|
||||
\arg FMC_INT_FLAG_PGERR: FMC operation error interrupt flag
|
||||
\arg FMC_INT_FLAG_PGAERR: FMC program alignment error interrupt flag
|
||||
\arg FMC_INT_FLAG_WPERR: FMC erase/program protection error interrupt flag
|
||||
\arg FMC_INT_FLAG_END: FMC end of operation interrupt flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_interrupt_flag_clear(uint32_t flag)
|
||||
{
|
||||
/* clear the flag */
|
||||
FMC_STAT = flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the FMC state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval state of FMC, refer to fmc_state_enum
|
||||
*/
|
||||
static fmc_state_enum fmc_state_get(void)
|
||||
{
|
||||
fmc_state_enum fmc_state = FMC_READY;
|
||||
|
||||
if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_BUSY)){
|
||||
fmc_state = FMC_BUSY;
|
||||
}else{
|
||||
if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_WPERR)){
|
||||
fmc_state = FMC_WPERR;
|
||||
}else{
|
||||
if((uint32_t)0x00U != (FMC_STAT & (FMC_STAT_PGERR))){
|
||||
fmc_state = FMC_PGERR;
|
||||
}else{
|
||||
if((uint32_t)0x00U != (FMC_STAT & (FMC_STAT_PGAERR))){
|
||||
fmc_state = FMC_PGAERR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check whether FMC is ready or not
|
||||
\param[in] timeout: timeout count
|
||||
\param[out] none
|
||||
\retval state of FMC, refer to fmc_state_enum
|
||||
*/
|
||||
static fmc_state_enum fmc_ready_wait(uint32_t timeout)
|
||||
{
|
||||
fmc_state_enum fmc_state = FMC_BUSY;
|
||||
|
||||
/* wait for FMC ready */
|
||||
do{
|
||||
/* get FMC state */
|
||||
fmc_state = fmc_state_get();
|
||||
timeout--;
|
||||
}while((FMC_BUSY == fmc_state) && (0x00U != timeout));
|
||||
|
||||
if(FMC_BUSY == fmc_state){
|
||||
fmc_state = FMC_TOERR;
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
@@ -0,0 +1,875 @@
|
||||
/*!
|
||||
\file gd32e50x_fmc.c
|
||||
\brief FMC driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_fmc.h"
|
||||
|
||||
/* FMC mask */
|
||||
#define LOW_8BITS_MASK ((uint32_t)0x000000FFU)
|
||||
#define HIGH_8BITS_MASK ((uint32_t)0x0000FF00U)
|
||||
#define LOW_8BITS_MASK1 ((uint32_t)0x00FF0000U)
|
||||
#define HIGH_8BITS_MASK1 ((uint32_t)0xFF000000U)
|
||||
#define LOW_16BITS_MASK ((uint32_t)0x0000FFFFU)
|
||||
#define HIGH_16BITS_MASK ((uint32_t)0xFFFF0000U)
|
||||
|
||||
/* USER of option bytes mask */
|
||||
#define OB_USER_MASK ((uint8_t)0x38U)
|
||||
|
||||
/* default offset */
|
||||
#define FMC_OBSTAT_USER_OFFSET 2U
|
||||
#define FMC_OBSTAT_DATA_OFFSET 10U
|
||||
|
||||
/* return the FMC state */
|
||||
static fmc_state_enum fmc_state_get(void);
|
||||
/* check FMC ready or not */
|
||||
static fmc_state_enum fmc_ready_wait(uint32_t timeout);
|
||||
|
||||
/*!
|
||||
\brief unlock the main FMC operation
|
||||
it is better to used in pairs with fmc_lock
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_unlock(void)
|
||||
{
|
||||
if(RESET != (FMC_CTL & FMC_CTL_LK)){
|
||||
/* write the FMC unlock key */
|
||||
FMC_KEY = UNLOCK_KEY0;
|
||||
FMC_KEY = UNLOCK_KEY1;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief lock the main FMC operation
|
||||
it is better to used in pairs with fmc_unlock after an operation
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_lock(void)
|
||||
{
|
||||
/* set the LK bit */
|
||||
FMC_CTL |= FMC_CTL_LK;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set the wait state
|
||||
\param[in] wscnt: wait state
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_WAIT_STATE_0: 0 wait state added
|
||||
\arg FMC_WAIT_STATE_1: 1 wait state added
|
||||
\arg FMC_WAIT_STATE_2: 2 wait state added
|
||||
\arg FMC_WAIT_STATE_3: 3 wait state added
|
||||
\arg FMC_WAIT_STATE_4: 4 wait state added
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_wscnt_set(uint32_t wscnt)
|
||||
{
|
||||
uint32_t ws;
|
||||
|
||||
ws = FMC_WS;
|
||||
|
||||
/* set the wait state counter value */
|
||||
ws &= ~FMC_WS_WSCNT;
|
||||
FMC_WS = (ws | wscnt);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable pre-fetch
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_prefetch_enable(void)
|
||||
{
|
||||
FMC_WS |= FMC_WS_PFEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable pre-fetch
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_prefetch_disable(void)
|
||||
{
|
||||
FMC_WS &= ~FMC_WS_PFEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable IBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_ibus_enable(void)
|
||||
{
|
||||
FMC_WS |= FMC_WS_ICEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable IBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_ibus_disable(void)
|
||||
{
|
||||
FMC_WS &= ~FMC_WS_ICEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset IBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_ibus_reset(void)
|
||||
{
|
||||
FMC_WS |= FMC_WS_ICRST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_dbus_enable(void)
|
||||
{
|
||||
FMC_WS |= FMC_WS_DCEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_dbus_disable(void)
|
||||
{
|
||||
FMC_WS &= ~FMC_WS_DCEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset DBUS cache
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_dbus_reset(void)
|
||||
{
|
||||
FMC_WS |= FMC_WS_DCRST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief FMC erase page
|
||||
\param[in] page_address: target page address
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
*/
|
||||
fmc_state_enum fmc_page_erase(uint32_t page_address)
|
||||
{
|
||||
fmc_state_enum fmc_state;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start page erase */
|
||||
FMC_CTL |= FMC_CTL_PER;
|
||||
FMC_ADDR = page_address;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
/* reset the PER bit */
|
||||
FMC_CTL &= ~FMC_CTL_PER;
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief FMC erase whole chip
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
*/
|
||||
fmc_state_enum fmc_mass_erase(void)
|
||||
{
|
||||
fmc_state_enum fmc_state;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start chip erase */
|
||||
FMC_CTL |= FMC_CTL_MER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
/* reset the MER bit */
|
||||
FMC_CTL &= ~FMC_CTL_MER;
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief FMC program a word at the corresponding address
|
||||
\param[in] address: address to program
|
||||
\param[in] data: word to program
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
*/
|
||||
fmc_state_enum fmc_word_program(uint32_t address, uint32_t data)
|
||||
{
|
||||
fmc_state_enum fmc_state;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* set the PG bit to start program */
|
||||
FMC_CTL |= FMC_CTL_PG;
|
||||
REG32(address) = data;
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
/* reset the PG bit */
|
||||
FMC_CTL &= ~FMC_CTL_PG;
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief unlock the option bytes operation
|
||||
it is better to used in pairs with ob_lock
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ob_unlock(void)
|
||||
{
|
||||
if(RESET == (FMC_CTL & FMC_CTL_OBWEN)){
|
||||
/* write the FMC ob unlock key */
|
||||
FMC_OBKEY = UNLOCK_KEY0;
|
||||
FMC_OBKEY = UNLOCK_KEY1;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief lock the option bytes operation
|
||||
it is better to used in pairs with ob_unlock after an operation
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ob_lock(void)
|
||||
{
|
||||
/* reset the OBWEN bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBWEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief erase the option bytes
|
||||
programmer must ensure FMC & option bytes are both unlocked before calling this function
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
\arg FMC_OB_HSPC: high security protection
|
||||
*/
|
||||
fmc_state_enum ob_erase(void)
|
||||
{
|
||||
uint32_t temp_spc;
|
||||
fmc_state_enum fmc_state;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
temp_spc = OB_SPC_USER;
|
||||
|
||||
/* check the option bytes security protection value */
|
||||
if((RESET != ob_security_protection_flag_get()) && (FMC_HSPC == (temp_spc & LOW_8BITS_MASK))){
|
||||
fmc_state = FMC_OB_HSPC;
|
||||
}
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start erase the option bytes */
|
||||
FMC_CTL |= FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* reset the OBER bit and enable the option bytes programming */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
/* set the OBPG bit */
|
||||
FMC_CTL |= FMC_CTL_OBPG;
|
||||
/* restore the last get option bytes security protection code */
|
||||
OB_SPC_USER = (temp_spc & LOW_8BITS_MASK) | LOW_8BITS_MASK1;
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
/* reset the OBPG bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBPG;
|
||||
}else{
|
||||
/* reset the OBER bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
}
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable write protection
|
||||
programmer must ensure FMC & option bytes are both unlocked before calling this function
|
||||
\param[in] ob_wp: specify sector to be write protected
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg OB_WP_NONE: disable all write protection
|
||||
\arg OB_WP_x(x=0..31): write protect specify sector
|
||||
\arg OB_WP_ALL: write protect all sector
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
\arg FMC_OB_HSPC: high security protection
|
||||
*/
|
||||
fmc_state_enum ob_write_protection_enable(uint32_t ob_wp)
|
||||
{
|
||||
uint32_t temp_spc;
|
||||
uint8_t i;
|
||||
uint32_t op_byte[4];
|
||||
|
||||
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
temp_spc = OB_SPC_USER;
|
||||
|
||||
/* check the option bytes security protection value */
|
||||
if((RESET != ob_security_protection_flag_get()) && (FMC_HSPC == (temp_spc & LOW_8BITS_MASK))){
|
||||
fmc_state = FMC_OB_HSPC;
|
||||
}
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
op_byte[i] = OP_BYTE(i);
|
||||
}
|
||||
|
||||
ob_wp = (uint32_t)(~ob_wp);
|
||||
op_byte[2] = (ob_wp & LOW_8BITS_MASK) | ((ob_wp & HIGH_8BITS_MASK) << 8);
|
||||
op_byte[3] = ((ob_wp & LOW_8BITS_MASK1) >> 16) | ((ob_wp & HIGH_8BITS_MASK1) >> 8);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start erase the option byte */
|
||||
FMC_CTL |= FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* reset the OBER bit and enable the option bytes programming */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_OBPG;
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
OP_BYTE(i) = op_byte[i];
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
if(FMC_READY != fmc_state){
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* reset the OBPG bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBPG;
|
||||
}else{
|
||||
/* reset the OBER bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure security protection
|
||||
programmer must ensure FMC & option bytes are both unlocked before calling this function
|
||||
\param[in] ob_spc: specify security protection
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_NSPC: no security protection
|
||||
\arg FMC_LSPC: low security protection
|
||||
\arg FMC_HSPC: high security protection
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
\arg FMC_OB_HSPC: high security protection
|
||||
*/
|
||||
fmc_state_enum ob_security_protection_config(uint8_t ob_spc)
|
||||
{
|
||||
uint32_t temp_spc;
|
||||
uint8_t i;
|
||||
uint32_t op_byte[4];
|
||||
|
||||
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
temp_spc = OB_SPC_USER & LOW_16BITS_MASK;
|
||||
|
||||
/* check the option bytes security protection value */
|
||||
if((RESET != ob_security_protection_flag_get()) && (FMC_HSPC == (temp_spc & LOW_8BITS_MASK))){
|
||||
fmc_state = FMC_OB_HSPC;
|
||||
}
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
op_byte[i] = OP_BYTE(i);
|
||||
}
|
||||
op_byte[0] = ((uint32_t)(ob_spc)) | ((op_byte[0] & HIGH_16BITS_MASK));
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start erase the option bytes */
|
||||
FMC_CTL |= FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* reset the OBER bit and enable the option bytes programming */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_OBPG;
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
OP_BYTE(i) = op_byte[i];
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
if(FMC_READY != fmc_state){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset the OBPG bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBPG;
|
||||
}else{
|
||||
/* reset the OBER bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief program option bytes USER
|
||||
programmer must ensure FMC & option bytes are both unlocked before calling this function
|
||||
\param[in] ob_fwdgt: option bytes free watchdog value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg OB_FWDGT_SW: software free watchdog
|
||||
\arg OB_FWDGT_HW: hardware free watchdog
|
||||
\param[in] ob_deepsleep: option bytes deepsleep reset value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode
|
||||
\arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode
|
||||
\param[in] ob_stdby:option bytes standby reset value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg OB_STDBY_NRST: no reset when entering standby mode
|
||||
\arg OB_STDBY_RST: generate a reset instead of entering standby mode
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
\arg FMC_OB_HSPC: high security protection
|
||||
*/
|
||||
fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby)
|
||||
{
|
||||
uint32_t temp_spc;
|
||||
uint8_t temp;
|
||||
uint8_t i;
|
||||
uint32_t op_byte[4];
|
||||
|
||||
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
temp_spc = OB_SPC_USER;
|
||||
|
||||
/* check the option bytes security protection value */
|
||||
if((RESET != ob_security_protection_flag_get()) && (FMC_HSPC == (temp_spc & LOW_8BITS_MASK))){
|
||||
fmc_state = FMC_OB_HSPC;
|
||||
}
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
op_byte[i] = OP_BYTE(i);
|
||||
}
|
||||
temp = ((uint8_t)((uint8_t)(((uint8_t)(ob_fwdgt) | ob_deepsleep) | ob_stdby)) | (OB_USER_MASK));
|
||||
op_byte[0] = ((uint32_t)(temp) << 16U) | ((op_byte[0] & LOW_16BITS_MASK));
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start erase the option bytes */
|
||||
FMC_CTL |= FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
if(FMC_READY == fmc_state){
|
||||
/* reset the OBER bit and enable the option bytes programming */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_OBPG;
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
OP_BYTE(i) = op_byte[i];
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
if(FMC_READY != fmc_state){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset the OBPG bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBPG;
|
||||
}else{
|
||||
/* reset the OBER bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
}
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief program option bytes DATA
|
||||
\param[in] data: the byte to be programmed
|
||||
\param[out] none
|
||||
\retval state of FMC
|
||||
\arg FMC_READY: the operation has been completed
|
||||
\arg FMC_PGERR: program error
|
||||
\arg FMC_PGAERR: program alignment error
|
||||
\arg FMC_WPERR: erase/program protection error
|
||||
\arg FMC_TOERR: timeout error
|
||||
\arg FMC_OB_HSPC: high security protection
|
||||
*/
|
||||
fmc_state_enum ob_data_program(uint16_t ob_data)
|
||||
{
|
||||
uint32_t temp_spc;
|
||||
uint8_t i;
|
||||
uint32_t op_byte[4];
|
||||
|
||||
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
temp_spc = OB_SPC_USER;
|
||||
|
||||
/* check the option bytes security protection value */
|
||||
if((RESET != ob_security_protection_flag_get()) && (FMC_HSPC == (temp_spc & LOW_8BITS_MASK))){
|
||||
fmc_state = FMC_OB_HSPC;
|
||||
}
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
op_byte[i] = OP_BYTE(i);
|
||||
}
|
||||
op_byte[1] = (uint32_t)((ob_data & LOW_8BITS_MASK) | ((ob_data & HIGH_8BITS_MASK) << 8));
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* start erase the option bytes */
|
||||
FMC_CTL |= FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_START;
|
||||
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
|
||||
if(FMC_READY == fmc_state){
|
||||
/* reset the OBER bit and enable the option bytes programming */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
FMC_CTL |= FMC_CTL_OBPG;
|
||||
|
||||
for(i = 0U; i < 4U; i++){
|
||||
OP_BYTE(i) = op_byte[i];
|
||||
/* wait for the FMC ready */
|
||||
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
||||
if(FMC_READY != fmc_state){
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* reset the OBPG bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBPG;
|
||||
}else{
|
||||
/* reset the OBER bit */
|
||||
FMC_CTL &= ~FMC_CTL_OBER;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the value of option bytes USER
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the option bytes USER value
|
||||
*/
|
||||
uint8_t ob_user_get(void)
|
||||
{
|
||||
/* return the FMC user option bytes value */
|
||||
return (uint8_t)(FMC_OBSTAT >> FMC_OBSTAT_USER_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the value of option bytes DATA
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the option bytes DATA value
|
||||
*/
|
||||
uint16_t ob_data_get(void)
|
||||
{
|
||||
return (uint16_t)(FMC_OBSTAT >> FMC_OBSTAT_DATA_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the value of option bytes write protection
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the write protection option bytes value
|
||||
*/
|
||||
uint32_t ob_write_protection_get(void)
|
||||
{
|
||||
/* return the FMC write protection option bytes value */
|
||||
return FMC_WP;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the FMC option bytes security protection state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus ob_security_protection_flag_get(void)
|
||||
{
|
||||
FlagStatus spc_state = RESET;
|
||||
|
||||
if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){
|
||||
spc_state = SET;
|
||||
}else{
|
||||
spc_state = RESET;
|
||||
}
|
||||
return spc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get FMC flag status
|
||||
\param[in] flag: FMC flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_FLAG_BUSY: FMC busy flag
|
||||
\arg FMC_FLAG_PGERR: FMC program error flag
|
||||
\arg FMC_FLAG_PGAERR: FMC program alignment error flag
|
||||
\arg FMC_FLAG_WPERR: FMC erase/program protection error flag
|
||||
\arg FMC_FLAG_END: FMC end of operation flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus fmc_flag_get(uint32_t flag)
|
||||
{
|
||||
FlagStatus status = RESET;
|
||||
|
||||
if(FMC_STAT & flag){
|
||||
status = SET;
|
||||
}
|
||||
/* return the state of corresponding FMC flag */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear the FMC flag
|
||||
\param[in] flag: FMC flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_FLAG_PGERR: FMC program error flag
|
||||
\arg FMC_FLAG_PGAERR: FMC program alignment error flag
|
||||
\arg FMC_FLAG_WPERR: FMC erase/program protection error flag
|
||||
\arg FMC_FLAG_END: FMC end of operation flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_flag_clear(uint32_t flag)
|
||||
{
|
||||
/* clear the flags */
|
||||
FMC_STAT = flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable FMC interrupt
|
||||
\param[in] interrupt: the FMC interrupt
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_INT_END: FMC end of operation interrupt
|
||||
\arg FMC_INT_ERR: FMC error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_interrupt_enable(uint32_t interrupt)
|
||||
{
|
||||
FMC_CTL |= interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable FMC interrupt
|
||||
\param[in] interrupt: the FMC interrupt
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_INT_END: FMC end of operation interrupt
|
||||
\arg FMC_INT_ERR: FMC error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_interrupt_disable(uint32_t interrupt)
|
||||
{
|
||||
FMC_CTL &= ~(uint32_t)interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get FMC interrupt flag
|
||||
\param[in] flag: FMC interrupt flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FMC_INT_FLAG_PGERR: FMC operation error interrupt flag
|
||||
\arg FMC_INT_FLAG_PGAERR: FMC program alignment error interrupt flag
|
||||
\arg FMC_INT_FLAG_WPERR: FMC erase/program protection error interrupt flag
|
||||
\arg FMC_INT_FLAG_END: FMC end of operation interrupt flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus fmc_interrupt_flag_get(uint32_t flag)
|
||||
{
|
||||
FlagStatus status = RESET;
|
||||
|
||||
if(FMC_STAT & flag){
|
||||
status = SET;
|
||||
}
|
||||
/* return the state of corresponding FMC flag */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear FMC interrupt flag
|
||||
\param[in] flag: FMC interrupt flag
|
||||
one or more parameters can be selected which is shown as below:
|
||||
\arg FMC_INT_FLAG_PGERR: FMC operation error interrupt flag
|
||||
\arg FMC_INT_FLAG_PGAERR: FMC program alignment error interrupt flag
|
||||
\arg FMC_INT_FLAG_WPERR: FMC erase/program protection error interrupt flag
|
||||
\arg FMC_INT_FLAG_END: FMC end of operation interrupt flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fmc_interrupt_flag_clear(uint32_t flag)
|
||||
{
|
||||
/* clear the flag */
|
||||
FMC_STAT = flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the FMC state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval state of FMC, refer to fmc_state_enum
|
||||
*/
|
||||
static fmc_state_enum fmc_state_get(void)
|
||||
{
|
||||
fmc_state_enum fmc_state = FMC_READY;
|
||||
|
||||
if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_BUSY)){
|
||||
fmc_state = FMC_BUSY;
|
||||
}else{
|
||||
if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_WPERR)){
|
||||
fmc_state = FMC_WPERR;
|
||||
}else{
|
||||
if((uint32_t)0x00U != (FMC_STAT & (FMC_STAT_PGERR))){
|
||||
fmc_state = FMC_PGERR;
|
||||
}else{
|
||||
if((uint32_t)0x00U != (FMC_STAT & (FMC_STAT_PGAERR))){
|
||||
fmc_state = FMC_PGAERR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check whether FMC is ready or not
|
||||
\param[in] timeout: timeout count
|
||||
\param[out] none
|
||||
\retval state of FMC, refer to fmc_state_enum
|
||||
*/
|
||||
static fmc_state_enum fmc_ready_wait(uint32_t timeout)
|
||||
{
|
||||
fmc_state_enum fmc_state = FMC_BUSY;
|
||||
|
||||
/* wait for FMC ready */
|
||||
do{
|
||||
/* get FMC state */
|
||||
fmc_state = fmc_state_get();
|
||||
timeout--;
|
||||
}while((FMC_BUSY == fmc_state) && (0x00U != timeout));
|
||||
|
||||
if(FMC_BUSY == fmc_state){
|
||||
fmc_state = FMC_TOERR;
|
||||
}
|
||||
/* return the FMC state */
|
||||
return fmc_state;
|
||||
}
|
||||
@@ -0,0 +1,699 @@
|
||||
/*!
|
||||
\file gd32e50x_gpio.c
|
||||
\brief GPIO driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_gpio.h"
|
||||
|
||||
#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/
|
||||
#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */
|
||||
#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */
|
||||
#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */
|
||||
#define PCF_SWJCFG_MASK ((uint32_t)0xF8FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */
|
||||
#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */
|
||||
#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */
|
||||
#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */
|
||||
#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/
|
||||
|
||||
/*!
|
||||
\brief reset GPIO port
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset alternate function I/O(AFIO)
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_afio_deinit(void)
|
||||
{
|
||||
rcu_periph_reset_enable(RCU_AFRST);
|
||||
rcu_periph_reset_disable(RCU_AFRST);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief GPIO parameter initialization
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\param[in] mode: gpio pin mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg GPIO_MODE_AIN: analog input mode
|
||||
\arg GPIO_MODE_IN_FLOATING: floating input mode
|
||||
\arg GPIO_MODE_IPD: pull-down input mode
|
||||
\arg GPIO_MODE_IPU: pull-up input mode
|
||||
\arg GPIO_MODE_OUT_OD: GPIO output with open-drain
|
||||
\arg GPIO_MODE_OUT_PP: GPIO output with push-pull
|
||||
\arg GPIO_MODE_AF_OD: AFIO output with open-drain
|
||||
\arg GPIO_MODE_AF_PP: AFIO output with push-pull
|
||||
\param[in] speed: gpio output max speed value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg GPIO_OSPEED_10MHZ: output max speed 10MHz
|
||||
\arg GPIO_OSPEED_2MHZ: output max speed 2MHz
|
||||
\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_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin)
|
||||
{
|
||||
uint16_t i;
|
||||
uint32_t temp_mode = 0U;
|
||||
uint32_t reg = 0U;
|
||||
|
||||
/* GPIO mode configuration */
|
||||
temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU));
|
||||
|
||||
/* GPIO speed configuration */
|
||||
if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){
|
||||
/* output mode max speed */
|
||||
if(GPIO_OSPEED_MAX == (uint32_t)speed){
|
||||
temp_mode |= (uint32_t)0x03U;
|
||||
/* set the corresponding SPD bit */
|
||||
GPIOx_SPD(gpio_periph) |= (uint32_t)pin ;
|
||||
}else{
|
||||
/* output mode max speed:10MHz,2MHz,50MHz */
|
||||
temp_mode |= (uint32_t)speed;
|
||||
}
|
||||
}
|
||||
|
||||
/* configure the eight low port pins with GPIO_CTL0 */
|
||||
for(i = 0U;i < 8U;i++){
|
||||
if((1U << i) & pin){
|
||||
reg = GPIO_CTL0(gpio_periph);
|
||||
|
||||
/* clear the specified pin mode bits */
|
||||
reg &= ~GPIO_MODE_MASK(i);
|
||||
/* set the specified pin mode bits */
|
||||
reg |= GPIO_MODE_SET(i, temp_mode);
|
||||
|
||||
/* set IPD or IPU */
|
||||
if(GPIO_MODE_IPD == mode){
|
||||
/* reset the corresponding OCTL bit */
|
||||
GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}else{
|
||||
/* set the corresponding OCTL bit */
|
||||
if(GPIO_MODE_IPU == mode){
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}
|
||||
}
|
||||
/* set GPIO_CTL0 register */
|
||||
GPIO_CTL0(gpio_periph) = reg;
|
||||
}
|
||||
}
|
||||
/* configure the eight high port pins with GPIO_CTL1 */
|
||||
for(i = 8U;i < 16U;i++){
|
||||
if((1U << i) & pin){
|
||||
reg = GPIO_CTL1(gpio_periph);
|
||||
|
||||
/* clear the specified pin mode bits */
|
||||
reg &= ~GPIO_MODE_MASK(i - 8U);
|
||||
/* set the specified pin mode bits */
|
||||
reg |= GPIO_MODE_SET(i - 8U, temp_mode);
|
||||
|
||||
/* set IPD or IPU */
|
||||
if(GPIO_MODE_IPD == mode){
|
||||
/* reset the corresponding OCTL bit */
|
||||
GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}else{
|
||||
/* set the corresponding OCTL bit */
|
||||
if(GPIO_MODE_IPU == mode){
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}
|
||||
}
|
||||
/* set GPIO_CTL1 register */
|
||||
GPIO_CTL1(gpio_periph) = reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set GPIO pin bit
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\param[in] data: specify the value to be written to the port output data 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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\param[in] pin: GPIO pin
|
||||
only one parameter 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 port input status
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\param[in] pin: GPIO pin
|
||||
only one parameter 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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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 configure GPIO pin remap
|
||||
\param[in] gpio_remap: select the pin to remap
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_SPI0_REMAP: SPI0 remapping
|
||||
\arg GPIO_I2C0_REMAP: I2C0 remapping
|
||||
\arg GPIO_USART0_REMAP: USART0 remapping
|
||||
\arg GPIO_USART1_REMAP: USART1 remapping
|
||||
\arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping
|
||||
\arg GPIO_USART2_FULL_REMAP: USART2 full remapping
|
||||
\arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping
|
||||
\arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping
|
||||
\arg GPIO_TIMER1_PARTIAL_REMAP0: TIMER1 partial remapping
|
||||
\arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping
|
||||
\arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping
|
||||
\arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping
|
||||
\arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping
|
||||
\arg GPIO_TIMER3_REMAP: TIMER3 remapping
|
||||
\arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_PD01_REMAP: PD01 remapping
|
||||
\arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping
|
||||
\arg GPIO_ADC0_ETRGRT_REMAP: ADC0 external trigger routine conversion remapping(only for GD32E50X_HD devices)
|
||||
\arg GPIO_ADC1_ETRGRT_REMAP: ADC1 external trigger routine conversion remapping(only for GD32E50X_HD devices)
|
||||
\arg GPIO_ENET_REMAP: ENET remapping(only for GD32E50X_CL and GD32E508 devices)
|
||||
\arg GPIO_CAN1_REMAP: CAN1 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST
|
||||
\arg GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled
|
||||
\arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled
|
||||
\arg GPIO_SPI2_REMAP: SPI2 remapping
|
||||
\arg GPIO_TIMER1ITR1_REMAP: TIMER1 internal trigger 1 remapping(only for GD32E50X_CL and GD32E508 devices)
|
||||
\arg GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping(only for GD32E50X_CL and GD32E508 devices)
|
||||
\arg GPIO_TIMER8_REMAP: TIMER8 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_TIMER9_REMAP: TIMER9 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_TIMER10_REMAP: TIMER10 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_TIMER12_REMAP: TIMER12 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_TIMER13_REMAP: TIMER13 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect
|
||||
\arg GPIO_CTC_REMAP0: CTC remapping(PD15)
|
||||
\arg GPIO_CTC_REMAP1: CTC remapping(PF0)
|
||||
\param[in] newvalue: ENABLE or DISABLE
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue)
|
||||
{
|
||||
uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U;
|
||||
|
||||
if(((uint32_t)0x80000000U) == (remap & 0x80000000U)){
|
||||
/* get AFIO_PCF1 regiter value */
|
||||
temp_reg = AFIO_PCF1;
|
||||
}else{
|
||||
/* get AFIO_PCF0 regiter value */
|
||||
temp_reg = AFIO_PCF0;
|
||||
}
|
||||
|
||||
temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U;
|
||||
remap1 = remap & LSB_16BIT_MASK;
|
||||
|
||||
/* judge pin remap type */
|
||||
if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){
|
||||
temp_reg &= PCF_SWJCFG_MASK;
|
||||
AFIO_PCF0 &= PCF_SWJCFG_MASK;
|
||||
}else if(PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)){
|
||||
remap2 = ((uint32_t)0x03U) << temp_mask;
|
||||
temp_reg &= ~remap2;
|
||||
temp_reg |= ~PCF_SWJCFG_MASK;
|
||||
}else{
|
||||
temp_reg &= ~(remap1 << ((remap >> 0x15U)*0x10U));
|
||||
temp_reg |= ~PCF_SWJCFG_MASK;
|
||||
}
|
||||
|
||||
/* set pin remap value */
|
||||
if(DISABLE != newvalue){
|
||||
temp_reg |= (remap1 << ((remap >> 0x15U)*0x10U));
|
||||
}
|
||||
|
||||
if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){
|
||||
/* set AFIO_PCF1 regiter value */
|
||||
AFIO_PCF1 = temp_reg;
|
||||
}else{
|
||||
/* set AFIO_PCF0 regiter value */
|
||||
AFIO_PCF0 = temp_reg;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure AFIO port alternate function
|
||||
\param[in] afio_function: select the port AFIO function(SHRTIMER not support on GD32EPRT devices)
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg AFIO_PA2_CMP1_CFG: configure PA2 alternate function to CMP1
|
||||
\arg AFIO_PA3_USBHS_CFG: configure PA3 alternate function to USBHS
|
||||
\arg AFIO_PA5_USBHS_CFG: configure PA5 alternate function to USBHS
|
||||
\arg AFIO_PA8_I2C2_CFG: configure PA8 alternate function to I2C2
|
||||
\arg AFIO_PA8_SHRTIMER_CFG: configure PA8 alternate function to SHRTIMER
|
||||
\arg AFIO_PA9_CAN2_CFG: configure PA9 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PA9_I2C2_CFG: configure PA9 alternate function to I2C2
|
||||
\arg AFIO_PA9_SHRTIMER_CFG: configure PA9 alternate function to SHRTIMER
|
||||
\arg AFIO_PA10_CAN2_CFG: configure PA10 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PA10_CMP5_CFG: configure PA10 alternate function to CMP5
|
||||
\arg AFIO_PA10_SHRTIMER_CFG: configure PA10 alternate function to SHRTIMER
|
||||
\arg AFIO_PA11_USART5_CFG: configure PA11 alternate function to USART5
|
||||
\arg AFIO_PA11_SHRTIMER_CFG: configure PA11 alternate function to SHRTIMER
|
||||
\arg AFIO_PA12_CMP1_CFG: configure PA12 alternate function to CMP1
|
||||
\arg AFIO_PA12_USART5_CFG: configure PA12 alternate function to USART5
|
||||
\arg AFIO_PA12_SHRTIMER_CFG: configure PA12 alternate function to SHRTIMER
|
||||
\arg AFIO_PA15_SHRTIMER_CFG: configure PA15 alternate function to SHRTIMER
|
||||
\arg AFIO_PB0_USBHS_CFG: configure PB0 alternate function to USBHS
|
||||
\arg AFIO_PB1_CMP3_CFG: configure PB1 alternate function to CMP3
|
||||
\arg AFIO_PB1_USBHS_CFG: configure PB1 alternate function to USBHS
|
||||
\arg AFIO_PB1_SHRTIMER_CFG: configure PB1 alternate function to SHRTIMER
|
||||
\arg AFIO_PB2_USBHS_CFG: configure PB2 alternate function to USBHS
|
||||
\arg AFIO_PB2_SHRTIMER_CFG: configure PB2 alternate function to SHRTIMER
|
||||
\arg AFIO_PB3_SHRTIMER_CFG: configure PB3 alternate function to SHRTIMER
|
||||
\arg AFIO_PB4_I2S2_CFG: configure PB4 alternate function to I2S2
|
||||
\arg AFIO_PB4_I2C2_CFG: configure PB4 alternate function to I2C2
|
||||
\arg AFIO_PB4_SHRTIMER_CFG: configure PB4 alternate function to SHRTIMER
|
||||
\arg AFIO_PB5_I2C2_CFG: configure PB5 alternate function to I2C2
|
||||
\arg AFIO_PB5_USBHS_CFG: configure PB5 alternate function to USBHS
|
||||
\arg AFIO_PB5_SHRTIMER_CFG: configure PB5 alternate function to SHRTIMER
|
||||
\arg AFIO_PB6_SHRTIMER_CFG: configure PB6 alternate function to SHRTIMER
|
||||
\arg AFIO_PB7_SHRTIMER_CFG: configure PB7 alternate function to SHRTIMER
|
||||
\arg AFIO_PB8_I2C2_CFG: configure PB8 alternate function to I2C2
|
||||
\arg AFIO_PB8_SHRTIMER_CFG: configure PB8 alternate function to SHRTIMER
|
||||
\arg AFIO_PB9_CMP1_CFG: configure PB9 alternate function to CMP1
|
||||
\arg AFIO_PB9_SHRTIMER_CFG: configure PB9 alternate function to SHRTIMER
|
||||
\arg AFIO_PB10_CAN2_CFG: configure PB10 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PB10_USBHS_CFG: configure PB10 alternate function to USBHS
|
||||
\arg AFIO_PB10_SHRTIMER_CFG: configure PB10 alternate function to SHRTIMER
|
||||
\arg AFIO_PB11_CAN2_CFG: configure PB11 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PB11_USBHS_CFG: configure PB11 alternate function to USBHS
|
||||
\arg AFIO_PB11_SHRTIMER_CFG: configure PB11 alternate function to SHRTIMER
|
||||
\arg AFIO_PB12_USBHS_CFG: configure PB12 alternate function to USBHS
|
||||
\arg AFIO_PB12_SHRTIMER_CFG: configure PB12 alternate function to SHRTIMER
|
||||
\arg AFIO_PB13_USBHS_CFG: configure PB13 alternate function to USBHS
|
||||
\arg AFIO_PB13_SHRTIMER_CFG: configure PB13 alternate function to SHRTIMER
|
||||
\arg AFIO_PB14_I2S1_CFG: configure PB14 alternate function to I2S1
|
||||
\arg AFIO_PB14_SHRTIMER_CFG: configure PB14 alternate function to SHRTIMER
|
||||
\arg AFIO_PB15_SHRTIMER_CFG: configure PB15 alternate function to SHRTIMER
|
||||
\arg AFIO_PC0_USBHS_CFG: configure PC0 alternate function to USBHS
|
||||
\arg AFIO_PC2_I2S1_CFG: configure PC2 alternate function to I2S1
|
||||
\arg AFIO_PC2_USBHS_CFG: configure PC2 alternate function to USBHS
|
||||
\arg AFIO_PC3_USBHS_CFG: configure PC3 alternate function to USBHS
|
||||
\arg AFIO_PC6_CMP5_CFG: configure PC6 alternate function to CMP5
|
||||
\arg AFIO_PC6_USART5_CFG: configure PC6 alternate function to USART5
|
||||
\arg AFIO_PC6_SHRTIMER_CFG: configure PC6 alternate function to SHRTIMER
|
||||
\arg AFIO_PC7_USART5_CFG: configure PC7 alternate function to USART5
|
||||
\arg AFIO_PC7_SHRTIMER_CFG: configure PC7 alternate function to SHRTIMER
|
||||
\arg AFIO_PC8_USART5_CFG: configure PC8 alternate function to USART5
|
||||
\arg AFIO_PC8_SHRTIMER_CFG: configure PC8 alternate function to SHRTIMER
|
||||
\arg AFIO_PC9_I2C2_CFG: configure PC9 alternate function to I2C2
|
||||
\arg AFIO_PC9_SHRTIMER_CFG: configure PC9 alternate function to SHRTIMER
|
||||
\arg AFIO_PC10_I2C2_CFG: configure PC10 alternate function to I2C2
|
||||
\arg AFIO_PC11_I2S2_CFG: configure PC11 alternate function to I2S2
|
||||
\arg AFIO_PC11_SHRTIMER_CFG: configure PC11 alternate function to SHRTIMER
|
||||
\arg AFIO_PC12_SHRTIMER_CFG: configure PC12 alternate function to SHRTIMER
|
||||
\arg AFIO_PD4_SHRTIMER_CFG: configure PD4 alternate function to SHRTIMER
|
||||
\arg AFIO_PD5_SHRTIMER_CFG: configure PD5 alternate function to SHRTIMER
|
||||
\arg AFIO_PE0_CAN2_CFG: configure PE0 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PE0_SHRTIMER_CFG: configure PE0 alternate function to SHRTIMER
|
||||
\arg AFIO_PE1_CAN2_CFG: configure PE1 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PE1_SHRTIMER_CFG: configure PE1 alternate function to SHRTIMER
|
||||
\arg AFIO_PE8_CMP1_CFG: configure PE8 alternate function to CMP1
|
||||
\arg AFIO_PE9_CMP3_CFG: configure PE9 alternate function to CMP3
|
||||
\arg AFIO_PE10_CMP5_CFG: configure PE10 alternate function to CMP5
|
||||
\arg AFIO_PE11_CMP5_CFG: configure PE11 alternate function to CMP5
|
||||
\arg AFIO_PE12_CMP3_CFG: configure PE12 alternate function to CMP3
|
||||
\arg AFIO_PE13_CMP1_CFG: configure PE13 alternate function to CMP1
|
||||
\arg AFIO_PG6_SHRTIMER_CFG: configure PG6 alternate function to SHRTIMER
|
||||
\arg AFIO_PG7_USART5_CFG: configure PG7 alternate function to USART5
|
||||
\arg AFIO_PG7_SHRTIMER_CFG: configure PG7 alternate function to SHRTIMER
|
||||
\arg AFIO_PG9_USART5_CFG: configure PG9 alternate function to USART5
|
||||
\arg AFIO_PG10_SHRTIMER_CFG: configure PG10 alternate function to SHRTIMER
|
||||
\arg AFIO_PG11_SHRTIMER_CFG: configure PG11 alternate function to SHRTIMER
|
||||
\arg AFIO_PG12_SHRTIMER_CFG: configure PG12 alternate function to SHRTIMER
|
||||
\arg AFIO_PG13_SHRTIMER_CFG: configure PG13 alternate function to SHRTIMER
|
||||
\arg AFIO_PG14_USART5_CFG: configure PG14 alternate function to USART5
|
||||
\param[in] newvalue: ENABLE or DISABLE
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_afio_port_config(uint32_t afio_function, ControlStatus newvalue)
|
||||
{
|
||||
uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U;
|
||||
|
||||
/* get AFIO_PCFx(x=A,B,C,D,E,G) regiter value */
|
||||
temp_reg = REG32(AFIO+0x0000003CU+((afio_function>>24)<<2));
|
||||
|
||||
temp_mask = (afio_function & PCF_POSITION_MASK) >> 0x10U;
|
||||
remap1 = afio_function & LSB_16BIT_MASK;
|
||||
|
||||
/* judge port function select type */
|
||||
if(afio_function & PCF_LOCATION2_MASK){
|
||||
remap2 = ((uint32_t)0x03U) << temp_mask;
|
||||
remap2 = (remap2 << (((afio_function & PCF_LOCATION1_MASK) >> 0x15U)*0x10U));
|
||||
temp_reg &= ~remap2;
|
||||
}else{
|
||||
temp_reg &= ~(remap1 << (((afio_function & PCF_LOCATION1_MASK) >> 0x15U)*0x10U));
|
||||
}
|
||||
|
||||
/* set pin remap value */
|
||||
if(DISABLE != newvalue){
|
||||
temp_reg |= (remap1 << (((afio_function & PCF_LOCATION1_MASK) >> 0x15U)*0x10U));
|
||||
}
|
||||
|
||||
/* set AFIO_PCFx(x=A,B,C,D,E,G) regiter value */
|
||||
REG32(AFIO+0x0000003CU+((afio_function>>24)<<2)) = temp_reg;
|
||||
}
|
||||
|
||||
#if (defined(GD32E50X_CL) || defined(GD32E508) || defined(GD32EPRT))
|
||||
/*!
|
||||
\brief select ethernet MII or RMII PHY
|
||||
\param[in] enet_sel: ethernet MII or RMII PHY selection
|
||||
\arg GPIO_ENET_PHY_MII: configure ethernet MAC for connection with an MII PHY
|
||||
\arg GPIO_ENET_PHY_RMII: configure ethernet MAC for connection with an RMII PHY
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_ethernet_phy_select(uint32_t enet_sel)
|
||||
{
|
||||
/* clear AFIO_PCF0_ENET_PHY_SEL bit */
|
||||
AFIO_PCF0 &= (uint32_t)(~AFIO_PCF0_ENET_PHY_SEL);
|
||||
|
||||
/* select MII or RMII PHY */
|
||||
AFIO_PCF0 |= (uint32_t)enet_sel;
|
||||
}
|
||||
#endif /* GD32E50X_CL||GD32E508||GD32EPRT */
|
||||
|
||||
/*!
|
||||
\brief select GPIO pin exti sources
|
||||
\param[in] output_port: gpio event output port
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PORT_SOURCE_GPIOA: output port source A
|
||||
\arg GPIO_PORT_SOURCE_GPIOB: output port source B
|
||||
\arg GPIO_PORT_SOURCE_GPIOC: output port source C
|
||||
\arg GPIO_PORT_SOURCE_GPIOD: output port source D
|
||||
\arg GPIO_PORT_SOURCE_GPIOE: output port source E
|
||||
\arg GPIO_PORT_SOURCE_GPIOF: output port source F
|
||||
\arg GPIO_PORT_SOURCE_GPIOG: output port source G
|
||||
\param[in] output_pin: GPIO output pin source
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PIN_SOURCE_x(x=0..15)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin)
|
||||
{
|
||||
uint32_t source = 0U;
|
||||
source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK));
|
||||
|
||||
/* select EXTI sources */
|
||||
if(GPIO_PIN_SOURCE_4 > output_pin){
|
||||
/* select EXTI0/EXTI1/EXTI2/EXTI3 */
|
||||
AFIO_EXTISS0 &= ~source;
|
||||
AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else if(GPIO_PIN_SOURCE_8 > output_pin){
|
||||
/* select EXTI4/EXTI5/EXTI6/EXTI7 */
|
||||
AFIO_EXTISS1 &= ~source;
|
||||
AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else if(GPIO_PIN_SOURCE_12 > output_pin){
|
||||
/* select EXTI8/EXTI9/EXTI10/EXTI11 */
|
||||
AFIO_EXTISS2 &= ~source;
|
||||
AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else{
|
||||
/* select EXTI12/EXTI13/EXTI14/EXTI15 */
|
||||
AFIO_EXTISS3 &= ~source;
|
||||
AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure GPIO pin event output
|
||||
\param[in] output_port: gpio event output port
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_EVENT_PORT_GPIOA: event output port A
|
||||
\arg GPIO_EVENT_PORT_GPIOB: event output port B
|
||||
\arg GPIO_EVENT_PORT_GPIOC: event output port C
|
||||
\arg GPIO_EVENT_PORT_GPIOD: event output port D
|
||||
\arg GPIO_EVENT_PORT_GPIOE: event output port E
|
||||
\param[in] output_pin: GPIO event output pin
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_EVENT_PIN_x(x=0..15)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_config(uint8_t output_port, uint8_t output_pin)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
reg = AFIO_EC;
|
||||
|
||||
/* clear AFIO_EC_PORT and AFIO_EC_PIN bits */
|
||||
reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN));
|
||||
|
||||
reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET);
|
||||
reg |= (uint32_t)output_pin;
|
||||
|
||||
AFIO_EC = reg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable GPIO pin event output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_enable(void)
|
||||
{
|
||||
AFIO_EC |= AFIO_EC_EOE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable GPIO pin event output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_disable(void)
|
||||
{
|
||||
AFIO_EC &= (uint32_t)(~AFIO_EC_EOE);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief lock GPIO pin bit
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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 configure the I/O compensation cell
|
||||
\param[in] compensation: specifies the I/O compensation cell mode
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_COMPENSATION_ENABLE: I/O compensation cell is enabled
|
||||
\arg GPIO_COMPENSATION_DISABLE: I/O compensation cell is disabled
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_compensation_config(uint32_t compensation)
|
||||
{
|
||||
uint32_t reg;
|
||||
reg = AFIO_CPSCTL;
|
||||
|
||||
/* reset the AFIO_CPSCTL_CPS_EN bit and set according to gpio_compensation */
|
||||
reg &= ~AFIO_CPSCTL_CPS_EN;
|
||||
AFIO_CPSCTL = (reg | compensation);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check the I/O compensation cell is ready or not
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus gpio_compensation_flag_get(void)
|
||||
{
|
||||
if(((uint32_t)RESET) != (AFIO_CPSCTL & AFIO_CPSCTL_CPS_RDY)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,699 @@
|
||||
/*!
|
||||
\file gd32e50x_gpio.c
|
||||
\brief GPIO driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_gpio.h"
|
||||
|
||||
#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/
|
||||
#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */
|
||||
#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */
|
||||
#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */
|
||||
#define PCF_SWJCFG_MASK ((uint32_t)0xF8FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */
|
||||
#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */
|
||||
#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */
|
||||
#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */
|
||||
#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/
|
||||
|
||||
/*!
|
||||
\brief reset GPIO port
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset alternate function I/O(AFIO)
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_afio_deinit(void)
|
||||
{
|
||||
rcu_periph_reset_enable(RCU_AFRST);
|
||||
rcu_periph_reset_disable(RCU_AFRST);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief GPIO parameter initialization
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\param[in] mode: gpio pin mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg GPIO_MODE_AIN: analog input mode
|
||||
\arg GPIO_MODE_IN_FLOATING: floating input mode
|
||||
\arg GPIO_MODE_IPD: pull-down input mode
|
||||
\arg GPIO_MODE_IPU: pull-up input mode
|
||||
\arg GPIO_MODE_OUT_OD: GPIO output with open-drain
|
||||
\arg GPIO_MODE_OUT_PP: GPIO output with push-pull
|
||||
\arg GPIO_MODE_AF_OD: AFIO output with open-drain
|
||||
\arg GPIO_MODE_AF_PP: AFIO output with push-pull
|
||||
\param[in] speed: gpio output max speed value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg GPIO_OSPEED_10MHZ: output max speed 10MHz
|
||||
\arg GPIO_OSPEED_2MHZ: output max speed 2MHz
|
||||
\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_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin)
|
||||
{
|
||||
uint16_t i;
|
||||
uint32_t temp_mode = 0U;
|
||||
uint32_t reg = 0U;
|
||||
|
||||
/* GPIO mode configuration */
|
||||
temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU));
|
||||
|
||||
/* GPIO speed configuration */
|
||||
if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){
|
||||
/* output mode max speed */
|
||||
if(GPIO_OSPEED_MAX == (uint32_t)speed){
|
||||
temp_mode |= (uint32_t)0x03U;
|
||||
/* set the corresponding SPD bit */
|
||||
GPIOx_SPD(gpio_periph) |= (uint32_t)pin ;
|
||||
}else{
|
||||
/* output mode max speed:10MHz,2MHz,50MHz */
|
||||
temp_mode |= (uint32_t)speed;
|
||||
}
|
||||
}
|
||||
|
||||
/* configure the eight low port pins with GPIO_CTL0 */
|
||||
for(i = 0U;i < 8U;i++){
|
||||
if((1U << i) & pin){
|
||||
reg = GPIO_CTL0(gpio_periph);
|
||||
|
||||
/* clear the specified pin mode bits */
|
||||
reg &= ~GPIO_MODE_MASK(i);
|
||||
/* set the specified pin mode bits */
|
||||
reg |= GPIO_MODE_SET(i, temp_mode);
|
||||
|
||||
/* set IPD or IPU */
|
||||
if(GPIO_MODE_IPD == mode){
|
||||
/* reset the corresponding OCTL bit */
|
||||
GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}else{
|
||||
/* set the corresponding OCTL bit */
|
||||
if(GPIO_MODE_IPU == mode){
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}
|
||||
}
|
||||
/* set GPIO_CTL0 register */
|
||||
GPIO_CTL0(gpio_periph) = reg;
|
||||
}
|
||||
}
|
||||
/* configure the eight high port pins with GPIO_CTL1 */
|
||||
for(i = 8U;i < 16U;i++){
|
||||
if((1U << i) & pin){
|
||||
reg = GPIO_CTL1(gpio_periph);
|
||||
|
||||
/* clear the specified pin mode bits */
|
||||
reg &= ~GPIO_MODE_MASK(i - 8U);
|
||||
/* set the specified pin mode bits */
|
||||
reg |= GPIO_MODE_SET(i - 8U, temp_mode);
|
||||
|
||||
/* set IPD or IPU */
|
||||
if(GPIO_MODE_IPD == mode){
|
||||
/* reset the corresponding OCTL bit */
|
||||
GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}else{
|
||||
/* set the corresponding OCTL bit */
|
||||
if(GPIO_MODE_IPU == mode){
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}
|
||||
}
|
||||
/* set GPIO_CTL1 register */
|
||||
GPIO_CTL1(gpio_periph) = reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set GPIO pin bit
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\param[in] data: specify the value to be written to the port output data 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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\param[in] pin: GPIO pin
|
||||
only one parameter 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 port input status
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\param[in] pin: GPIO pin
|
||||
only one parameter 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: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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 configure GPIO pin remap
|
||||
\param[in] gpio_remap: select the pin to remap
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_SPI0_REMAP: SPI0 remapping
|
||||
\arg GPIO_I2C0_REMAP: I2C0 remapping
|
||||
\arg GPIO_USART0_REMAP: USART0 remapping
|
||||
\arg GPIO_USART1_REMAP: USART1 remapping
|
||||
\arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping
|
||||
\arg GPIO_USART2_FULL_REMAP: USART2 full remapping
|
||||
\arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping
|
||||
\arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping
|
||||
\arg GPIO_TIMER1_PARTIAL_REMAP0: TIMER1 partial remapping
|
||||
\arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping
|
||||
\arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping
|
||||
\arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping
|
||||
\arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping
|
||||
\arg GPIO_TIMER3_REMAP: TIMER3 remapping
|
||||
\arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_PD01_REMAP: PD01 remapping
|
||||
\arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping
|
||||
\arg GPIO_ADC0_ETRGRT_REMAP: ADC0 external trigger routine conversion remapping(only for GD32E50X_HD devices)
|
||||
\arg GPIO_ADC1_ETRGRT_REMAP: ADC1 external trigger routine conversion remapping(only for GD32E50X_HD devices)
|
||||
\arg GPIO_ENET_REMAP: ENET remapping(only for GD32E50X_CL and GD32E508 devices)
|
||||
\arg GPIO_CAN1_REMAP: CAN1 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST
|
||||
\arg GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled
|
||||
\arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled
|
||||
\arg GPIO_SPI2_REMAP: SPI2 remapping
|
||||
\arg GPIO_TIMER1ITR1_REMAP: TIMER1 internal trigger 1 remapping(only for GD32E50X_CL and GD32E508 devices)
|
||||
\arg GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping(only for GD32E50X_CL and GD32E508 devices)
|
||||
\arg GPIO_TIMER8_REMAP: TIMER8 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_TIMER9_REMAP: TIMER9 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_TIMER10_REMAP: TIMER10 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_TIMER12_REMAP: TIMER12 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_TIMER13_REMAP: TIMER13 remapping(not support on GD32EPRT devices)
|
||||
\arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect
|
||||
\arg GPIO_CTC_REMAP0: CTC remapping(PD15)
|
||||
\arg GPIO_CTC_REMAP1: CTC remapping(PF0)
|
||||
\param[in] newvalue: ENABLE or DISABLE
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue)
|
||||
{
|
||||
uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U;
|
||||
|
||||
if(((uint32_t)0x80000000U) == (remap & 0x80000000U)){
|
||||
/* get AFIO_PCF1 regiter value */
|
||||
temp_reg = AFIO_PCF1;
|
||||
}else{
|
||||
/* get AFIO_PCF0 regiter value */
|
||||
temp_reg = AFIO_PCF0;
|
||||
}
|
||||
|
||||
temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U;
|
||||
remap1 = remap & LSB_16BIT_MASK;
|
||||
|
||||
/* judge pin remap type */
|
||||
if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){
|
||||
temp_reg &= PCF_SWJCFG_MASK;
|
||||
AFIO_PCF0 &= PCF_SWJCFG_MASK;
|
||||
}else if(PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)){
|
||||
remap2 = ((uint32_t)0x03U) << temp_mask;
|
||||
temp_reg &= ~remap2;
|
||||
temp_reg |= ~PCF_SWJCFG_MASK;
|
||||
}else{
|
||||
temp_reg &= ~(remap1 << ((remap >> 0x15U)*0x10U));
|
||||
temp_reg |= ~PCF_SWJCFG_MASK;
|
||||
}
|
||||
|
||||
/* set pin remap value */
|
||||
if(DISABLE != newvalue){
|
||||
temp_reg |= (remap1 << ((remap >> 0x15U)*0x10U));
|
||||
}
|
||||
|
||||
if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){
|
||||
/* set AFIO_PCF1 regiter value */
|
||||
AFIO_PCF1 = temp_reg;
|
||||
}else{
|
||||
/* set AFIO_PCF0 regiter value */
|
||||
AFIO_PCF0 = temp_reg;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure AFIO port alternate function
|
||||
\param[in] afio_function: select the port AFIO function(SHRTIMER not support on GD32EPRT devices)
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg AFIO_PA2_CMP1_CFG: configure PA2 alternate function to CMP1
|
||||
\arg AFIO_PA3_USBHS_CFG: configure PA3 alternate function to USBHS
|
||||
\arg AFIO_PA5_USBHS_CFG: configure PA5 alternate function to USBHS
|
||||
\arg AFIO_PA8_I2C2_CFG: configure PA8 alternate function to I2C2
|
||||
\arg AFIO_PA8_SHRTIMER_CFG: configure PA8 alternate function to SHRTIMER
|
||||
\arg AFIO_PA9_CAN2_CFG: configure PA9 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PA9_I2C2_CFG: configure PA9 alternate function to I2C2
|
||||
\arg AFIO_PA9_SHRTIMER_CFG: configure PA9 alternate function to SHRTIMER
|
||||
\arg AFIO_PA10_CAN2_CFG: configure PA10 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PA10_CMP5_CFG: configure PA10 alternate function to CMP5
|
||||
\arg AFIO_PA10_SHRTIMER_CFG: configure PA10 alternate function to SHRTIMER
|
||||
\arg AFIO_PA11_USART5_CFG: configure PA11 alternate function to USART5
|
||||
\arg AFIO_PA11_SHRTIMER_CFG: configure PA11 alternate function to SHRTIMER
|
||||
\arg AFIO_PA12_CMP1_CFG: configure PA12 alternate function to CMP1
|
||||
\arg AFIO_PA12_USART5_CFG: configure PA12 alternate function to USART5
|
||||
\arg AFIO_PA12_SHRTIMER_CFG: configure PA12 alternate function to SHRTIMER
|
||||
\arg AFIO_PA15_SHRTIMER_CFG: configure PA15 alternate function to SHRTIMER
|
||||
\arg AFIO_PB0_USBHS_CFG: configure PB0 alternate function to USBHS
|
||||
\arg AFIO_PB1_CMP3_CFG: configure PB1 alternate function to CMP3
|
||||
\arg AFIO_PB1_USBHS_CFG: configure PB1 alternate function to USBHS
|
||||
\arg AFIO_PB1_SHRTIMER_CFG: configure PB1 alternate function to SHRTIMER
|
||||
\arg AFIO_PB2_USBHS_CFG: configure PB2 alternate function to USBHS
|
||||
\arg AFIO_PB2_SHRTIMER_CFG: configure PB2 alternate function to SHRTIMER
|
||||
\arg AFIO_PB3_SHRTIMER_CFG: configure PB3 alternate function to SHRTIMER
|
||||
\arg AFIO_PB4_I2S2_CFG: configure PB4 alternate function to I2S2
|
||||
\arg AFIO_PB4_I2C2_CFG: configure PB4 alternate function to I2C2
|
||||
\arg AFIO_PB4_SHRTIMER_CFG: configure PB4 alternate function to SHRTIMER
|
||||
\arg AFIO_PB5_I2C2_CFG: configure PB5 alternate function to I2C2
|
||||
\arg AFIO_PB5_USBHS_CFG: configure PB5 alternate function to USBHS
|
||||
\arg AFIO_PB5_SHRTIMER_CFG: configure PB5 alternate function to SHRTIMER
|
||||
\arg AFIO_PB6_SHRTIMER_CFG: configure PB6 alternate function to SHRTIMER
|
||||
\arg AFIO_PB7_SHRTIMER_CFG: configure PB7 alternate function to SHRTIMER
|
||||
\arg AFIO_PB8_I2C2_CFG: configure PB8 alternate function to I2C2
|
||||
\arg AFIO_PB8_SHRTIMER_CFG: configure PB8 alternate function to SHRTIMER
|
||||
\arg AFIO_PB9_CMP1_CFG: configure PB9 alternate function to CMP1
|
||||
\arg AFIO_PB9_SHRTIMER_CFG: configure PB9 alternate function to SHRTIMER
|
||||
\arg AFIO_PB10_CAN2_CFG: configure PB10 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PB10_USBHS_CFG: configure PB10 alternate function to USBHS
|
||||
\arg AFIO_PB10_SHRTIMER_CFG: configure PB10 alternate function to SHRTIMER
|
||||
\arg AFIO_PB11_CAN2_CFG: configure PB11 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PB11_USBHS_CFG: configure PB11 alternate function to USBHS
|
||||
\arg AFIO_PB11_SHRTIMER_CFG: configure PB11 alternate function to SHRTIMER
|
||||
\arg AFIO_PB12_USBHS_CFG: configure PB12 alternate function to USBHS
|
||||
\arg AFIO_PB12_SHRTIMER_CFG: configure PB12 alternate function to SHRTIMER
|
||||
\arg AFIO_PB13_USBHS_CFG: configure PB13 alternate function to USBHS
|
||||
\arg AFIO_PB13_SHRTIMER_CFG: configure PB13 alternate function to SHRTIMER
|
||||
\arg AFIO_PB14_I2S1_CFG: configure PB14 alternate function to I2S1
|
||||
\arg AFIO_PB14_SHRTIMER_CFG: configure PB14 alternate function to SHRTIMER
|
||||
\arg AFIO_PB15_SHRTIMER_CFG: configure PB15 alternate function to SHRTIMER
|
||||
\arg AFIO_PC0_USBHS_CFG: configure PC0 alternate function to USBHS
|
||||
\arg AFIO_PC2_I2S1_CFG: configure PC2 alternate function to I2S1
|
||||
\arg AFIO_PC2_USBHS_CFG: configure PC2 alternate function to USBHS
|
||||
\arg AFIO_PC3_USBHS_CFG: configure PC3 alternate function to USBHS
|
||||
\arg AFIO_PC6_CMP5_CFG: configure PC6 alternate function to CMP5
|
||||
\arg AFIO_PC6_USART5_CFG: configure PC6 alternate function to USART5
|
||||
\arg AFIO_PC6_SHRTIMER_CFG: configure PC6 alternate function to SHRTIMER
|
||||
\arg AFIO_PC7_USART5_CFG: configure PC7 alternate function to USART5
|
||||
\arg AFIO_PC7_SHRTIMER_CFG: configure PC7 alternate function to SHRTIMER
|
||||
\arg AFIO_PC8_USART5_CFG: configure PC8 alternate function to USART5
|
||||
\arg AFIO_PC8_SHRTIMER_CFG: configure PC8 alternate function to SHRTIMER
|
||||
\arg AFIO_PC9_I2C2_CFG: configure PC9 alternate function to I2C2
|
||||
\arg AFIO_PC9_SHRTIMER_CFG: configure PC9 alternate function to SHRTIMER
|
||||
\arg AFIO_PC10_I2C2_CFG: configure PC10 alternate function to I2C2
|
||||
\arg AFIO_PC11_I2S2_CFG: configure PC11 alternate function to I2S2
|
||||
\arg AFIO_PC11_SHRTIMER_CFG: configure PC11 alternate function to SHRTIMER
|
||||
\arg AFIO_PC12_SHRTIMER_CFG: configure PC12 alternate function to SHRTIMER
|
||||
\arg AFIO_PD4_SHRTIMER_CFG: configure PD4 alternate function to SHRTIMER
|
||||
\arg AFIO_PD5_SHRTIMER_CFG: configure PD5 alternate function to SHRTIMER
|
||||
\arg AFIO_PE0_CAN2_CFG: configure PE0 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PE0_SHRTIMER_CFG: configure PE0 alternate function to SHRTIMER
|
||||
\arg AFIO_PE1_CAN2_CFG: configure PE1 alternate function to CAN2(not support on GD32EPRT devices)
|
||||
\arg AFIO_PE1_SHRTIMER_CFG: configure PE1 alternate function to SHRTIMER
|
||||
\arg AFIO_PE8_CMP1_CFG: configure PE8 alternate function to CMP1
|
||||
\arg AFIO_PE9_CMP3_CFG: configure PE9 alternate function to CMP3
|
||||
\arg AFIO_PE10_CMP5_CFG: configure PE10 alternate function to CMP5
|
||||
\arg AFIO_PE11_CMP5_CFG: configure PE11 alternate function to CMP5
|
||||
\arg AFIO_PE12_CMP3_CFG: configure PE12 alternate function to CMP3
|
||||
\arg AFIO_PE13_CMP1_CFG: configure PE13 alternate function to CMP1
|
||||
\arg AFIO_PG6_SHRTIMER_CFG: configure PG6 alternate function to SHRTIMER
|
||||
\arg AFIO_PG7_USART5_CFG: configure PG7 alternate function to USART5
|
||||
\arg AFIO_PG7_SHRTIMER_CFG: configure PG7 alternate function to SHRTIMER
|
||||
\arg AFIO_PG9_USART5_CFG: configure PG9 alternate function to USART5
|
||||
\arg AFIO_PG10_SHRTIMER_CFG: configure PG10 alternate function to SHRTIMER
|
||||
\arg AFIO_PG11_SHRTIMER_CFG: configure PG11 alternate function to SHRTIMER
|
||||
\arg AFIO_PG12_SHRTIMER_CFG: configure PG12 alternate function to SHRTIMER
|
||||
\arg AFIO_PG13_SHRTIMER_CFG: configure PG13 alternate function to SHRTIMER
|
||||
\arg AFIO_PG14_USART5_CFG: configure PG14 alternate function to USART5
|
||||
\param[in] newvalue: ENABLE or DISABLE
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_afio_port_config(uint32_t afio_function, ControlStatus newvalue)
|
||||
{
|
||||
uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U;
|
||||
|
||||
/* get AFIO_PCFx(x=A,B,C,D,E,G) regiter value */
|
||||
temp_reg = REG32(AFIO+0x0000003CU+((afio_function>>24)<<2));
|
||||
|
||||
temp_mask = (afio_function & PCF_POSITION_MASK) >> 0x10U;
|
||||
remap1 = afio_function & LSB_16BIT_MASK;
|
||||
|
||||
/* judge port function select type */
|
||||
if(afio_function & PCF_LOCATION2_MASK){
|
||||
remap2 = ((uint32_t)0x03U) << temp_mask;
|
||||
remap2 = (remap2 << (((afio_function & PCF_LOCATION1_MASK) >> 0x15U)*0x10U));
|
||||
temp_reg &= ~remap2;
|
||||
}else{
|
||||
temp_reg &= ~(remap1 << (((afio_function & PCF_LOCATION1_MASK) >> 0x15U)*0x10U));
|
||||
}
|
||||
|
||||
/* set pin remap value */
|
||||
if(DISABLE != newvalue){
|
||||
temp_reg |= (remap1 << (((afio_function & PCF_LOCATION1_MASK) >> 0x15U)*0x10U));
|
||||
}
|
||||
|
||||
/* set AFIO_PCFx(x=A,B,C,D,E,G) regiter value */
|
||||
REG32(AFIO+0x0000003CU+((afio_function>>24)<<2)) = temp_reg;
|
||||
}
|
||||
|
||||
#if (defined(GD32E50X_CL) || defined(GD32E508) || defined(GD32EPRT))
|
||||
/*!
|
||||
\brief select ethernet MII or RMII PHY
|
||||
\param[in] enet_sel: ethernet MII or RMII PHY selection
|
||||
\arg GPIO_ENET_PHY_MII: configure ethernet MAC for connection with an MII PHY
|
||||
\arg GPIO_ENET_PHY_RMII: configure ethernet MAC for connection with an RMII PHY
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_ethernet_phy_select(uint32_t enet_sel)
|
||||
{
|
||||
/* clear AFIO_PCF0_ENET_PHY_SEL bit */
|
||||
AFIO_PCF0 &= (uint32_t)(~AFIO_PCF0_ENET_PHY_SEL);
|
||||
|
||||
/* select MII or RMII PHY */
|
||||
AFIO_PCF0 |= (uint32_t)enet_sel;
|
||||
}
|
||||
#endif /* GD32E50X_CL||GD32E508||GD32EPRT */
|
||||
|
||||
/*!
|
||||
\brief select GPIO pin exti sources
|
||||
\param[in] output_port: gpio event output port
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PORT_SOURCE_GPIOA: output port source A
|
||||
\arg GPIO_PORT_SOURCE_GPIOB: output port source B
|
||||
\arg GPIO_PORT_SOURCE_GPIOC: output port source C
|
||||
\arg GPIO_PORT_SOURCE_GPIOD: output port source D
|
||||
\arg GPIO_PORT_SOURCE_GPIOE: output port source E
|
||||
\arg GPIO_PORT_SOURCE_GPIOF: output port source F
|
||||
\arg GPIO_PORT_SOURCE_GPIOG: output port source G
|
||||
\param[in] output_pin: GPIO output pin source
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PIN_SOURCE_x(x=0..15)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin)
|
||||
{
|
||||
uint32_t source = 0U;
|
||||
source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK));
|
||||
|
||||
/* select EXTI sources */
|
||||
if(GPIO_PIN_SOURCE_4 > output_pin){
|
||||
/* select EXTI0/EXTI1/EXTI2/EXTI3 */
|
||||
AFIO_EXTISS0 &= ~source;
|
||||
AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else if(GPIO_PIN_SOURCE_8 > output_pin){
|
||||
/* select EXTI4/EXTI5/EXTI6/EXTI7 */
|
||||
AFIO_EXTISS1 &= ~source;
|
||||
AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else if(GPIO_PIN_SOURCE_12 > output_pin){
|
||||
/* select EXTI8/EXTI9/EXTI10/EXTI11 */
|
||||
AFIO_EXTISS2 &= ~source;
|
||||
AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else{
|
||||
/* select EXTI12/EXTI13/EXTI14/EXTI15 */
|
||||
AFIO_EXTISS3 &= ~source;
|
||||
AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure GPIO pin event output
|
||||
\param[in] output_port: gpio event output port
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_EVENT_PORT_GPIOA: event output port A
|
||||
\arg GPIO_EVENT_PORT_GPIOB: event output port B
|
||||
\arg GPIO_EVENT_PORT_GPIOC: event output port C
|
||||
\arg GPIO_EVENT_PORT_GPIOD: event output port D
|
||||
\arg GPIO_EVENT_PORT_GPIOE: event output port E
|
||||
\param[in] output_pin: GPIO event output pin
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_EVENT_PIN_x(x=0..15)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_config(uint8_t output_port, uint8_t output_pin)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
reg = AFIO_EC;
|
||||
|
||||
/* clear AFIO_EC_PORT and AFIO_EC_PIN bits */
|
||||
reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN));
|
||||
|
||||
reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET);
|
||||
reg |= (uint32_t)output_pin;
|
||||
|
||||
AFIO_EC = reg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable GPIO pin event output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_enable(void)
|
||||
{
|
||||
AFIO_EC |= AFIO_EC_EOE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable GPIO pin event output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_disable(void)
|
||||
{
|
||||
AFIO_EC &= (uint32_t)(~AFIO_EC_EOE);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief lock GPIO pin bit
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G)
|
||||
\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 configure the I/O compensation cell
|
||||
\param[in] compensation: specifies the I/O compensation cell mode
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_COMPENSATION_ENABLE: I/O compensation cell is enabled
|
||||
\arg GPIO_COMPENSATION_DISABLE: I/O compensation cell is disabled
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_compensation_config(uint32_t compensation)
|
||||
{
|
||||
uint32_t reg;
|
||||
reg = AFIO_CPSCTL;
|
||||
|
||||
/* reset the AFIO_CPSCTL_CPS_EN bit and set according to gpio_compensation */
|
||||
reg &= ~AFIO_CPSCTL_CPS_EN;
|
||||
AFIO_CPSCTL = (reg | compensation);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check the I/O compensation cell is ready or not
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus gpio_compensation_flag_get(void)
|
||||
{
|
||||
if(((uint32_t)RESET) != (AFIO_CPSCTL & AFIO_CPSCTL_CPS_RDY)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*!
|
||||
\file gd32e50x_misc.c
|
||||
\brief MISC driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_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 nvic_prigroup, nvic_priority;
|
||||
|
||||
/* check current priority group */
|
||||
switch(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) {
|
||||
case NVIC_PRIGROUP_PRE0_SUB4:
|
||||
case NVIC_PRIGROUP_PRE1_SUB3:
|
||||
case NVIC_PRIGROUP_PRE2_SUB2:
|
||||
case NVIC_PRIGROUP_PRE3_SUB1:
|
||||
case NVIC_PRIGROUP_PRE4_SUB0:
|
||||
break;
|
||||
default:
|
||||
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
|
||||
break;
|
||||
}
|
||||
|
||||
/* get the priority group value */
|
||||
nvic_prigroup = NVIC_GetPriorityGrouping();
|
||||
|
||||
/* encoding the pre-emption, subpriority priority */
|
||||
nvic_priority = NVIC_EncodePriority(nvic_prigroup, (uint32_t)nvic_irq_pre_priority, (uint32_t)nvic_irq_sub_priority);
|
||||
/* set priority */
|
||||
NVIC_SetPriority(nvic_irq, nvic_priority);
|
||||
|
||||
/* enable the selected IRQ */
|
||||
NVIC_EnableIRQ(nvic_irq);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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_DisableIRQ((IRQn_Type)nvic_irq);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initiates a system reset request to reset the MCU
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void nvic_system_reset(void)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
/*!
|
||||
\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,180 @@
|
||||
/*!
|
||||
\file gd32e50x_misc.c
|
||||
\brief MISC driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_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 nvic_prigroup, nvic_priority;
|
||||
|
||||
/* check current priority group */
|
||||
switch(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) {
|
||||
case NVIC_PRIGROUP_PRE0_SUB4:
|
||||
case NVIC_PRIGROUP_PRE1_SUB3:
|
||||
case NVIC_PRIGROUP_PRE2_SUB2:
|
||||
case NVIC_PRIGROUP_PRE3_SUB1:
|
||||
case NVIC_PRIGROUP_PRE4_SUB0:
|
||||
break;
|
||||
default:
|
||||
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
|
||||
break;
|
||||
}
|
||||
|
||||
/* get the priority group value */
|
||||
nvic_prigroup = NVIC_GetPriorityGrouping();
|
||||
|
||||
/* encoding the pre-emption, subpriority priority */
|
||||
nvic_priority = NVIC_EncodePriority(nvic_prigroup, (uint32_t)nvic_irq_pre_priority, (uint32_t)nvic_irq_sub_priority);
|
||||
/* set priority */
|
||||
NVIC_SetPriority(nvic_irq, nvic_priority);
|
||||
|
||||
/* enable the selected IRQ */
|
||||
NVIC_EnableIRQ(nvic_irq);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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_DisableIRQ((IRQn_Type)nvic_irq);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initiates a system reset request to reset the MCU
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void nvic_system_reset(void)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
/*!
|
||||
\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,522 @@
|
||||
/*!
|
||||
\file gd32e50x_pmu.c
|
||||
\brief PMU driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_pmu.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:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\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_CTL0 &= ~PMU_CTL0_LVDEN;
|
||||
/* clear LVDT bits */
|
||||
PMU_CTL0 &= ~PMU_CTL0_LVDT;
|
||||
/* set LVDT bits according to lvdt_n */
|
||||
PMU_CTL0 |= lvdt_n;
|
||||
/* enable LVD */
|
||||
PMU_CTL0 |= PMU_CTL0_LVDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable PMU LVD
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_lvd_disable(void)
|
||||
{
|
||||
/* disable LVD */
|
||||
PMU_CTL0 &= ~PMU_CTL0_LVDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable high-driver mode
|
||||
this bit set by software only when IRC8M or HXTAL used as system clock
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_highdriver_mode_enable(void)
|
||||
{
|
||||
PMU_CTL0 |= PMU_CTL0_HDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable high-driver mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_highdriver_mode_disable(void)
|
||||
{
|
||||
PMU_CTL0 &= ~PMU_CTL0_HDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief switch high-driver mode
|
||||
this bit set by software only when IRC8M or HXTAL used as system clock
|
||||
\param[in] highdr_switch:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\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_CTL0 &= ~PMU_CTL0_HDS;
|
||||
PMU_CTL0 |= highdr_switch;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable low-driver mode in deep-sleep/deep-sleep 1/deep-sleep 2 mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_lowdriver_mode_enable(void)
|
||||
{
|
||||
PMU_CTL0 |= PMU_CTL0_LDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable low-driver mode in deep-sleep/deep-sleep 1/deep-sleep 2 mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_lowdriver_mode_disable(void)
|
||||
{
|
||||
PMU_CTL0 &= ~PMU_CTL0_LDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief in deep-sleep/deep-sleep 1/deep-sleep 2 mode, driver mode when use low power LDO
|
||||
\param[in] mode:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\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_CTL0 &= ~PMU_CTL0_LDLP;
|
||||
PMU_CTL0 |= mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief in deep-sleep/deep-sleep 1/deep-sleep 2 mode, driver mode when use normal power LDO
|
||||
\param[in] mode:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\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_CTL0 &= ~PMU_CTL0_LDNP;
|
||||
PMU_CTL0 |= mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at sleep mode
|
||||
\param[in] sleepmodecmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_sleepmode(uint8_t sleepmodecmd)
|
||||
{
|
||||
/* clear sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
|
||||
/* select WFI or WFE command to enter sleep mode */
|
||||
if(WFI_CMD == sleepmodecmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at deepsleep mode
|
||||
\param[in] ldo:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LDO_NORMAL: LDO normal work when pmu enter deepsleep mode
|
||||
\arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode
|
||||
\param[in] lowdrive:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LOWDRIVER_ENABLE: low-driver mode enable in deep-sleep mode
|
||||
\arg PMU_LOWDRIVER_DISABLE: low-driver mode disable in deep-sleep mode
|
||||
\param[in] deepsleepmodecmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_deepsleepmode(uint32_t ldo, uint32_t lowdrive, uint8_t deepsleepmodecmd)
|
||||
{
|
||||
/* clear stbmod and ldolp bits and low drive bits */
|
||||
PMU_CTL0 &= ~((uint32_t)(PMU_CTL0_STBMOD | PMU_CTL0_LDOLP | PMU_CTL0_LDEN | PMU_CTL0_LDNP | PMU_CTL0_LDLP));
|
||||
/* clear deep-sleep 1/2 mode enable bits */
|
||||
PMU_CTL1 &= ~(PMU_CTL1_DPMOD1 | PMU_CTL1_DPMOD2);
|
||||
|
||||
/* set ldolp bit according to pmu_ldo */
|
||||
PMU_CTL0 |= ldo;
|
||||
|
||||
/* low drive mode config in deep-sleep mode */
|
||||
if(PMU_LOWDRIVER_ENABLE == lowdrive){
|
||||
if(PMU_LDO_NORMAL == ldo){
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDNP);
|
||||
}else{
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDLP);
|
||||
}
|
||||
}
|
||||
|
||||
/* set sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
/* select WFI or WFE command to enter deepsleep mode */
|
||||
if(WFI_CMD == deepsleepmodecmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
|
||||
/* reset sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at deepsleep mode 1
|
||||
\param[in] ldo:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LDO_NORMAL: LDO normal work when pmu enter deepsleep mode 1
|
||||
\arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode 1
|
||||
\param[in] lowdrive:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LOWDRIVER_ENABLE: low-driver mode enable in deep-sleep 1 mode
|
||||
\arg PMU_LOWDRIVER_DISABLE: low-driver mode disable in deep-sleep 1 mode
|
||||
\param[in] deepsleepmode1cmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_deepsleepmode_1(uint32_t ldo, uint32_t lowdrive, uint8_t deepsleepmode1cmd)
|
||||
{
|
||||
/* clear stbmod and ldolp bits and low drive bits */
|
||||
PMU_CTL0 &= ~((uint32_t)(PMU_CTL0_STBMOD | PMU_CTL0_LDOLP | PMU_CTL0_LDEN | PMU_CTL0_LDNP | PMU_CTL0_LDLP));
|
||||
/* clear deep-sleep 2 mode enable bit */
|
||||
PMU_CTL1 &= ~PMU_CTL1_DPMOD2;
|
||||
/* enable deep-sleep 1 mode */
|
||||
PMU_CTL1 |= PMU_CTL1_DPMOD1;
|
||||
|
||||
/* set ldolp bit according to pmu_ldo */
|
||||
PMU_CTL0 |= ldo;
|
||||
|
||||
/* low drive mode config in deep-sleep 1 mode */
|
||||
if(PMU_LOWDRIVER_ENABLE == lowdrive){
|
||||
if(PMU_LDO_NORMAL == ldo){
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDNP);
|
||||
}else{
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDLP);
|
||||
}
|
||||
}
|
||||
|
||||
/* set sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
/* select WFI or WFE command to enter deepsleep mode 1 */
|
||||
if(WFI_CMD == deepsleepmode1cmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
|
||||
/* reset sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
PMU_CTL1 &= ~PMU_CTL1_DPMOD1;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at deepsleep mode 2
|
||||
\param[in] ldo:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LDO_NORMAL: LDO normal work when pmu enter deepsleep mode 2
|
||||
\arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode 2
|
||||
\param[in] lowdrive:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LOWDRIVER_ENABLE: low-driver mode enable in deep-sleep 2 mode
|
||||
\arg PMU_LOWDRIVER_DISABLE: low-driver mode disable in deep-sleep 2 mode
|
||||
\param[in] deepsleepmode2cmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_deepsleepmode_2(uint32_t ldo, uint32_t lowdrive, uint8_t deepsleepmode2cmd)
|
||||
{
|
||||
/* clear stbmod and ldolp bits and low drive bits */
|
||||
PMU_CTL0 &= ~((uint32_t)(PMU_CTL0_STBMOD | PMU_CTL0_LDOLP | PMU_CTL0_LDEN | PMU_CTL0_LDNP | PMU_CTL0_LDLP));
|
||||
/* clear deep-sleep 1 mode enable bit */
|
||||
PMU_CTL1 &= ~PMU_CTL1_DPMOD1;
|
||||
/* enable deep-sleep 2 mode */
|
||||
PMU_CTL1 |= PMU_CTL1_DPMOD2;
|
||||
|
||||
/* set ldolp bit according to pmu_ldo */
|
||||
PMU_CTL0 |= ldo;
|
||||
|
||||
/* low drive mode config in deep-sleep 2 mode */
|
||||
if(PMU_LOWDRIVER_ENABLE == lowdrive){
|
||||
if(PMU_LDO_NORMAL == ldo){
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDNP);
|
||||
}else{
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDLP);
|
||||
}
|
||||
}
|
||||
|
||||
/* set sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
/* select WFI or WFE command to enter deepsleep mode 2 */
|
||||
if(WFI_CMD == deepsleepmode2cmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
|
||||
/* reset sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
PMU_CTL1 &= ~PMU_CTL1_DPMOD2;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief pmu work at standby mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_standbymode(void)
|
||||
{
|
||||
/* set stbmod bit */
|
||||
PMU_CTL0 |= PMU_CTL0_STBMOD;
|
||||
|
||||
/* reset wakeup flag */
|
||||
PMU_CTL0 |= PMU_CTL0_WURST;
|
||||
|
||||
/* set sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
REG32( 0xE000E010U ) &= 0x00010004U;
|
||||
REG32( 0xE000E180U ) = 0XFFFFFFF7U;
|
||||
REG32( 0xE000E184U ) = 0XFFFFFDFFU;
|
||||
REG32( 0xE000E188U ) = 0xFFFFFFFFU;
|
||||
|
||||
/* select WFI command to enter standby mode */
|
||||
__WFI();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable PMU wakeup pin
|
||||
\param[in] wakeup_pin:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg PMU_WAKEUP_PIN0: WKUP Pin 0 (PA0)
|
||||
\arg PMU_WAKEUP_PIN1: WKUP Pin 1 (PC13)
|
||||
\arg PMU_WAKEUP_PIN2: WKUP Pin 2 (PE6)
|
||||
\arg PMU_WAKEUP_PIN3: WKUP Pin 3 (PA2)
|
||||
\arg PMU_WAKEUP_PIN4: WKUP Pin 4 (PC5)
|
||||
\arg PMU_WAKEUP_PIN5: WKUP Pin 5 (PB5)
|
||||
\arg PMU_WAKEUP_PIN6: WKUP Pin 6 (PB15)
|
||||
\arg PMU_WAKEUP_PIN7: WKUP Pin 7 (PF8)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_wakeup_pin_enable(uint32_t wakeup_pin)
|
||||
{
|
||||
PMU_CS0 |= wakeup_pin;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable PMU wakeup pin
|
||||
\param[in] wakeup_pin:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg PMU_WAKEUP_PIN0: WKUP Pin 0 (PA0)
|
||||
\arg PMU_WAKEUP_PIN1: WKUP Pin 1 (PC13)
|
||||
\arg PMU_WAKEUP_PIN2: WKUP Pin 2 (PE6)
|
||||
\arg PMU_WAKEUP_PIN3: WKUP Pin 3 (PA2)
|
||||
\arg PMU_WAKEUP_PIN4: WKUP Pin 4 (PC5)
|
||||
\arg PMU_WAKEUP_PIN5: WKUP Pin 5 (PB5)
|
||||
\arg PMU_WAKEUP_PIN6: WKUP Pin 6 (PB15)
|
||||
\arg PMU_WAKEUP_PIN7: WKUP Pin 7 (PF8)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_wakeup_pin_disable(uint32_t wakeup_pin)
|
||||
{
|
||||
PMU_CS0 &= ~(wakeup_pin);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable backup domain write
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_backup_write_enable(void)
|
||||
{
|
||||
PMU_CTL0 |= PMU_CTL0_BKPWEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable backup domain write
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_backup_write_disable(void)
|
||||
{
|
||||
PMU_CTL0 &= ~PMU_CTL0_BKPWEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get flag state
|
||||
\param[in] flag:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_FLAG_WAKEUP: wakeup flag
|
||||
\arg PMU_FLAG_STANDBY: standby flag
|
||||
\arg PMU_FLAG_LVD: lvd 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
|
||||
\arg PMU_FLAG_DEEPSLEEP_1: deep-sleep 1 mode status flag
|
||||
\arg PMU_FLAG_DEEPSLEEP_2: deep-sleep 2 mode status flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus pmu_flag_get(uint32_t flag)
|
||||
{
|
||||
FlagStatus ret = RESET;
|
||||
|
||||
if(RESET != (flag & BIT(31))){
|
||||
flag &= ~BIT(31);
|
||||
if(PMU_CS1 & flag){
|
||||
ret = SET;
|
||||
}
|
||||
}else{
|
||||
if(PMU_CS0 & flag){
|
||||
ret = SET;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear flag bit
|
||||
\param[in] flag:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag
|
||||
\arg PMU_FLAG_RESET_STANDBY: reset standby flag
|
||||
\arg PMU_FLAG_RESET_DEEPSLEEP_1: reset deep-sleep 1 mode status flag
|
||||
\arg PMU_FLAG_RESET_DEEPSLEEP_2: reset deep-sleep 2 mode status flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_flag_clear(uint32_t flag)
|
||||
{
|
||||
switch(flag){
|
||||
case PMU_FLAG_RESET_WAKEUP:
|
||||
/* reset wakeup flag */
|
||||
PMU_CTL0 |= PMU_CTL0_WURST;
|
||||
break;
|
||||
case PMU_FLAG_RESET_STANDBY:
|
||||
/* reset standby flag */
|
||||
PMU_CTL0 |= PMU_CTL0_STBRST;
|
||||
break;
|
||||
case PMU_FLAG_RESET_DEEPSLEEP_1:
|
||||
/* reset deep-sleep 1 mode status flag */
|
||||
PMU_CS1 &= ~PMU_CS1_DPF1;
|
||||
break;
|
||||
case PMU_FLAG_RESET_DEEPSLEEP_2:
|
||||
/* reset deep-sleep 2 mode status flag */
|
||||
PMU_CS1 &= ~PMU_CS1_DPF2;
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,522 @@
|
||||
/*!
|
||||
\file gd32e50x_pmu.c
|
||||
\brief PMU driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_pmu.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:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\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_CTL0 &= ~PMU_CTL0_LVDEN;
|
||||
/* clear LVDT bits */
|
||||
PMU_CTL0 &= ~PMU_CTL0_LVDT;
|
||||
/* set LVDT bits according to lvdt_n */
|
||||
PMU_CTL0 |= lvdt_n;
|
||||
/* enable LVD */
|
||||
PMU_CTL0 |= PMU_CTL0_LVDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable PMU LVD
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_lvd_disable(void)
|
||||
{
|
||||
/* disable LVD */
|
||||
PMU_CTL0 &= ~PMU_CTL0_LVDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable high-driver mode
|
||||
this bit set by software only when IRC8M or HXTAL used as system clock
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_highdriver_mode_enable(void)
|
||||
{
|
||||
PMU_CTL0 |= PMU_CTL0_HDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable high-driver mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_highdriver_mode_disable(void)
|
||||
{
|
||||
PMU_CTL0 &= ~PMU_CTL0_HDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief switch high-driver mode
|
||||
this bit set by software only when IRC8M or HXTAL used as system clock
|
||||
\param[in] highdr_switch:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\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_CTL0 &= ~PMU_CTL0_HDS;
|
||||
PMU_CTL0 |= highdr_switch;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable low-driver mode in deep-sleep/deep-sleep 1/deep-sleep 2 mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_lowdriver_mode_enable(void)
|
||||
{
|
||||
PMU_CTL0 |= PMU_CTL0_LDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable low-driver mode in deep-sleep/deep-sleep 1/deep-sleep 2 mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_lowdriver_mode_disable(void)
|
||||
{
|
||||
PMU_CTL0 &= ~PMU_CTL0_LDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief in deep-sleep/deep-sleep 1/deep-sleep 2 mode, driver mode when use low power LDO
|
||||
\param[in] mode:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\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_CTL0 &= ~PMU_CTL0_LDLP;
|
||||
PMU_CTL0 |= mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief in deep-sleep/deep-sleep 1/deep-sleep 2 mode, driver mode when use normal power LDO
|
||||
\param[in] mode:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\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_CTL0 &= ~PMU_CTL0_LDNP;
|
||||
PMU_CTL0 |= mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at sleep mode
|
||||
\param[in] sleepmodecmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_sleepmode(uint8_t sleepmodecmd)
|
||||
{
|
||||
/* clear sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
|
||||
/* select WFI or WFE command to enter sleep mode */
|
||||
if(WFI_CMD == sleepmodecmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at deepsleep mode
|
||||
\param[in] ldo:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LDO_NORMAL: LDO normal work when pmu enter deepsleep mode
|
||||
\arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode
|
||||
\param[in] lowdrive:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LOWDRIVER_ENABLE: low-driver mode enable in deep-sleep mode
|
||||
\arg PMU_LOWDRIVER_DISABLE: low-driver mode disable in deep-sleep mode
|
||||
\param[in] deepsleepmodecmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_deepsleepmode(uint32_t ldo, uint32_t lowdrive, uint8_t deepsleepmodecmd)
|
||||
{
|
||||
/* clear stbmod and ldolp bits and low drive bits */
|
||||
PMU_CTL0 &= ~((uint32_t)(PMU_CTL0_STBMOD | PMU_CTL0_LDOLP | PMU_CTL0_LDEN | PMU_CTL0_LDNP | PMU_CTL0_LDLP));
|
||||
/* clear deep-sleep 1/2 mode enable bits */
|
||||
PMU_CTL1 &= ~(PMU_CTL1_DPMOD1 | PMU_CTL1_DPMOD2);
|
||||
|
||||
/* set ldolp bit according to pmu_ldo */
|
||||
PMU_CTL0 |= ldo;
|
||||
|
||||
/* low drive mode config in deep-sleep mode */
|
||||
if(PMU_LOWDRIVER_ENABLE == lowdrive){
|
||||
if(PMU_LDO_NORMAL == ldo){
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDNP);
|
||||
}else{
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDLP);
|
||||
}
|
||||
}
|
||||
|
||||
/* set sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
/* select WFI or WFE command to enter deepsleep mode */
|
||||
if(WFI_CMD == deepsleepmodecmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
|
||||
/* reset sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at deepsleep mode 1
|
||||
\param[in] ldo:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LDO_NORMAL: LDO normal work when pmu enter deepsleep mode 1
|
||||
\arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode 1
|
||||
\param[in] lowdrive:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LOWDRIVER_ENABLE: low-driver mode enable in deep-sleep 1 mode
|
||||
\arg PMU_LOWDRIVER_DISABLE: low-driver mode disable in deep-sleep 1 mode
|
||||
\param[in] deepsleepmode1cmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_deepsleepmode_1(uint32_t ldo, uint32_t lowdrive, uint8_t deepsleepmode1cmd)
|
||||
{
|
||||
/* clear stbmod and ldolp bits and low drive bits */
|
||||
PMU_CTL0 &= ~((uint32_t)(PMU_CTL0_STBMOD | PMU_CTL0_LDOLP | PMU_CTL0_LDEN | PMU_CTL0_LDNP | PMU_CTL0_LDLP));
|
||||
/* clear deep-sleep 2 mode enable bit */
|
||||
PMU_CTL1 &= ~PMU_CTL1_DPMOD2;
|
||||
/* enable deep-sleep 1 mode */
|
||||
PMU_CTL1 |= PMU_CTL1_DPMOD1;
|
||||
|
||||
/* set ldolp bit according to pmu_ldo */
|
||||
PMU_CTL0 |= ldo;
|
||||
|
||||
/* low drive mode config in deep-sleep 1 mode */
|
||||
if(PMU_LOWDRIVER_ENABLE == lowdrive){
|
||||
if(PMU_LDO_NORMAL == ldo){
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDNP);
|
||||
}else{
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDLP);
|
||||
}
|
||||
}
|
||||
|
||||
/* set sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
/* select WFI or WFE command to enter deepsleep mode 1 */
|
||||
if(WFI_CMD == deepsleepmode1cmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
|
||||
/* reset sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
PMU_CTL1 &= ~PMU_CTL1_DPMOD1;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at deepsleep mode 2
|
||||
\param[in] ldo:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LDO_NORMAL: LDO normal work when pmu enter deepsleep mode 2
|
||||
\arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode 2
|
||||
\param[in] lowdrive:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LOWDRIVER_ENABLE: low-driver mode enable in deep-sleep 2 mode
|
||||
\arg PMU_LOWDRIVER_DISABLE: low-driver mode disable in deep-sleep 2 mode
|
||||
\param[in] deepsleepmode2cmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_deepsleepmode_2(uint32_t ldo, uint32_t lowdrive, uint8_t deepsleepmode2cmd)
|
||||
{
|
||||
/* clear stbmod and ldolp bits and low drive bits */
|
||||
PMU_CTL0 &= ~((uint32_t)(PMU_CTL0_STBMOD | PMU_CTL0_LDOLP | PMU_CTL0_LDEN | PMU_CTL0_LDNP | PMU_CTL0_LDLP));
|
||||
/* clear deep-sleep 1 mode enable bit */
|
||||
PMU_CTL1 &= ~PMU_CTL1_DPMOD1;
|
||||
/* enable deep-sleep 2 mode */
|
||||
PMU_CTL1 |= PMU_CTL1_DPMOD2;
|
||||
|
||||
/* set ldolp bit according to pmu_ldo */
|
||||
PMU_CTL0 |= ldo;
|
||||
|
||||
/* low drive mode config in deep-sleep 2 mode */
|
||||
if(PMU_LOWDRIVER_ENABLE == lowdrive){
|
||||
if(PMU_LDO_NORMAL == ldo){
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDNP);
|
||||
}else{
|
||||
PMU_CTL0 |= (uint32_t)(PMU_CTL0_LDEN | PMU_CTL0_LDLP);
|
||||
}
|
||||
}
|
||||
|
||||
/* set sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
/* select WFI or WFE command to enter deepsleep mode 2 */
|
||||
if(WFI_CMD == deepsleepmode2cmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
|
||||
/* reset sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
PMU_CTL1 &= ~PMU_CTL1_DPMOD2;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief pmu work at standby mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_standbymode(void)
|
||||
{
|
||||
/* set stbmod bit */
|
||||
PMU_CTL0 |= PMU_CTL0_STBMOD;
|
||||
|
||||
/* reset wakeup flag */
|
||||
PMU_CTL0 |= PMU_CTL0_WURST;
|
||||
|
||||
/* set sleepdeep bit of Cortex-M33 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
REG32( 0xE000E010U ) &= 0x00010004U;
|
||||
REG32( 0xE000E180U ) = 0XFFFFFFF7U;
|
||||
REG32( 0xE000E184U ) = 0XFFFFFDFFU;
|
||||
REG32( 0xE000E188U ) = 0xFFFFFFFFU;
|
||||
|
||||
/* select WFI command to enter standby mode */
|
||||
__WFI();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable PMU wakeup pin
|
||||
\param[in] wakeup_pin:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg PMU_WAKEUP_PIN0: WKUP Pin 0 (PA0)
|
||||
\arg PMU_WAKEUP_PIN1: WKUP Pin 1 (PC13)
|
||||
\arg PMU_WAKEUP_PIN2: WKUP Pin 2 (PE6)
|
||||
\arg PMU_WAKEUP_PIN3: WKUP Pin 3 (PA2)
|
||||
\arg PMU_WAKEUP_PIN4: WKUP Pin 4 (PC5)
|
||||
\arg PMU_WAKEUP_PIN5: WKUP Pin 5 (PB5)
|
||||
\arg PMU_WAKEUP_PIN6: WKUP Pin 6 (PB15)
|
||||
\arg PMU_WAKEUP_PIN7: WKUP Pin 7 (PF8)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_wakeup_pin_enable(uint32_t wakeup_pin)
|
||||
{
|
||||
PMU_CS0 |= wakeup_pin;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable PMU wakeup pin
|
||||
\param[in] wakeup_pin:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg PMU_WAKEUP_PIN0: WKUP Pin 0 (PA0)
|
||||
\arg PMU_WAKEUP_PIN1: WKUP Pin 1 (PC13)
|
||||
\arg PMU_WAKEUP_PIN2: WKUP Pin 2 (PE6)
|
||||
\arg PMU_WAKEUP_PIN3: WKUP Pin 3 (PA2)
|
||||
\arg PMU_WAKEUP_PIN4: WKUP Pin 4 (PC5)
|
||||
\arg PMU_WAKEUP_PIN5: WKUP Pin 5 (PB5)
|
||||
\arg PMU_WAKEUP_PIN6: WKUP Pin 6 (PB15)
|
||||
\arg PMU_WAKEUP_PIN7: WKUP Pin 7 (PF8)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_wakeup_pin_disable(uint32_t wakeup_pin)
|
||||
{
|
||||
PMU_CS0 &= ~(wakeup_pin);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable backup domain write
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_backup_write_enable(void)
|
||||
{
|
||||
PMU_CTL0 |= PMU_CTL0_BKPWEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable backup domain write
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_backup_write_disable(void)
|
||||
{
|
||||
PMU_CTL0 &= ~PMU_CTL0_BKPWEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get flag state
|
||||
\param[in] flag:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_FLAG_WAKEUP: wakeup flag
|
||||
\arg PMU_FLAG_STANDBY: standby flag
|
||||
\arg PMU_FLAG_LVD: lvd 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
|
||||
\arg PMU_FLAG_DEEPSLEEP_1: deep-sleep 1 mode status flag
|
||||
\arg PMU_FLAG_DEEPSLEEP_2: deep-sleep 2 mode status flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus pmu_flag_get(uint32_t flag)
|
||||
{
|
||||
FlagStatus ret = RESET;
|
||||
|
||||
if(RESET != (flag & BIT(31))){
|
||||
flag &= ~BIT(31);
|
||||
if(PMU_CS1 & flag){
|
||||
ret = SET;
|
||||
}
|
||||
}else{
|
||||
if(PMU_CS0 & flag){
|
||||
ret = SET;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear flag bit
|
||||
\param[in] flag:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag
|
||||
\arg PMU_FLAG_RESET_STANDBY: reset standby flag
|
||||
\arg PMU_FLAG_RESET_DEEPSLEEP_1: reset deep-sleep 1 mode status flag
|
||||
\arg PMU_FLAG_RESET_DEEPSLEEP_2: reset deep-sleep 2 mode status flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_flag_clear(uint32_t flag)
|
||||
{
|
||||
switch(flag){
|
||||
case PMU_FLAG_RESET_WAKEUP:
|
||||
/* reset wakeup flag */
|
||||
PMU_CTL0 |= PMU_CTL0_WURST;
|
||||
break;
|
||||
case PMU_FLAG_RESET_STANDBY:
|
||||
/* reset standby flag */
|
||||
PMU_CTL0 |= PMU_CTL0_STBRST;
|
||||
break;
|
||||
case PMU_FLAG_RESET_DEEPSLEEP_1:
|
||||
/* reset deep-sleep 1 mode status flag */
|
||||
PMU_CS1 &= ~PMU_CS1_DPF1;
|
||||
break;
|
||||
case PMU_FLAG_RESET_DEEPSLEEP_2:
|
||||
/* reset deep-sleep 2 mode status flag */
|
||||
PMU_CS1 &= ~PMU_CS1_DPF2;
|
||||
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,895 @@
|
||||
/*!
|
||||
\file gd32e50x_spi.c
|
||||
\brief SPI driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_spi.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 */
|
||||
|
||||
/* I2S clock source selection, multiplication and division mask */
|
||||
#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /*!< I2S1 clock source selection */
|
||||
#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /*!< I2S2 clock source selection */
|
||||
#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /*!< I2S clock multiplication mask */
|
||||
#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /*!< I2S clock division mask */
|
||||
|
||||
/*!
|
||||
\brief reset SPI and I2S
|
||||
\param[in] spi_periph: SPIx(x=0,1,2),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;
|
||||
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)
|
||||
\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)
|
||||
\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)
|
||||
\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_PHILIPS: I2S philips 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 prescaler
|
||||
\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;
|
||||
|
||||
#ifdef GD32E50X_CL
|
||||
uint32_t pll2mf_4 = 0U;
|
||||
#endif /* GD32E50X_CL */
|
||||
|
||||
/* deinit SPI_I2SPSC register */
|
||||
SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE;
|
||||
|
||||
#ifdef GD32E50X_CL
|
||||
/* get the I2S clock source */
|
||||
if(((uint32_t)spi_periph) == SPI1){
|
||||
/* I2S1 clock source selection */
|
||||
clks = I2S1_CLOCK_SEL;
|
||||
}else{
|
||||
/* I2S2 clock source selection */
|
||||
clks = I2S2_CLOCK_SEL;
|
||||
}
|
||||
|
||||
if(0U != (RCU_CFG1 & clks)){
|
||||
/* get RCU PLL2 clock multiplication factor */
|
||||
clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> 12U);
|
||||
|
||||
pll2mf_4 = RCU_CFG1 & RCU_CFG1_PLL2MF_4;
|
||||
|
||||
if( 0U == pll2mf_4){
|
||||
if((clks > 5U) && (clks < 15U)){
|
||||
/* multiplier is between 8 and 16 */
|
||||
clks += 2U;
|
||||
}else{
|
||||
if(15U == clks){
|
||||
/* multiplier is 20 */
|
||||
clks = 20U;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(clks < 15U){
|
||||
/* multiplier is between 18 and 32 */
|
||||
clks += 18U;
|
||||
}else{
|
||||
if(15U == clks){
|
||||
/* multiplier is 40 */
|
||||
clks = 40U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get the PREDV1 value */
|
||||
i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> 4U) + 1U);
|
||||
/* calculate i2sclock based on PLL2 and PREDV1 */
|
||||
i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U);
|
||||
}else{
|
||||
/* get system clock */
|
||||
i2sclock = rcu_clock_freq_get(CK_SYS);
|
||||
}
|
||||
#else
|
||||
/* get system clock */
|
||||
i2sclock = rcu_clock_freq_get(CK_SYS);
|
||||
#endif /* GD32E50X_CL */
|
||||
|
||||
/* 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)
|
||||
\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)
|
||||
\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)
|
||||
\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)
|
||||
\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)
|
||||
\param[in] 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 dma)
|
||||
{
|
||||
if(SPI_DMA_TRANSMIT == dma){
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN;
|
||||
}else{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI DMA send or receive
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] 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 dma)
|
||||
{
|
||||
if(SPI_DMA_TRANSMIT == 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)
|
||||
\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);
|
||||
/* confige 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)
|
||||
\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)
|
||||
\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)
|
||||
\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 clear SPI/I2S format error flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\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)
|
||||
\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)
|
||||
{
|
||||
/* enable SPI CRC */
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
|
||||
|
||||
/* 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)
|
||||
\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 CRC function
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\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 CRC function
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\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)
|
||||
\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)
|
||||
\param[in] 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 crc)
|
||||
{
|
||||
if(SPI_CRC_TX == 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)
|
||||
\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)
|
||||
\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)
|
||||
\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 SPI NSS pulse mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nssp_mode_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI NSS pulse mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nssp_mode_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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_PHILIPS : I2S philips 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 enable SPI quad wire mode
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_quad_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI quad wire mode
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_quad_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI quad wire mode write
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\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 SPI quad wire mode read
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\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 quad wire mode SPI_IO2 and SPI_IO3 pin output
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\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 quad wire mode SPI_IO2 and SPI_IO3 pin output
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\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 enable SPI and I2S interrupt
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] interrupt: 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)
|
||||
{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI and I2S interrupt
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] interrupt: 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)
|
||||
{
|
||||
SPI_CTL1(spi_periph) &= ~(uint32_t)interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI and I2S interrupt flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] interrupt: SPI/I2S interrupt flag status
|
||||
only one parameter can be selected which is 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;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI and I2S flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] flag: SPI/I2S flag status
|
||||
only one parameter can be selected which is 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,895 @@
|
||||
/*!
|
||||
\file gd32e50x_spi.c
|
||||
\brief SPI driver
|
||||
|
||||
\version 2026-02-09, V1.7.0, firmware for GD32E50x
|
||||
*/
|
||||
|
||||
/*
|
||||
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 "gd32e50x_spi.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 */
|
||||
|
||||
/* I2S clock source selection, multiplication and division mask */
|
||||
#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /*!< I2S1 clock source selection */
|
||||
#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /*!< I2S2 clock source selection */
|
||||
#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /*!< I2S clock multiplication mask */
|
||||
#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /*!< I2S clock division mask */
|
||||
|
||||
/*!
|
||||
\brief reset SPI and I2S
|
||||
\param[in] spi_periph: SPIx(x=0,1,2),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;
|
||||
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)
|
||||
\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)
|
||||
\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)
|
||||
\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_PHILIPS: I2S philips 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 prescaler
|
||||
\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;
|
||||
|
||||
#ifdef GD32E50X_CL
|
||||
uint32_t pll2mf_4 = 0U;
|
||||
#endif /* GD32E50X_CL */
|
||||
|
||||
/* deinit SPI_I2SPSC register */
|
||||
SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE;
|
||||
|
||||
#ifdef GD32E50X_CL
|
||||
/* get the I2S clock source */
|
||||
if(((uint32_t)spi_periph) == SPI1){
|
||||
/* I2S1 clock source selection */
|
||||
clks = I2S1_CLOCK_SEL;
|
||||
}else{
|
||||
/* I2S2 clock source selection */
|
||||
clks = I2S2_CLOCK_SEL;
|
||||
}
|
||||
|
||||
if(0U != (RCU_CFG1 & clks)){
|
||||
/* get RCU PLL2 clock multiplication factor */
|
||||
clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> 12U);
|
||||
|
||||
pll2mf_4 = RCU_CFG1 & RCU_CFG1_PLL2MF_4;
|
||||
|
||||
if( 0U == pll2mf_4){
|
||||
if((clks > 5U) && (clks < 15U)){
|
||||
/* multiplier is between 8 and 16 */
|
||||
clks += 2U;
|
||||
}else{
|
||||
if(15U == clks){
|
||||
/* multiplier is 20 */
|
||||
clks = 20U;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(clks < 15U){
|
||||
/* multiplier is between 18 and 32 */
|
||||
clks += 18U;
|
||||
}else{
|
||||
if(15U == clks){
|
||||
/* multiplier is 40 */
|
||||
clks = 40U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get the PREDV1 value */
|
||||
i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> 4U) + 1U);
|
||||
/* calculate i2sclock based on PLL2 and PREDV1 */
|
||||
i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U);
|
||||
}else{
|
||||
/* get system clock */
|
||||
i2sclock = rcu_clock_freq_get(CK_SYS);
|
||||
}
|
||||
#else
|
||||
/* get system clock */
|
||||
i2sclock = rcu_clock_freq_get(CK_SYS);
|
||||
#endif /* GD32E50X_CL */
|
||||
|
||||
/* 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)
|
||||
\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)
|
||||
\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)
|
||||
\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)
|
||||
\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)
|
||||
\param[in] 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 dma)
|
||||
{
|
||||
if(SPI_DMA_TRANSMIT == dma){
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN;
|
||||
}else{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI DMA send or receive
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] 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 dma)
|
||||
{
|
||||
if(SPI_DMA_TRANSMIT == 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)
|
||||
\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);
|
||||
/* confige 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)
|
||||
\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)
|
||||
\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)
|
||||
\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 clear SPI/I2S format error flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\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)
|
||||
\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)
|
||||
{
|
||||
/* enable SPI CRC */
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
|
||||
|
||||
/* 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)
|
||||
\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 CRC function
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\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 CRC function
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\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)
|
||||
\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)
|
||||
\param[in] 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 crc)
|
||||
{
|
||||
if(SPI_CRC_TX == 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)
|
||||
\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)
|
||||
\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)
|
||||
\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 SPI NSS pulse mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nssp_mode_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI NSS pulse mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nssp_mode_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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_PHILIPS : I2S philips 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 enable SPI quad wire mode
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_quad_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI quad wire mode
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_quad_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI quad wire mode write
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\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 SPI quad wire mode read
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\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 quad wire mode SPI_IO2 and SPI_IO3 pin output
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\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 quad wire mode SPI_IO2 and SPI_IO3 pin output
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\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 enable SPI and I2S interrupt
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] interrupt: 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)
|
||||
{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI and I2S interrupt
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] interrupt: 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)
|
||||
{
|
||||
SPI_CTL1(spi_periph) &= ~(uint32_t)interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI and I2S interrupt flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] interrupt: SPI/I2S interrupt flag status
|
||||
only one parameter can be selected which is 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;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI and I2S flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] flag: SPI/I2S flag status
|
||||
only one parameter can be selected which is 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,101 @@
|
||||
#ifndef REGIONS_GD32E508VE_H
|
||||
#define REGIONS_GD32E508VE_H
|
||||
|
||||
|
||||
//-------- <<< Use Configuration Wizard in Context Menu >>> --------------------
|
||||
//------ With VS Code: Open Preview for Configuration Wizard -------------------
|
||||
|
||||
// <n> Auto-generated using information from packs
|
||||
// <i> Device Family Pack (DFP): GigaDevice::GD32E50x_DFP@1.9.0
|
||||
|
||||
// <h> ROM Configuration
|
||||
// =======================
|
||||
// <h> __ROM0 (is rx memory: IROM1 from DFP)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region. Default: 0x08000000
|
||||
// <i> Contains Startup and Vector Table
|
||||
#define __ROM0_BASE 0x08000000
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region. Default: 0x00080000
|
||||
#define __ROM0_SIZE 0x00080000
|
||||
// </h>
|
||||
|
||||
// <h> __ROM1 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __ROM1_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __ROM1_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// <h> __ROM2 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __ROM2_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __ROM2_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// <h> __ROM3 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __ROM3_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __ROM3_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// </h>
|
||||
|
||||
// <h> RAM Configuration
|
||||
// =======================
|
||||
// <h> __RAM0 (is rwx memory: IRAM1 from DFP)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region. Default: 0x20000000
|
||||
// <i> Contains uninitialized RAM, Stack, and Heap
|
||||
#define __RAM0_BASE 0x20000000
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region. Default: 0x00020000
|
||||
#define __RAM0_SIZE 0x00020000
|
||||
// </h>
|
||||
|
||||
// <h> __RAM1 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __RAM1_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __RAM1_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// <h> __RAM2 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __RAM2_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __RAM2_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// <h> __RAM3 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __RAM3_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __RAM3_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// </h>
|
||||
|
||||
// <h> Stack / Heap Configuration
|
||||
// <o0> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
// <o1> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
#define __STACK_SIZE 0x00000200
|
||||
#define __HEAP_SIZE 0x00000C00
|
||||
// </h>
|
||||
|
||||
|
||||
#endif /* REGIONS_GD32E508VE_H */
|
||||
@@ -0,0 +1,434 @@
|
||||
;/*!
|
||||
; \file startup_gd32e50x_cl.s
|
||||
; \brief start up file
|
||||
;
|
||||
; \version 2025-07-09, V1.6.1, firmware for GD32E50x
|
||||
;*/
|
||||
;
|
||||
;/*
|
||||
; * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
|
||||
; * Copyright (c) 2023, GigaDevice Semiconductor Inc.
|
||||
; *
|
||||
; * SPDX-License-Identifier: Apache-2.0
|
||||
; *
|
||||
; * Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
; * not use this file except in compliance with the License.
|
||||
; * You may obtain a copy of the License at
|
||||
; *
|
||||
; * www.apache.org/licenses/LICENSE-2.0
|
||||
; *
|
||||
; * Unless required by applicable law or agreed to in writing, software
|
||||
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
; * See the License for the specific language governing permissions and
|
||||
; * limitations under the License.
|
||||
; */
|
||||
;/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
|
||||
|
||||
|
||||
; <h> Stack Configuration
|
||||
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
Stack_Size EQU 0x00000800
|
||||
|
||||
AREA STACK, NOINIT, READWRITE, ALIGN=3
|
||||
Stack_Mem SPACE Stack_Size
|
||||
__initial_sp
|
||||
|
||||
|
||||
; <h> Heap Configuration
|
||||
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
Heap_Size EQU 0x00000400
|
||||
|
||||
AREA HEAP, NOINIT, READWRITE, ALIGN=3
|
||||
__heap_base
|
||||
Heap_Mem SPACE Heap_Size
|
||||
__heap_limit
|
||||
|
||||
PRESERVE8
|
||||
THUMB
|
||||
|
||||
; /* reset Vector Mapped to at Address 0 */
|
||||
AREA RESET, DATA, READONLY
|
||||
EXPORT __Vectors
|
||||
EXPORT __Vectors_End
|
||||
EXPORT __Vectors_Size
|
||||
|
||||
__Vectors DCD __initial_sp ; Top of Stack
|
||||
DCD Reset_Handler ; Reset Handler
|
||||
DCD NMI_Handler ; NMI Handler
|
||||
DCD HardFault_Handler ; Hard Fault Handler
|
||||
DCD MemManage_Handler ; MPU Fault Handler
|
||||
DCD BusFault_Handler ; Bus Fault Handler
|
||||
DCD UsageFault_Handler ; Usage Fault Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD SVC_Handler ; SVCall Handler
|
||||
DCD DebugMon_Handler ; Debug Monitor Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD PendSV_Handler ; PendSV Handler
|
||||
DCD SysTick_Handler ; SysTick Handler
|
||||
|
||||
; /* external interrupts handler */
|
||||
DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer
|
||||
DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect
|
||||
DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect
|
||||
DCD RTC_IRQHandler ; 19:RTC through EXTI Line
|
||||
DCD FMC_IRQHandler ; 20:FMC
|
||||
DCD RCU_CTC_IRQHandler ; 21:RCU and CTC
|
||||
DCD EXTI0_IRQHandler ; 22:EXTI Line 0
|
||||
DCD EXTI1_IRQHandler ; 23:EXTI Line 1
|
||||
DCD EXTI2_IRQHandler ; 24:EXTI Line 2
|
||||
DCD EXTI3_IRQHandler ; 25:EXTI Line 3
|
||||
DCD EXTI4_IRQHandler ; 26:EXTI Line 4
|
||||
DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0
|
||||
DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1
|
||||
DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2
|
||||
DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3
|
||||
DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4
|
||||
DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5
|
||||
DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6
|
||||
DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1
|
||||
DCD CAN0_TX_IRQHandler ; 35:CAN0 TX
|
||||
DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0
|
||||
DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1
|
||||
DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC
|
||||
DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9
|
||||
DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8
|
||||
DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9
|
||||
DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10
|
||||
DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare
|
||||
DCD TIMER1_IRQHandler ; 44:TIMER1
|
||||
DCD TIMER2_IRQHandler ; 45:TIMER2
|
||||
DCD TIMER3_IRQHandler ; 46:TIMER3
|
||||
DCD I2C0_EV_IRQHandler ; 47:I2C0 Event
|
||||
DCD I2C0_ER_IRQHandler ; 48:I2C0 Error
|
||||
DCD I2C1_EV_IRQHandler ; 49:I2C1 Event
|
||||
DCD I2C1_ER_IRQHandler ; 50:I2C1 Error
|
||||
DCD SPI0_IRQHandler ; 51:SPI0
|
||||
DCD SPI1_I2S1ADD_IRQHandler ; 52:SPI1 or I2S1ADD
|
||||
DCD USART0_IRQHandler ; 53:USART0
|
||||
DCD USART1_IRQHandler ; 54:USART1
|
||||
DCD USART2_IRQHandler ; 55:USART2
|
||||
DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15
|
||||
DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm
|
||||
DCD USBHS_WKUP_IRQHandler ; 58:USBHS Wakeup
|
||||
DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11
|
||||
DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12
|
||||
DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13
|
||||
DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare
|
||||
DCD 0 ; Reserved
|
||||
DCD EXMC_IRQHandler ; 64:EXMC
|
||||
DCD 0 ; Reserved
|
||||
DCD TIMER4_IRQHandler ; 66:TIMER4
|
||||
DCD SPI2_I2S2ADD_IRQHandler ; 67:SPI2 or I2S2ADD
|
||||
DCD UART3_IRQHandler ; 68:UART3
|
||||
DCD UART4_IRQHandler ; 69:UART4
|
||||
DCD TIMER5_DAC_IRQHandler ; 70:TIMER5 or DAC
|
||||
DCD TIMER6_IRQHandler ; 71:TIMER6
|
||||
DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0
|
||||
DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1
|
||||
DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2
|
||||
DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3
|
||||
DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4
|
||||
DCD ENET_IRQHandler ; 77:Ethernet
|
||||
DCD ENET_WKUP_IRQHandler ; 78:Ethernet Wakeup through EXTI Line
|
||||
DCD CAN1_TX_IRQHandler ; 79:CAN1 TX
|
||||
DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0
|
||||
DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1
|
||||
DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC
|
||||
DCD USBHS_IRQHandler ; 83:USBHS
|
||||
DCD 0 ; Reserved
|
||||
DCD SHRTIMER_IRQ2_IRQHandler ; 85:SHRTIMER IRQ2
|
||||
DCD SHRTIMER_IRQ3_IRQHandler ; 86:SHRTIMER IRQ3
|
||||
DCD SHRTIMER_IRQ4_IRQHandler ; 87:SHRTIMER IRQ4
|
||||
DCD SHRTIMER_IRQ5_IRQHandler ; 88:SHRTIMER IRQ5
|
||||
DCD SHRTIMER_IRQ6_IRQHandler ; 89:SHRTIMER IRQ6
|
||||
DCD USBHS_EP1_OUT_IRQHandler ; 90:USBHS end point 1 out
|
||||
DCD USBHS_EP1_IN_IRQHandler ; 91:USBHS end point 1 in
|
||||
DCD SHRTIMER_IRQ0_IRQHandler ; 92:SHRTIMER IRQ0
|
||||
DCD SHRTIMER_IRQ1_IRQHandler ; 93:SHRTIMER IRQ1
|
||||
DCD CAN2_TX_IRQHandler ; 94:CAN2 TX
|
||||
DCD CAN2_RX0_IRQHandler ; 95:CAN2 RX0
|
||||
DCD CAN2_RX1_IRQHandler ; 96:CAN2 RX1
|
||||
DCD CAN2_EWMC_IRQHandler ; 97:CAN2 EWMC
|
||||
DCD I2C2_EV_IRQHandler ; 98:I2C2 Event
|
||||
DCD I2C2_ER_IRQHandler ; 99:I2C2 Error
|
||||
DCD USART5_IRQHandler ; 100:USART5
|
||||
DCD I2C2_WKUP_IRQHandler ; 101:I2C2 Wakeup
|
||||
DCD USART5_WKUP_IRQHandler ; 102:USART5 Wakeup
|
||||
DCD TMU_IRQHandler ; 103:TMU
|
||||
|
||||
__Vectors_End
|
||||
|
||||
__Vectors_Size EQU __Vectors_End - __Vectors
|
||||
|
||||
AREA |.text|, CODE, READONLY
|
||||
|
||||
;/* reset Handler */
|
||||
Reset_Handler PROC
|
||||
EXPORT Reset_Handler [WEAK]
|
||||
IMPORT SystemInit
|
||||
IMPORT __main
|
||||
LDR R0, =SystemInit
|
||||
BLX R0
|
||||
LDR R0, =__main
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
;/* dummy Exception Handlers */
|
||||
NMI_Handler PROC
|
||||
EXPORT NMI_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
HardFault_Handler\
|
||||
PROC
|
||||
EXPORT HardFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
MemManage_Handler\
|
||||
PROC
|
||||
EXPORT MemManage_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
BusFault_Handler\
|
||||
PROC
|
||||
EXPORT BusFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
UsageFault_Handler\
|
||||
PROC
|
||||
EXPORT UsageFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SVC_Handler PROC
|
||||
EXPORT SVC_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
DebugMon_Handler\
|
||||
PROC
|
||||
EXPORT DebugMon_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
PendSV_Handler\
|
||||
PROC
|
||||
EXPORT PendSV_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SysTick_Handler\
|
||||
PROC
|
||||
EXPORT SysTick_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
Default_Handler PROC
|
||||
; /* external interrupts handler */
|
||||
EXPORT WWDGT_IRQHandler [WEAK]
|
||||
EXPORT LVD_IRQHandler [WEAK]
|
||||
EXPORT TAMPER_IRQHandler [WEAK]
|
||||
EXPORT RTC_IRQHandler [WEAK]
|
||||
EXPORT FMC_IRQHandler [WEAK]
|
||||
EXPORT RCU_CTC_IRQHandler [WEAK]
|
||||
EXPORT EXTI0_IRQHandler [WEAK]
|
||||
EXPORT EXTI1_IRQHandler [WEAK]
|
||||
EXPORT EXTI2_IRQHandler [WEAK]
|
||||
EXPORT EXTI3_IRQHandler [WEAK]
|
||||
EXPORT EXTI4_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel0_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel1_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel2_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel3_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel4_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel5_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel6_IRQHandler [WEAK]
|
||||
EXPORT ADC0_1_IRQHandler [WEAK]
|
||||
EXPORT CAN0_TX_IRQHandler [WEAK]
|
||||
EXPORT CAN0_RX0_IRQHandler [WEAK]
|
||||
EXPORT CAN0_RX1_IRQHandler [WEAK]
|
||||
EXPORT CAN0_EWMC_IRQHandler [WEAK]
|
||||
EXPORT EXTI5_9_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_Channel_IRQHandler [WEAK]
|
||||
EXPORT TIMER1_IRQHandler [WEAK]
|
||||
EXPORT TIMER2_IRQHandler [WEAK]
|
||||
EXPORT TIMER3_IRQHandler [WEAK]
|
||||
EXPORT I2C0_EV_IRQHandler [WEAK]
|
||||
EXPORT I2C0_ER_IRQHandler [WEAK]
|
||||
EXPORT I2C1_EV_IRQHandler [WEAK]
|
||||
EXPORT I2C1_ER_IRQHandler [WEAK]
|
||||
EXPORT SPI0_IRQHandler [WEAK]
|
||||
EXPORT SPI1_I2S1ADD_IRQHandler [WEAK]
|
||||
EXPORT USART0_IRQHandler [WEAK]
|
||||
EXPORT USART1_IRQHandler [WEAK]
|
||||
EXPORT USART2_IRQHandler [WEAK]
|
||||
EXPORT EXTI10_15_IRQHandler [WEAK]
|
||||
EXPORT RTC_Alarm_IRQHandler [WEAK]
|
||||
EXPORT USBHS_WKUP_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_Channel_IRQHandler [WEAK]
|
||||
EXPORT EXMC_IRQHandler [WEAK]
|
||||
EXPORT TIMER4_IRQHandler [WEAK]
|
||||
EXPORT SPI2_I2S2ADD_IRQHandler [WEAK]
|
||||
EXPORT UART3_IRQHandler [WEAK]
|
||||
EXPORT UART4_IRQHandler [WEAK]
|
||||
EXPORT TIMER5_DAC_IRQHandler [WEAK]
|
||||
EXPORT TIMER6_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel0_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel1_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel2_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel3_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel4_IRQHandler [WEAK]
|
||||
EXPORT ENET_IRQHandler [WEAK]
|
||||
EXPORT ENET_WKUP_IRQHandler [WEAK]
|
||||
EXPORT CAN1_TX_IRQHandler [WEAK]
|
||||
EXPORT CAN1_RX0_IRQHandler [WEAK]
|
||||
EXPORT CAN1_RX1_IRQHandler [WEAK]
|
||||
EXPORT CAN1_EWMC_IRQHandler [WEAK]
|
||||
EXPORT USBHS_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ2_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ3_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ4_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ5_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ6_IRQHandler [WEAK]
|
||||
EXPORT USBHS_EP1_OUT_IRQHandler [WEAK]
|
||||
EXPORT USBHS_EP1_IN_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ0_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ1_IRQHandler [WEAK]
|
||||
EXPORT CAN2_TX_IRQHandler [WEAK]
|
||||
EXPORT CAN2_RX0_IRQHandler [WEAK]
|
||||
EXPORT CAN2_RX1_IRQHandler [WEAK]
|
||||
EXPORT CAN2_EWMC_IRQHandler [WEAK]
|
||||
EXPORT I2C2_EV_IRQHandler [WEAK]
|
||||
EXPORT I2C2_ER_IRQHandler [WEAK]
|
||||
EXPORT USART5_IRQHandler [WEAK]
|
||||
EXPORT I2C2_WKUP_IRQHandler [WEAK]
|
||||
EXPORT USART5_WKUP_IRQHandler [WEAK]
|
||||
EXPORT TMU_IRQHandler [WEAK]
|
||||
|
||||
;/* external interrupts handler */
|
||||
WWDGT_IRQHandler
|
||||
LVD_IRQHandler
|
||||
TAMPER_IRQHandler
|
||||
RTC_IRQHandler
|
||||
FMC_IRQHandler
|
||||
RCU_CTC_IRQHandler
|
||||
EXTI0_IRQHandler
|
||||
EXTI1_IRQHandler
|
||||
EXTI2_IRQHandler
|
||||
EXTI3_IRQHandler
|
||||
EXTI4_IRQHandler
|
||||
DMA0_Channel0_IRQHandler
|
||||
DMA0_Channel1_IRQHandler
|
||||
DMA0_Channel2_IRQHandler
|
||||
DMA0_Channel3_IRQHandler
|
||||
DMA0_Channel4_IRQHandler
|
||||
DMA0_Channel5_IRQHandler
|
||||
DMA0_Channel6_IRQHandler
|
||||
ADC0_1_IRQHandler
|
||||
CAN0_TX_IRQHandler
|
||||
CAN0_RX0_IRQHandler
|
||||
CAN0_RX1_IRQHandler
|
||||
CAN0_EWMC_IRQHandler
|
||||
EXTI5_9_IRQHandler
|
||||
TIMER0_BRK_TIMER8_IRQHandler
|
||||
TIMER0_UP_TIMER9_IRQHandler
|
||||
TIMER0_TRG_CMT_TIMER10_IRQHandler
|
||||
TIMER0_Channel_IRQHandler
|
||||
TIMER1_IRQHandler
|
||||
TIMER2_IRQHandler
|
||||
TIMER3_IRQHandler
|
||||
I2C0_EV_IRQHandler
|
||||
I2C0_ER_IRQHandler
|
||||
I2C1_EV_IRQHandler
|
||||
I2C1_ER_IRQHandler
|
||||
SPI0_IRQHandler
|
||||
SPI1_I2S1ADD_IRQHandler
|
||||
USART0_IRQHandler
|
||||
USART1_IRQHandler
|
||||
USART2_IRQHandler
|
||||
EXTI10_15_IRQHandler
|
||||
RTC_Alarm_IRQHandler
|
||||
USBHS_WKUP_IRQHandler
|
||||
TIMER7_BRK_TIMER11_IRQHandler
|
||||
TIMER7_UP_TIMER12_IRQHandler
|
||||
TIMER7_TRG_CMT_TIMER13_IRQHandler
|
||||
TIMER7_Channel_IRQHandler
|
||||
EXMC_IRQHandler
|
||||
TIMER4_IRQHandler
|
||||
SPI2_I2S2ADD_IRQHandler
|
||||
UART3_IRQHandler
|
||||
UART4_IRQHandler
|
||||
TIMER5_DAC_IRQHandler
|
||||
TIMER6_IRQHandler
|
||||
DMA1_Channel0_IRQHandler
|
||||
DMA1_Channel1_IRQHandler
|
||||
DMA1_Channel2_IRQHandler
|
||||
DMA1_Channel3_IRQHandler
|
||||
DMA1_Channel4_IRQHandler
|
||||
ENET_IRQHandler
|
||||
ENET_WKUP_IRQHandler
|
||||
CAN1_TX_IRQHandler
|
||||
CAN1_RX0_IRQHandler
|
||||
CAN1_RX1_IRQHandler
|
||||
CAN1_EWMC_IRQHandler
|
||||
USBHS_IRQHandler
|
||||
SHRTIMER_IRQ2_IRQHandler
|
||||
SHRTIMER_IRQ3_IRQHandler
|
||||
SHRTIMER_IRQ4_IRQHandler
|
||||
SHRTIMER_IRQ5_IRQHandler
|
||||
SHRTIMER_IRQ6_IRQHandler
|
||||
USBHS_EP1_OUT_IRQHandler
|
||||
USBHS_EP1_IN_IRQHandler
|
||||
SHRTIMER_IRQ0_IRQHandler
|
||||
SHRTIMER_IRQ1_IRQHandler
|
||||
CAN2_TX_IRQHandler
|
||||
CAN2_RX0_IRQHandler
|
||||
CAN2_RX1_IRQHandler
|
||||
CAN2_EWMC_IRQHandler
|
||||
I2C2_EV_IRQHandler
|
||||
I2C2_ER_IRQHandler
|
||||
USART5_IRQHandler
|
||||
I2C2_WKUP_IRQHandler
|
||||
USART5_WKUP_IRQHandler
|
||||
TMU_IRQHandler
|
||||
|
||||
B .
|
||||
ENDP
|
||||
|
||||
ALIGN
|
||||
|
||||
; user Initial Stack & Heap
|
||||
|
||||
IF :DEF:__MICROLIB
|
||||
|
||||
EXPORT __initial_sp
|
||||
EXPORT __heap_base
|
||||
EXPORT __heap_limit
|
||||
|
||||
ELSE
|
||||
|
||||
IMPORT __use_two_region_memory
|
||||
EXPORT __user_initial_stackheap
|
||||
|
||||
__user_initial_stackheap PROC
|
||||
LDR R0, = Heap_Mem
|
||||
LDR R1, =(Stack_Mem + Stack_Size)
|
||||
LDR R2, = (Heap_Mem + Heap_Size)
|
||||
LDR R3, = Stack_Mem
|
||||
BX LR
|
||||
ENDP
|
||||
|
||||
ALIGN
|
||||
|
||||
ENDIF
|
||||
|
||||
END
|
||||
@@ -0,0 +1,434 @@
|
||||
;/*!
|
||||
; \file startup_gd32e50x_cl.s
|
||||
; \brief start up file
|
||||
;
|
||||
; \version 2025-07-09, V1.6.1, firmware for GD32E50x
|
||||
;*/
|
||||
;
|
||||
;/*
|
||||
; * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
|
||||
; * Copyright (c) 2023, GigaDevice Semiconductor Inc.
|
||||
; *
|
||||
; * SPDX-License-Identifier: Apache-2.0
|
||||
; *
|
||||
; * Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
; * not use this file except in compliance with the License.
|
||||
; * You may obtain a copy of the License at
|
||||
; *
|
||||
; * www.apache.org/licenses/LICENSE-2.0
|
||||
; *
|
||||
; * Unless required by applicable law or agreed to in writing, software
|
||||
; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
; * See the License for the specific language governing permissions and
|
||||
; * limitations under the License.
|
||||
; */
|
||||
;/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
|
||||
|
||||
|
||||
; <h> Stack Configuration
|
||||
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
Stack_Size EQU 0x00000800
|
||||
|
||||
AREA STACK, NOINIT, READWRITE, ALIGN=3
|
||||
Stack_Mem SPACE Stack_Size
|
||||
__initial_sp
|
||||
|
||||
|
||||
; <h> Heap Configuration
|
||||
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
Heap_Size EQU 0x00000400
|
||||
|
||||
AREA HEAP, NOINIT, READWRITE, ALIGN=3
|
||||
__heap_base
|
||||
Heap_Mem SPACE Heap_Size
|
||||
__heap_limit
|
||||
|
||||
PRESERVE8
|
||||
THUMB
|
||||
|
||||
; /* reset Vector Mapped to at Address 0 */
|
||||
AREA RESET, DATA, READONLY
|
||||
EXPORT __Vectors
|
||||
EXPORT __Vectors_End
|
||||
EXPORT __Vectors_Size
|
||||
|
||||
__Vectors DCD __initial_sp ; Top of Stack
|
||||
DCD Reset_Handler ; Reset Handler
|
||||
DCD NMI_Handler ; NMI Handler
|
||||
DCD HardFault_Handler ; Hard Fault Handler
|
||||
DCD MemManage_Handler ; MPU Fault Handler
|
||||
DCD BusFault_Handler ; Bus Fault Handler
|
||||
DCD UsageFault_Handler ; Usage Fault Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD SVC_Handler ; SVCall Handler
|
||||
DCD DebugMon_Handler ; Debug Monitor Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD PendSV_Handler ; PendSV Handler
|
||||
DCD SysTick_Handler ; SysTick Handler
|
||||
|
||||
; /* external interrupts handler */
|
||||
DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer
|
||||
DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect
|
||||
DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect
|
||||
DCD RTC_IRQHandler ; 19:RTC through EXTI Line
|
||||
DCD FMC_IRQHandler ; 20:FMC
|
||||
DCD RCU_CTC_IRQHandler ; 21:RCU and CTC
|
||||
DCD EXTI0_IRQHandler ; 22:EXTI Line 0
|
||||
DCD EXTI1_IRQHandler ; 23:EXTI Line 1
|
||||
DCD EXTI2_IRQHandler ; 24:EXTI Line 2
|
||||
DCD EXTI3_IRQHandler ; 25:EXTI Line 3
|
||||
DCD EXTI4_IRQHandler ; 26:EXTI Line 4
|
||||
DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0
|
||||
DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1
|
||||
DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2
|
||||
DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3
|
||||
DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4
|
||||
DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5
|
||||
DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6
|
||||
DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1
|
||||
DCD CAN0_TX_IRQHandler ; 35:CAN0 TX
|
||||
DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0
|
||||
DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1
|
||||
DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC
|
||||
DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9
|
||||
DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8
|
||||
DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9
|
||||
DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10
|
||||
DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare
|
||||
DCD TIMER1_IRQHandler ; 44:TIMER1
|
||||
DCD TIMER2_IRQHandler ; 45:TIMER2
|
||||
DCD TIMER3_IRQHandler ; 46:TIMER3
|
||||
DCD I2C0_EV_IRQHandler ; 47:I2C0 Event
|
||||
DCD I2C0_ER_IRQHandler ; 48:I2C0 Error
|
||||
DCD I2C1_EV_IRQHandler ; 49:I2C1 Event
|
||||
DCD I2C1_ER_IRQHandler ; 50:I2C1 Error
|
||||
DCD SPI0_IRQHandler ; 51:SPI0
|
||||
DCD SPI1_I2S1ADD_IRQHandler ; 52:SPI1 or I2S1ADD
|
||||
DCD USART0_IRQHandler ; 53:USART0
|
||||
DCD USART1_IRQHandler ; 54:USART1
|
||||
DCD USART2_IRQHandler ; 55:USART2
|
||||
DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15
|
||||
DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm
|
||||
DCD USBHS_WKUP_IRQHandler ; 58:USBHS Wakeup
|
||||
DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11
|
||||
DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12
|
||||
DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13
|
||||
DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare
|
||||
DCD 0 ; Reserved
|
||||
DCD EXMC_IRQHandler ; 64:EXMC
|
||||
DCD 0 ; Reserved
|
||||
DCD TIMER4_IRQHandler ; 66:TIMER4
|
||||
DCD SPI2_I2S2ADD_IRQHandler ; 67:SPI2 or I2S2ADD
|
||||
DCD UART3_IRQHandler ; 68:UART3
|
||||
DCD UART4_IRQHandler ; 69:UART4
|
||||
DCD TIMER5_DAC_IRQHandler ; 70:TIMER5 or DAC
|
||||
DCD TIMER6_IRQHandler ; 71:TIMER6
|
||||
DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0
|
||||
DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1
|
||||
DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2
|
||||
DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3
|
||||
DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4
|
||||
DCD ENET_IRQHandler ; 77:Ethernet
|
||||
DCD ENET_WKUP_IRQHandler ; 78:Ethernet Wakeup through EXTI Line
|
||||
DCD CAN1_TX_IRQHandler ; 79:CAN1 TX
|
||||
DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0
|
||||
DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1
|
||||
DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC
|
||||
DCD USBHS_IRQHandler ; 83:USBHS
|
||||
DCD 0 ; Reserved
|
||||
DCD SHRTIMER_IRQ2_IRQHandler ; 85:SHRTIMER IRQ2
|
||||
DCD SHRTIMER_IRQ3_IRQHandler ; 86:SHRTIMER IRQ3
|
||||
DCD SHRTIMER_IRQ4_IRQHandler ; 87:SHRTIMER IRQ4
|
||||
DCD SHRTIMER_IRQ5_IRQHandler ; 88:SHRTIMER IRQ5
|
||||
DCD SHRTIMER_IRQ6_IRQHandler ; 89:SHRTIMER IRQ6
|
||||
DCD USBHS_EP1_OUT_IRQHandler ; 90:USBHS end point 1 out
|
||||
DCD USBHS_EP1_IN_IRQHandler ; 91:USBHS end point 1 in
|
||||
DCD SHRTIMER_IRQ0_IRQHandler ; 92:SHRTIMER IRQ0
|
||||
DCD SHRTIMER_IRQ1_IRQHandler ; 93:SHRTIMER IRQ1
|
||||
DCD CAN2_TX_IRQHandler ; 94:CAN2 TX
|
||||
DCD CAN2_RX0_IRQHandler ; 95:CAN2 RX0
|
||||
DCD CAN2_RX1_IRQHandler ; 96:CAN2 RX1
|
||||
DCD CAN2_EWMC_IRQHandler ; 97:CAN2 EWMC
|
||||
DCD I2C2_EV_IRQHandler ; 98:I2C2 Event
|
||||
DCD I2C2_ER_IRQHandler ; 99:I2C2 Error
|
||||
DCD USART5_IRQHandler ; 100:USART5
|
||||
DCD I2C2_WKUP_IRQHandler ; 101:I2C2 Wakeup
|
||||
DCD USART5_WKUP_IRQHandler ; 102:USART5 Wakeup
|
||||
DCD TMU_IRQHandler ; 103:TMU
|
||||
|
||||
__Vectors_End
|
||||
|
||||
__Vectors_Size EQU __Vectors_End - __Vectors
|
||||
|
||||
AREA |.text|, CODE, READONLY
|
||||
|
||||
;/* reset Handler */
|
||||
Reset_Handler PROC
|
||||
EXPORT Reset_Handler [WEAK]
|
||||
IMPORT SystemInit
|
||||
IMPORT __main
|
||||
LDR R0, =SystemInit
|
||||
BLX R0
|
||||
LDR R0, =__main
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
;/* dummy Exception Handlers */
|
||||
NMI_Handler PROC
|
||||
EXPORT NMI_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
HardFault_Handler\
|
||||
PROC
|
||||
EXPORT HardFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
MemManage_Handler\
|
||||
PROC
|
||||
EXPORT MemManage_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
BusFault_Handler\
|
||||
PROC
|
||||
EXPORT BusFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
UsageFault_Handler\
|
||||
PROC
|
||||
EXPORT UsageFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SVC_Handler PROC
|
||||
EXPORT SVC_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
DebugMon_Handler\
|
||||
PROC
|
||||
EXPORT DebugMon_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
PendSV_Handler\
|
||||
PROC
|
||||
EXPORT PendSV_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SysTick_Handler\
|
||||
PROC
|
||||
EXPORT SysTick_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
Default_Handler PROC
|
||||
; /* external interrupts handler */
|
||||
EXPORT WWDGT_IRQHandler [WEAK]
|
||||
EXPORT LVD_IRQHandler [WEAK]
|
||||
EXPORT TAMPER_IRQHandler [WEAK]
|
||||
EXPORT RTC_IRQHandler [WEAK]
|
||||
EXPORT FMC_IRQHandler [WEAK]
|
||||
EXPORT RCU_CTC_IRQHandler [WEAK]
|
||||
EXPORT EXTI0_IRQHandler [WEAK]
|
||||
EXPORT EXTI1_IRQHandler [WEAK]
|
||||
EXPORT EXTI2_IRQHandler [WEAK]
|
||||
EXPORT EXTI3_IRQHandler [WEAK]
|
||||
EXPORT EXTI4_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel0_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel1_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel2_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel3_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel4_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel5_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel6_IRQHandler [WEAK]
|
||||
EXPORT ADC0_1_IRQHandler [WEAK]
|
||||
EXPORT CAN0_TX_IRQHandler [WEAK]
|
||||
EXPORT CAN0_RX0_IRQHandler [WEAK]
|
||||
EXPORT CAN0_RX1_IRQHandler [WEAK]
|
||||
EXPORT CAN0_EWMC_IRQHandler [WEAK]
|
||||
EXPORT EXTI5_9_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_Channel_IRQHandler [WEAK]
|
||||
EXPORT TIMER1_IRQHandler [WEAK]
|
||||
EXPORT TIMER2_IRQHandler [WEAK]
|
||||
EXPORT TIMER3_IRQHandler [WEAK]
|
||||
EXPORT I2C0_EV_IRQHandler [WEAK]
|
||||
EXPORT I2C0_ER_IRQHandler [WEAK]
|
||||
EXPORT I2C1_EV_IRQHandler [WEAK]
|
||||
EXPORT I2C1_ER_IRQHandler [WEAK]
|
||||
EXPORT SPI0_IRQHandler [WEAK]
|
||||
EXPORT SPI1_I2S1ADD_IRQHandler [WEAK]
|
||||
EXPORT USART0_IRQHandler [WEAK]
|
||||
EXPORT USART1_IRQHandler [WEAK]
|
||||
EXPORT USART2_IRQHandler [WEAK]
|
||||
EXPORT EXTI10_15_IRQHandler [WEAK]
|
||||
EXPORT RTC_Alarm_IRQHandler [WEAK]
|
||||
EXPORT USBHS_WKUP_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_Channel_IRQHandler [WEAK]
|
||||
EXPORT EXMC_IRQHandler [WEAK]
|
||||
EXPORT TIMER4_IRQHandler [WEAK]
|
||||
EXPORT SPI2_I2S2ADD_IRQHandler [WEAK]
|
||||
EXPORT UART3_IRQHandler [WEAK]
|
||||
EXPORT UART4_IRQHandler [WEAK]
|
||||
EXPORT TIMER5_DAC_IRQHandler [WEAK]
|
||||
EXPORT TIMER6_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel0_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel1_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel2_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel3_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel4_IRQHandler [WEAK]
|
||||
EXPORT ENET_IRQHandler [WEAK]
|
||||
EXPORT ENET_WKUP_IRQHandler [WEAK]
|
||||
EXPORT CAN1_TX_IRQHandler [WEAK]
|
||||
EXPORT CAN1_RX0_IRQHandler [WEAK]
|
||||
EXPORT CAN1_RX1_IRQHandler [WEAK]
|
||||
EXPORT CAN1_EWMC_IRQHandler [WEAK]
|
||||
EXPORT USBHS_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ2_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ3_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ4_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ5_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ6_IRQHandler [WEAK]
|
||||
EXPORT USBHS_EP1_OUT_IRQHandler [WEAK]
|
||||
EXPORT USBHS_EP1_IN_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ0_IRQHandler [WEAK]
|
||||
EXPORT SHRTIMER_IRQ1_IRQHandler [WEAK]
|
||||
EXPORT CAN2_TX_IRQHandler [WEAK]
|
||||
EXPORT CAN2_RX0_IRQHandler [WEAK]
|
||||
EXPORT CAN2_RX1_IRQHandler [WEAK]
|
||||
EXPORT CAN2_EWMC_IRQHandler [WEAK]
|
||||
EXPORT I2C2_EV_IRQHandler [WEAK]
|
||||
EXPORT I2C2_ER_IRQHandler [WEAK]
|
||||
EXPORT USART5_IRQHandler [WEAK]
|
||||
EXPORT I2C2_WKUP_IRQHandler [WEAK]
|
||||
EXPORT USART5_WKUP_IRQHandler [WEAK]
|
||||
EXPORT TMU_IRQHandler [WEAK]
|
||||
|
||||
;/* external interrupts handler */
|
||||
WWDGT_IRQHandler
|
||||
LVD_IRQHandler
|
||||
TAMPER_IRQHandler
|
||||
RTC_IRQHandler
|
||||
FMC_IRQHandler
|
||||
RCU_CTC_IRQHandler
|
||||
EXTI0_IRQHandler
|
||||
EXTI1_IRQHandler
|
||||
EXTI2_IRQHandler
|
||||
EXTI3_IRQHandler
|
||||
EXTI4_IRQHandler
|
||||
DMA0_Channel0_IRQHandler
|
||||
DMA0_Channel1_IRQHandler
|
||||
DMA0_Channel2_IRQHandler
|
||||
DMA0_Channel3_IRQHandler
|
||||
DMA0_Channel4_IRQHandler
|
||||
DMA0_Channel5_IRQHandler
|
||||
DMA0_Channel6_IRQHandler
|
||||
ADC0_1_IRQHandler
|
||||
CAN0_TX_IRQHandler
|
||||
CAN0_RX0_IRQHandler
|
||||
CAN0_RX1_IRQHandler
|
||||
CAN0_EWMC_IRQHandler
|
||||
EXTI5_9_IRQHandler
|
||||
TIMER0_BRK_TIMER8_IRQHandler
|
||||
TIMER0_UP_TIMER9_IRQHandler
|
||||
TIMER0_TRG_CMT_TIMER10_IRQHandler
|
||||
TIMER0_Channel_IRQHandler
|
||||
TIMER1_IRQHandler
|
||||
TIMER2_IRQHandler
|
||||
TIMER3_IRQHandler
|
||||
I2C0_EV_IRQHandler
|
||||
I2C0_ER_IRQHandler
|
||||
I2C1_EV_IRQHandler
|
||||
I2C1_ER_IRQHandler
|
||||
SPI0_IRQHandler
|
||||
SPI1_I2S1ADD_IRQHandler
|
||||
USART0_IRQHandler
|
||||
USART1_IRQHandler
|
||||
USART2_IRQHandler
|
||||
EXTI10_15_IRQHandler
|
||||
RTC_Alarm_IRQHandler
|
||||
USBHS_WKUP_IRQHandler
|
||||
TIMER7_BRK_TIMER11_IRQHandler
|
||||
TIMER7_UP_TIMER12_IRQHandler
|
||||
TIMER7_TRG_CMT_TIMER13_IRQHandler
|
||||
TIMER7_Channel_IRQHandler
|
||||
EXMC_IRQHandler
|
||||
TIMER4_IRQHandler
|
||||
SPI2_I2S2ADD_IRQHandler
|
||||
UART3_IRQHandler
|
||||
UART4_IRQHandler
|
||||
TIMER5_DAC_IRQHandler
|
||||
TIMER6_IRQHandler
|
||||
DMA1_Channel0_IRQHandler
|
||||
DMA1_Channel1_IRQHandler
|
||||
DMA1_Channel2_IRQHandler
|
||||
DMA1_Channel3_IRQHandler
|
||||
DMA1_Channel4_IRQHandler
|
||||
ENET_IRQHandler
|
||||
ENET_WKUP_IRQHandler
|
||||
CAN1_TX_IRQHandler
|
||||
CAN1_RX0_IRQHandler
|
||||
CAN1_RX1_IRQHandler
|
||||
CAN1_EWMC_IRQHandler
|
||||
USBHS_IRQHandler
|
||||
SHRTIMER_IRQ2_IRQHandler
|
||||
SHRTIMER_IRQ3_IRQHandler
|
||||
SHRTIMER_IRQ4_IRQHandler
|
||||
SHRTIMER_IRQ5_IRQHandler
|
||||
SHRTIMER_IRQ6_IRQHandler
|
||||
USBHS_EP1_OUT_IRQHandler
|
||||
USBHS_EP1_IN_IRQHandler
|
||||
SHRTIMER_IRQ0_IRQHandler
|
||||
SHRTIMER_IRQ1_IRQHandler
|
||||
CAN2_TX_IRQHandler
|
||||
CAN2_RX0_IRQHandler
|
||||
CAN2_RX1_IRQHandler
|
||||
CAN2_EWMC_IRQHandler
|
||||
I2C2_EV_IRQHandler
|
||||
I2C2_ER_IRQHandler
|
||||
USART5_IRQHandler
|
||||
I2C2_WKUP_IRQHandler
|
||||
USART5_WKUP_IRQHandler
|
||||
TMU_IRQHandler
|
||||
|
||||
B .
|
||||
ENDP
|
||||
|
||||
ALIGN
|
||||
|
||||
; user Initial Stack & Heap
|
||||
|
||||
IF :DEF:__MICROLIB
|
||||
|
||||
EXPORT __initial_sp
|
||||
EXPORT __heap_base
|
||||
EXPORT __heap_limit
|
||||
|
||||
ELSE
|
||||
|
||||
IMPORT __use_two_region_memory
|
||||
EXPORT __user_initial_stackheap
|
||||
|
||||
__user_initial_stackheap PROC
|
||||
LDR R0, = Heap_Mem
|
||||
LDR R1, =(Stack_Mem + Stack_Size)
|
||||
LDR R2, = (Heap_Mem + Heap_Size)
|
||||
LDR R3, = Stack_Mem
|
||||
BX LR
|
||||
ENDP
|
||||
|
||||
ALIGN
|
||||
|
||||
ENDIF
|
||||
|
||||
END
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user