diff --git a/GD32E50X_BOOT/GD32E50X_BOOT.cproject.yml b/GD32E50X_BOOT/GD32E50X_BOOT.cproject.yml index 0d70035..075bf93 100644 --- a/GD32E50X_BOOT/GD32E50X_BOOT.cproject.yml +++ b/GD32E50X_BOOT/GD32E50X_BOOT.cproject.yml @@ -21,6 +21,8 @@ project: files: - file: ./device/Can.h - file: ./device/Can.cpp + - file: ./device/SpiOta.h + - file: ./device/SpiOta.cpp output: type: @@ -46,12 +48,14 @@ project: - component: Device:Startup - component: Device:GD32E50x_StdPeripherals:GPIO - component: Device:GD32E50x_StdPeripherals:EXTI + - component: Device:GD32E50x_StdPeripherals:SPI_I2S misc: - for-compiler: AC6 C-CPP: - -DGD32E508 - -DGD32E50X + - -DHXTAL_VALUE=8000000U - -gdwarf-5 - -D__MICROLIB - -fshort-enums @@ -64,8 +68,9 @@ project: ASM: - -DGD32E508 - -DGD32E50X + - -DHXTAL_VALUE=8000000U - -gdwarf-5 - -D__MICROLIB Link: - --library_type=microlib - - --entry=Reset_Handler + - --entry=Reset_Handler \ No newline at end of file diff --git a/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c b/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c deleted file mode 100644 index 7da27c0..0000000 --- a/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c +++ /dev/null @@ -1,239 +0,0 @@ -/*! - \file gd32e503z_eval.c - \brief firmware functions to manage leds, keys, COM ports - - \version 2025-07-09, V1.6.1, 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 "gd32e503z_eval.h" - -/* private variables */ -static uint32_t GPIO_PORT[LEDn] = {LED1_GPIO_PORT, LED2_GPIO_PORT, - LED3_GPIO_PORT, LED4_GPIO_PORT}; -static uint32_t GPIO_PIN[LEDn] = {LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN}; - -static rcu_periph_enum COM_CLK[COMn] = {EVAL_COM0_CLK}; -static uint32_t COM_TX_PIN[COMn] = {EVAL_COM0_TX_PIN}; -static uint32_t COM_RX_PIN[COMn] = {EVAL_COM0_RX_PIN}; -static uint32_t COM_GPIO_PORT[COMn] = {EVAL_COM0_GPIO_PORT}; -static rcu_periph_enum COM_GPIO_CLK[COMn] = {EVAL_COM0_GPIO_CLK}; - -static rcu_periph_enum GPIO_CLK[LEDn] = {LED1_GPIO_CLK, LED2_GPIO_CLK, - LED3_GPIO_CLK, LED4_GPIO_CLK}; - -static uint32_t KEY_PORT[KEYn] = {KEY_A_GPIO_PORT, - KEY_B_GPIO_PORT, - KEY_C_GPIO_PORT, - KEY_D_GPIO_PORT, - KEY_CET_GPIO_PORT}; -static uint32_t KEY_PIN[KEYn] = {KEY_A_PIN, - KEY_B_PIN, - KEY_C_PIN, - KEY_D_PIN, - KEY_CET_PIN}; -static rcu_periph_enum KEY_CLK[KEYn] = {KEY_A_GPIO_CLK, - KEY_B_GPIO_CLK, - KEY_C_GPIO_CLK, - KEY_D_GPIO_CLK, - KEY_CET_GPIO_CLK}; -static exti_line_enum KEY_EXTI_LINE[KEYn] = {KEY_A_EXTI_LINE, - KEY_B_EXTI_LINE, - KEY_C_EXTI_LINE, - KEY_D_EXTI_LINE, - KEY_CET_EXTI_LINE}; -static uint8_t KEY_PORT_SOURCE[KEYn] = {KEY_A_EXTI_PORT_SOURCE, - KEY_B_EXTI_PORT_SOURCE, - KEY_C_EXTI_PORT_SOURCE, - KEY_D_EXTI_PORT_SOURCE, - KEY_CET_EXTI_PORT_SOURCE}; -static uint8_t KEY_PIN_SOURCE[KEYn] = {KEY_A_EXTI_PIN_SOURCE, - KEY_B_EXTI_PIN_SOURCE, - KEY_C_EXTI_PIN_SOURCE, - KEY_D_EXTI_PIN_SOURCE, - KEY_CET_EXTI_PIN_SOURCE}; -static const IRQn_Type KEY_IRQn[KEYn] = {KEY_A_EXTI_IRQn, - KEY_B_EXTI_IRQn, - KEY_C_EXTI_IRQn, - KEY_D_EXTI_IRQn, - KEY_CET_EXTI_IRQn}; - -/*! - \brief configure led GPIO - \param[in] lednum: specify the led to be configured - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_init (led_typedef_enum lednum) -{ - /* enable the led clock */ - rcu_periph_clock_enable(GPIO_CLK[lednum]); - /* configure led GPIO port */ - gpio_init(GPIO_PORT[lednum], GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN[lednum]); - - GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief turn on selected led - \param[in] lednum: specify the led to be turned on - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_on(led_typedef_enum lednum) -{ - GPIO_BOP(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief turn off selected led - \param[in] lednum: specify the led to be turned off - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_off(led_typedef_enum lednum) -{ - GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief toggle selected led - \param[in] lednum: specify the led to be toggled - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_toggle(led_typedef_enum lednum) -{ - gpio_bit_write(GPIO_PORT[lednum], GPIO_PIN[lednum], - (bit_status)(1-gpio_input_bit_get(GPIO_PORT[lednum], GPIO_PIN[lednum]))); -} - -/*! - \brief configure key - \param[in] key_num: specify the key to be configured - \arg KEY_A: wakeup key - \arg KEY_B: tamper key - \arg KEY_C: user key - \arg KEY_D: extension key - \arg KEY_CET: extension key - \param[in] key_mode: specify button mode - \arg KEY_MODE_GPIO: key will be used as simple IO - \arg KEY_MODE_EXTI: key will be connected to EXTI line with interrupt - \param[out] none - \retval none -*/ -void gd_eval_key_init(key_typedef_enum key_num, keymode_typedef_enum key_mode) -{ - /* enable the key clock */ - rcu_periph_clock_enable(KEY_CLK[key_num]); - rcu_periph_clock_enable(RCU_AF); - - /* configure button pin as input */ - gpio_init(KEY_PORT[key_num], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, KEY_PIN[key_num]); - - if(key_mode == KEY_MODE_EXTI) { - /* enable and set key EXTI interrupt to the lowest priority */ - nvic_irq_enable(KEY_IRQn[key_num], 2U, 0U); - - /* connect key EXTI line to key GPIO pin */ - gpio_exti_source_select(KEY_PORT_SOURCE[key_num], KEY_PIN_SOURCE[key_num]); - - /* configure key EXTI line */ - exti_init(KEY_EXTI_LINE[key_num], EXTI_INTERRUPT, EXTI_TRIG_FALLING); - exti_interrupt_flag_clear(KEY_EXTI_LINE[key_num]); - } -} - -/*! - \brief return the selected key state - \param[in] key: specify the key to be checked - \arg KEY_A: wakeup key - \arg KEY_B: tamper key - \arg KEY_C: user key - \arg KEY_D: extension key - \arg KEY_CET: extension key - \param[out] none - \retval the key's GPIO pin value -*/ -uint8_t gd_eval_key_state_get(key_typedef_enum key) -{ - return gpio_input_bit_get(KEY_PORT[key], KEY_PIN[key]); -} - -/*! - \brief configure COM port - \param[in] com: COM on the board - \arg EVAL_COM0: COM0 on the board - \param[out] none - \retval none -*/ -void gd_eval_com_init(uint32_t com) -{ - uint32_t com_id = 0U; - if(EVAL_COM0 == com){ - com_id = 0U; - }else{ - while(1); - } - - /* enable GPIO clock */ - rcu_periph_clock_enable(COM_GPIO_CLK[com_id]); - - /* enable USART clock */ - rcu_periph_clock_enable(COM_CLK[com_id]); - - /* connect port to USARTx_Tx */ - gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_TX_PIN[com_id]); - - /* connect port to USARTx_Rx */ - gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, COM_RX_PIN[com_id]); - - /* USART configure */ - usart_deinit(com); - usart_baudrate_set(com, 115200U); - usart_receive_config(com, USART_RECEIVE_ENABLE); - usart_transmit_config(com, USART_TRANSMIT_ENABLE); - usart_enable(com); -} diff --git a/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c.base@1.2.4 b/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c.base@1.2.4 deleted file mode 100644 index 7da27c0..0000000 --- a/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c.base@1.2.4 +++ /dev/null @@ -1,239 +0,0 @@ -/*! - \file gd32e503z_eval.c - \brief firmware functions to manage leds, keys, COM ports - - \version 2025-07-09, V1.6.1, 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 "gd32e503z_eval.h" - -/* private variables */ -static uint32_t GPIO_PORT[LEDn] = {LED1_GPIO_PORT, LED2_GPIO_PORT, - LED3_GPIO_PORT, LED4_GPIO_PORT}; -static uint32_t GPIO_PIN[LEDn] = {LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN}; - -static rcu_periph_enum COM_CLK[COMn] = {EVAL_COM0_CLK}; -static uint32_t COM_TX_PIN[COMn] = {EVAL_COM0_TX_PIN}; -static uint32_t COM_RX_PIN[COMn] = {EVAL_COM0_RX_PIN}; -static uint32_t COM_GPIO_PORT[COMn] = {EVAL_COM0_GPIO_PORT}; -static rcu_periph_enum COM_GPIO_CLK[COMn] = {EVAL_COM0_GPIO_CLK}; - -static rcu_periph_enum GPIO_CLK[LEDn] = {LED1_GPIO_CLK, LED2_GPIO_CLK, - LED3_GPIO_CLK, LED4_GPIO_CLK}; - -static uint32_t KEY_PORT[KEYn] = {KEY_A_GPIO_PORT, - KEY_B_GPIO_PORT, - KEY_C_GPIO_PORT, - KEY_D_GPIO_PORT, - KEY_CET_GPIO_PORT}; -static uint32_t KEY_PIN[KEYn] = {KEY_A_PIN, - KEY_B_PIN, - KEY_C_PIN, - KEY_D_PIN, - KEY_CET_PIN}; -static rcu_periph_enum KEY_CLK[KEYn] = {KEY_A_GPIO_CLK, - KEY_B_GPIO_CLK, - KEY_C_GPIO_CLK, - KEY_D_GPIO_CLK, - KEY_CET_GPIO_CLK}; -static exti_line_enum KEY_EXTI_LINE[KEYn] = {KEY_A_EXTI_LINE, - KEY_B_EXTI_LINE, - KEY_C_EXTI_LINE, - KEY_D_EXTI_LINE, - KEY_CET_EXTI_LINE}; -static uint8_t KEY_PORT_SOURCE[KEYn] = {KEY_A_EXTI_PORT_SOURCE, - KEY_B_EXTI_PORT_SOURCE, - KEY_C_EXTI_PORT_SOURCE, - KEY_D_EXTI_PORT_SOURCE, - KEY_CET_EXTI_PORT_SOURCE}; -static uint8_t KEY_PIN_SOURCE[KEYn] = {KEY_A_EXTI_PIN_SOURCE, - KEY_B_EXTI_PIN_SOURCE, - KEY_C_EXTI_PIN_SOURCE, - KEY_D_EXTI_PIN_SOURCE, - KEY_CET_EXTI_PIN_SOURCE}; -static const IRQn_Type KEY_IRQn[KEYn] = {KEY_A_EXTI_IRQn, - KEY_B_EXTI_IRQn, - KEY_C_EXTI_IRQn, - KEY_D_EXTI_IRQn, - KEY_CET_EXTI_IRQn}; - -/*! - \brief configure led GPIO - \param[in] lednum: specify the led to be configured - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_init (led_typedef_enum lednum) -{ - /* enable the led clock */ - rcu_periph_clock_enable(GPIO_CLK[lednum]); - /* configure led GPIO port */ - gpio_init(GPIO_PORT[lednum], GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN[lednum]); - - GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief turn on selected led - \param[in] lednum: specify the led to be turned on - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_on(led_typedef_enum lednum) -{ - GPIO_BOP(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief turn off selected led - \param[in] lednum: specify the led to be turned off - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_off(led_typedef_enum lednum) -{ - GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief toggle selected led - \param[in] lednum: specify the led to be toggled - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_toggle(led_typedef_enum lednum) -{ - gpio_bit_write(GPIO_PORT[lednum], GPIO_PIN[lednum], - (bit_status)(1-gpio_input_bit_get(GPIO_PORT[lednum], GPIO_PIN[lednum]))); -} - -/*! - \brief configure key - \param[in] key_num: specify the key to be configured - \arg KEY_A: wakeup key - \arg KEY_B: tamper key - \arg KEY_C: user key - \arg KEY_D: extension key - \arg KEY_CET: extension key - \param[in] key_mode: specify button mode - \arg KEY_MODE_GPIO: key will be used as simple IO - \arg KEY_MODE_EXTI: key will be connected to EXTI line with interrupt - \param[out] none - \retval none -*/ -void gd_eval_key_init(key_typedef_enum key_num, keymode_typedef_enum key_mode) -{ - /* enable the key clock */ - rcu_periph_clock_enable(KEY_CLK[key_num]); - rcu_periph_clock_enable(RCU_AF); - - /* configure button pin as input */ - gpio_init(KEY_PORT[key_num], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, KEY_PIN[key_num]); - - if(key_mode == KEY_MODE_EXTI) { - /* enable and set key EXTI interrupt to the lowest priority */ - nvic_irq_enable(KEY_IRQn[key_num], 2U, 0U); - - /* connect key EXTI line to key GPIO pin */ - gpio_exti_source_select(KEY_PORT_SOURCE[key_num], KEY_PIN_SOURCE[key_num]); - - /* configure key EXTI line */ - exti_init(KEY_EXTI_LINE[key_num], EXTI_INTERRUPT, EXTI_TRIG_FALLING); - exti_interrupt_flag_clear(KEY_EXTI_LINE[key_num]); - } -} - -/*! - \brief return the selected key state - \param[in] key: specify the key to be checked - \arg KEY_A: wakeup key - \arg KEY_B: tamper key - \arg KEY_C: user key - \arg KEY_D: extension key - \arg KEY_CET: extension key - \param[out] none - \retval the key's GPIO pin value -*/ -uint8_t gd_eval_key_state_get(key_typedef_enum key) -{ - return gpio_input_bit_get(KEY_PORT[key], KEY_PIN[key]); -} - -/*! - \brief configure COM port - \param[in] com: COM on the board - \arg EVAL_COM0: COM0 on the board - \param[out] none - \retval none -*/ -void gd_eval_com_init(uint32_t com) -{ - uint32_t com_id = 0U; - if(EVAL_COM0 == com){ - com_id = 0U; - }else{ - while(1); - } - - /* enable GPIO clock */ - rcu_periph_clock_enable(COM_GPIO_CLK[com_id]); - - /* enable USART clock */ - rcu_periph_clock_enable(COM_CLK[com_id]); - - /* connect port to USARTx_Tx */ - gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_TX_PIN[com_id]); - - /* connect port to USARTx_Rx */ - gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, COM_RX_PIN[com_id]); - - /* USART configure */ - usart_deinit(com); - usart_baudrate_set(com, 115200U); - usart_receive_config(com, USART_RECEIVE_ENABLE); - usart_transmit_config(com, USART_TRANSMIT_ENABLE); - usart_enable(com); -} diff --git a/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c b/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c deleted file mode 100644 index 0e18853..0000000 --- a/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c +++ /dev/null @@ -1,227 +0,0 @@ -/*! - \file gd32e50x_fwdgt.c - \brief FWDGT 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_fwdgt.h" - -/*! - \brief enable write access to FWDGT_PSC and FWDGT_RLD - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_write_enable(void) -{ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; -} - -/*! - \brief disable write access to FWDGT_PSC and FWDGT_RLD - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_write_disable(void) -{ - FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; -} - -/*! - \brief start the free watchdog timer counter - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_enable(void) -{ - FWDGT_CTL = FWDGT_KEY_ENABLE; -} - -/*! - \brief configure the free watchdog timer counter prescaler value - \param[in] prescaler_value: specify prescaler value - only one parameter can be selected which is shown as below: - \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 - \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 - \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 - \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 - \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 - \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 - \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value) -{ - uint32_t timeout = FWDGT_PSC_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* enable write access to FWDGT_PSC */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT */ - FWDGT_PSC = (uint32_t)prescaler_value; - - /* wait until the PUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_PUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - return status; -} - -/*! - \brief configure the free watchdog timer counter reload value - \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_reload_value_config(uint16_t reload_value) -{ - uint32_t timeout = FWDGT_RLD_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* enable write access to FWDGT_RLD */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT_RLD */ - FWDGT_RLD = RLD_RLD(reload_value); - - /* wait until the RUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_RUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - return status; -} - -/*! - \brief reload the counter of FWDGT - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_counter_reload(void) -{ - FWDGT_CTL = FWDGT_KEY_RELOAD; -} - -/*! - \brief configure counter reload value, and prescaler divider value - \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) - \param[in] prescaler_value: FWDGT prescaler value - only one parameter can be selected which is shown as below: - \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 - \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 - \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 - \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 - \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 - \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 - \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_value) -{ - uint32_t timeout = FWDGT_PSC_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* start the free watchdog timer counter */ - FWDGT_CTL = FWDGT_KEY_ENABLE; - - /* enable write access to FWDGT_PSC,and FWDGT_RLD */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT PSC */ - FWDGT_PSC = (uint32_t)prescaler_value; - - /* wait until the PUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_PUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - if(SUCCESS == status) { - /* configure FWDGT_RLD */ - FWDGT_RLD = RLD_RLD(reload_value); - - /* wait until the RUD flag to be reset */ - timeout = FWDGT_RLD_TIMEOUT; - do { - flag_status = FWDGT_STAT & FWDGT_STAT_RUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - } - - if(SUCCESS == status) { - /* reload the counter */ - FWDGT_CTL = FWDGT_KEY_RELOAD; - } - - return status; -} - -/*! - \brief get flag state of FWDGT - \param[in] flag: flag to get - only one parameter can be selected which is shown as below: - \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going - \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus fwdgt_flag_get(uint16_t flag) -{ - FlagStatus flag_status = RESET; - if(FWDGT_STAT & flag) { - flag_status = SET; - } - return flag_status; -} diff --git a/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c.base@1.5.0 b/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c.base@1.5.0 deleted file mode 100644 index 0e18853..0000000 --- a/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c.base@1.5.0 +++ /dev/null @@ -1,227 +0,0 @@ -/*! - \file gd32e50x_fwdgt.c - \brief FWDGT 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_fwdgt.h" - -/*! - \brief enable write access to FWDGT_PSC and FWDGT_RLD - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_write_enable(void) -{ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; -} - -/*! - \brief disable write access to FWDGT_PSC and FWDGT_RLD - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_write_disable(void) -{ - FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; -} - -/*! - \brief start the free watchdog timer counter - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_enable(void) -{ - FWDGT_CTL = FWDGT_KEY_ENABLE; -} - -/*! - \brief configure the free watchdog timer counter prescaler value - \param[in] prescaler_value: specify prescaler value - only one parameter can be selected which is shown as below: - \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 - \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 - \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 - \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 - \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 - \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 - \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value) -{ - uint32_t timeout = FWDGT_PSC_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* enable write access to FWDGT_PSC */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT */ - FWDGT_PSC = (uint32_t)prescaler_value; - - /* wait until the PUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_PUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - return status; -} - -/*! - \brief configure the free watchdog timer counter reload value - \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_reload_value_config(uint16_t reload_value) -{ - uint32_t timeout = FWDGT_RLD_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* enable write access to FWDGT_RLD */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT_RLD */ - FWDGT_RLD = RLD_RLD(reload_value); - - /* wait until the RUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_RUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - return status; -} - -/*! - \brief reload the counter of FWDGT - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_counter_reload(void) -{ - FWDGT_CTL = FWDGT_KEY_RELOAD; -} - -/*! - \brief configure counter reload value, and prescaler divider value - \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) - \param[in] prescaler_value: FWDGT prescaler value - only one parameter can be selected which is shown as below: - \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 - \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 - \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 - \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 - \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 - \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 - \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_value) -{ - uint32_t timeout = FWDGT_PSC_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* start the free watchdog timer counter */ - FWDGT_CTL = FWDGT_KEY_ENABLE; - - /* enable write access to FWDGT_PSC,and FWDGT_RLD */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT PSC */ - FWDGT_PSC = (uint32_t)prescaler_value; - - /* wait until the PUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_PUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - if(SUCCESS == status) { - /* configure FWDGT_RLD */ - FWDGT_RLD = RLD_RLD(reload_value); - - /* wait until the RUD flag to be reset */ - timeout = FWDGT_RLD_TIMEOUT; - do { - flag_status = FWDGT_STAT & FWDGT_STAT_RUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - } - - if(SUCCESS == status) { - /* reload the counter */ - FWDGT_CTL = FWDGT_KEY_RELOAD; - } - - return status; -} - -/*! - \brief get flag state of FWDGT - \param[in] flag: flag to get - only one parameter can be selected which is shown as below: - \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going - \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus fwdgt_flag_get(uint16_t flag) -{ - FlagStatus flag_status = RESET; - if(FWDGT_STAT & flag) { - flag_status = SET; - } - return flag_status; -} diff --git a/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_spi.c b/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_spi.c new file mode 100644 index 0000000..e81dafa --- /dev/null +++ b/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_spi.c @@ -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; + } +} + + diff --git a/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_spi.c.base@1.5.0 b/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_spi.c.base@1.5.0 new file mode 100644 index 0000000..e81dafa --- /dev/null +++ b/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_spi.c.base@1.5.0 @@ -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; + } +} + + diff --git a/GD32E50X_BOOT/RTE/Device/GD32E508VE/regions_GD32E508VE.h b/GD32E50X_BOOT/RTE/Device/GD32E508VE/regions_GD32E508VE.h index 68d0696..f39f80f 100644 --- a/GD32E50X_BOOT/RTE/Device/GD32E508VE/regions_GD32E508VE.h +++ b/GD32E50X_BOOT/RTE/Device/GD32E508VE/regions_GD32E508VE.h @@ -17,7 +17,7 @@ #define __ROM0_BASE 0x08000000 // Region size [bytes] <0x0-0xFFFFFFFF:8> // Defines size of memory region. Default: 0x00080000 -#define __ROM0_SIZE 0x00080000 +#define __ROM0_SIZE 0x00012000 // // __ROM1 (unused) diff --git a/GD32E50X_BOOT/RTE/Device/GD32E508VE/system_gd32e50x.c b/GD32E50X_BOOT/RTE/Device/GD32E508VE/system_gd32e50x.c index 62360fe..1a7cb44 100644 --- a/GD32E50X_BOOT/RTE/Device/GD32E508VE/system_gd32e50x.c +++ b/GD32E50X_BOOT/RTE/Device/GD32E508VE/system_gd32e50x.c @@ -33,6 +33,7 @@ #define VECT_TAB_OFFSET (uint32_t)0x00 /* vector table base offset */ + /* select a system clock by uncommenting the following line */ /* use IRC8M */ //#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M) @@ -144,6 +145,12 @@ static void system_clock_180m_hxtal(void); static void system_clock_config(void); /* software delay to prevent the impact of Vcore fluctuations. It is strongly recommended to include it to avoid issues caused by self-removal. */ +/*! + \brief software delay helper used during clock switching + \param[in] time: delay scale factor + \param[out] none + \retval none +*/ static void _soft_delay_(uint32_t time) { __IO uint32_t i; @@ -997,7 +1004,23 @@ static void system_clock_180m_hxtal(void) RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); RCU_CFG0 |= RCU_PLL_MUL45; -#elif (defined(GD32E50X_CL) || defined(GD32E508)) +#elif defined(GD32E508) + /* GD32E508 + 8MHz HXTAL: + CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz + CK_PLL = CK_PREDIV0 * 45 = 180 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL45); + + RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ + } + +#elif defined(GD32E50X_CL) /* CK_PLL = (CK_PREDIV0) * 45 = 180 MHz */ RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL45); diff --git a/GD32E50X_BOOT/device/Can.cpp b/GD32E50X_BOOT/device/Can.cpp index b4246f9..2ef3d6c 100644 --- a/GD32E50X_BOOT/device/Can.cpp +++ b/GD32E50X_BOOT/device/Can.cpp @@ -8,42 +8,68 @@ #include "gd32e50x_misc.h" #include +/** + * @file Can.cpp + * @brief Bootloader CAN-FD 通信适配层实现。 + * + * 负责 CAN0 初始化、OTA 帧收发、软件发送队列与中断处理。 + */ + CAN_transmiter CAN0_transmiter; extern OTAHandler ota; -#define CAN_TX_QUEUE_SIZE 8 - -typedef struct { - u32 id; - u8 length; - u8 data[64]; - u8 valid; -} can_tx_queue_item_t; - -static can_tx_queue_item_t tx_queue[CAN_TX_QUEUE_SIZE]; -static volatile u8 tx_queue_head = 0; -static volatile u8 tx_queue_tail = 0; -static volatile u8 tx_queue_count = 0; -static can_trasnmit_message_struct queue_transmit_message; +CAN_transmiter::tx_queue_item_t CAN_transmiter::s_txQueue[CAN_transmiter::kTxQueueSize] = {}; +volatile u8 CAN_transmiter::s_txQueueHead = 0U; +volatile u8 CAN_transmiter::s_txQueueTail = 0U; +volatile u8 CAN_transmiter::s_txQueueCount = 0U; +can_trasnmit_message_struct CAN_transmiter::s_queueTransmitMessage = {}; +/** + * @brief 初始化 CAN0 相关 GPIO。 + * + * @return 0 表示初始化结束。 + */ u8 can_gpio_init(void) { + /** 打开 CAN0、GPIOB 和 AF 时钟。 */ rcu_periph_clock_enable(RCU_CAN0); rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_AF); + /** + * CAN0 使用 PB8/PB9 的部分重映射: + * - PB8 : RX,上拉输入 + * - PB9 : TX,复用推挽输出 + */ gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_8); gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP, ENABLE); + /** + * PB13 当前被拉低,通常可作为 CAN 收发器使能/待机控制脚。 + * 这里代码没有额外命名,先按“上电后默认拉低”保留原始行为。 + */ gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13); gpio_bit_reset(GPIOB, GPIO_PIN_13); return 0; } +/** + * @brief CAN DMA 初始化占位函数。 + * + * @return 无。 + */ void can_dma_init(void) { - /* Reserved: current receive path uses direct FIFO read to avoid DMA race. */ + /** + * 预留接口:当前接收路径直接从 FIFO 取数, + * 这样实现更简单,也避免 DMA 与中断抢数据的时序问题。 + */ } +/** + * @brief 配置 CAN-FD 控制器、滤波器和中断。 + * + * @return 无。 + */ void canfd_config(void) { can_parameter_struct can_parameter; can_fdframe_struct can_fd_parameter; @@ -54,6 +80,10 @@ void canfd_config(void) { can_dma_init(); can_deinit(CAN0); + /** + * 配置经典 CAN 仲裁段时序。 + * 这里 prescaler=6、BS1=7TQ、BS2=2TQ,配合具体时钟得到目标波特率。 + */ can_struct_para_init(CAN_INIT_STRUCT, &can_parameter); can_parameter.time_triggered = DISABLE; can_parameter.auto_bus_off_recovery = DISABLE; @@ -68,6 +98,10 @@ void canfd_config(void) { can_parameter.prescaler = 6; can_init(CAN0, &can_parameter); + /** + * 配置 CAN-FD 数据段时序。 + * fd_brs 打开后,数据段可以比仲裁段更快。 + */ can_struct_para_init(CAN_FD_FRAME_STRUCT, &can_fd_parameter); can_fd_parameter.fd_frame = ENABLE; can_fd_parameter.excp_event_detect = ENABLE; @@ -84,6 +118,10 @@ void canfd_config(void) { can_fd_parameter.data_prescaler = 6; can_fd_init(CAN0, &can_fd_parameter); + /** + * 过滤器全部放行。 + * 后续真正是否处理某个 ID,在接收中断里再按 OTA ID 白名单判断。 + */ can_struct_para_init(CAN_FILTER_STRUCT, &can_filter); can_filter.filter_mode = CAN_FILTERMODE_MASK; can_filter.filter_bits = CAN_FILTERBITS_32BIT; @@ -96,67 +134,136 @@ void canfd_config(void) { can_filter.filter_number = 0; can_filter_init(CAN0, &can_filter); + /** 打开接收和发送相关中断。 */ nvic_irq_enable(CAN0_RX0_IRQn, 1U, 0U); nvic_irq_enable(CAN0_TX_IRQn, 1U, 1U); can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0); } +/** + * @brief 初始化 CAN 发送器对象。 + * + * @return 0 表示初始化完成。 + */ u8 CAN_transmiter::init(void) { canfd_config(); + + /** 初始化软件侧收发对象和状态。 */ can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &transmit_message); can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &receive_message); can0_receive_count = 0; can0_send_flag = RESET; memset(transmit_data, 0, sizeof(transmit_data)); + memset(s_txQueue, 0, sizeof(s_txQueue)); + s_txQueueHead = 0U; + s_txQueueTail = 0U; + s_txQueueCount = 0U; + can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &s_queueTransmitMessage); return 0; } +/** + * @brief 轮询处理已接收的 CAN OTA 帧。 + * + * @return 无。 + */ void CAN_transmiter::communication_check(void) { + /** 发送完成标记目前只做一次性消费。 */ if (SET == can0_send_flag) { can0_send_flag = RESET; } + + /** + * 这里采用“中断收帧 + 主循环消费”的简单模型: + * 中断只保存最近一帧并累加计数,真正 OTA 处理放在主循环里完成。 + */ if (can0_receive_count > 0) { can0_receive_count--; - ota.handleOTAMessage(receive_message.rx_efid, receive_message.rx_data, - receive_message.rx_dlen); + + /** 走 CAN 收到的帧时,显式把 OTA 回包通道切回 CAN。 */ + ota_bind_can_transport(); + + if (receive_message.rx_efid == CANFD_OTA_CANCEL_ID) { + ota.handleLinkMessage(OTA_LINK_MSG_CANCEL, receive_message.rx_data, + receive_message.rx_dlen); + } else if (receive_message.rx_efid == CANFD_OTA_DATA_ID) { + ota.handleLinkMessage(OTA_LINK_MSG_DATA, receive_message.rx_data, + receive_message.rx_dlen); + } else if (receive_message.rx_efid == CANFD_OTA_REQ_ID) { + ota.handleLinkMessage(OTA_LINK_MSG_REQ, receive_message.rx_data, + receive_message.rx_dlen); + } } } -static u8 CAN_TX_QueuePush(u32 id, u8 length, u8 *data) { - if (tx_queue_count >= CAN_TX_QUEUE_SIZE) { +/** + * @brief 向软件发送队列压入一帧待发 CAN-FD 消息。 + * + * @param id 扩展帧 ID。 + * @param length 有效载荷长度。 + * @param data 指向待发送数据的指针。 + * @return 1 表示入队成功,0 表示队列已满。 + */ +u8 CAN_transmiter::queuePush(u32 id, u8 length, u8 *data) { + /** 队列满时直接失败,交给上层决定是否重试。 */ + if (s_txQueueCount >= kTxQueueSize) { return 0; } - tx_queue[tx_queue_tail].id = id; - tx_queue[tx_queue_tail].length = length; - memset(tx_queue[tx_queue_tail].data, 0, sizeof(tx_queue[tx_queue_tail].data)); + + s_txQueue[s_txQueueTail].id = id; + s_txQueue[s_txQueueTail].length = length; + memset(s_txQueue[s_txQueueTail].data, 0, sizeof(s_txQueue[s_txQueueTail].data)); for (u8 i = 0; i < length && i < 64U; ++i) { - tx_queue[tx_queue_tail].data[i] = data[i]; + s_txQueue[s_txQueueTail].data[i] = data[i]; } - tx_queue[tx_queue_tail].valid = 1U; - tx_queue_tail = (tx_queue_tail + 1U) % CAN_TX_QUEUE_SIZE; - tx_queue_count++; + s_txQueue[s_txQueueTail].valid = 1U; + + s_txQueueTail = (s_txQueueTail + 1U) % kTxQueueSize; + s_txQueueCount++; return 1; } -static u8 CAN_TX_QueuePop(can_tx_queue_item_t *item) { - if (tx_queue_count == 0U) { +/** + * @brief 从软件发送队列弹出一帧待发 CAN-FD 消息。 + * + * @param item 指向输出队列项的指针。 + * @return 1 表示出队成功,0 表示队列为空。 + */ +u8 CAN_transmiter::queuePop(tx_queue_item_t *item) { + if (s_txQueueCount == 0U) { return 0; } - *item = tx_queue[tx_queue_head]; - tx_queue[tx_queue_head].valid = 0U; - tx_queue_head = (tx_queue_head + 1U) % CAN_TX_QUEUE_SIZE; - tx_queue_count--; + + *item = s_txQueue[s_txQueueHead]; + s_txQueue[s_txQueueHead].valid = 0U; + s_txQueueHead = (s_txQueueHead + 1U) % kTxQueueSize; + s_txQueueCount--; return 1; } +/** + * @brief 异步发送一帧 CAN-FD 数据。 + * + * @param id 扩展帧 ID。 + * @param length 原始数据长度。 + * @param data 指向待发送数据缓冲区的指针。 + * @return 1 表示发送成功或成功入队,0 表示失败。 + */ u8 CAN_transmiter::CANFD_AsyncSend(u32 id, u8 length, u8 *data) { u8 valid_length = length; + + /** 只允许在 CAN-FD 模式下发送。 */ if (!(CAN_CTL(CAN0) & CAN_CTL_DFZ)) { return 0; } if (data == NULL) { return 0; } + + /** + * CAN-FD 的 DLC 不是任意长度都原样支持。 + * 这里把长度归一化到标准支持值:8/12/16/20/24/32/48/64。 + */ if (length > 8U) { if (length < 13U) valid_length = 12U; else if (length < 17U) valid_length = 16U; @@ -168,6 +275,7 @@ u8 CAN_transmiter::CANFD_AsyncSend(u32 id, u8 length, u8 *data) { else return 0; } + /** 组装发送帧。 */ transmit_message.tx_ft = CAN_FT_DATA; transmit_message.tx_ff = CAN_FF_EXTENDED; transmit_message.tx_efid = id; @@ -176,20 +284,37 @@ u8 CAN_transmiter::CANFD_AsyncSend(u32 id, u8 length, u8 *data) { transmit_message.fd_brs = ENABLE; transmit_message.fd_esi = DISABLE; + /** 不足 DLC 的部分补 0。 */ for (u8 i = 0; i < valid_length; ++i) { transmit_message.tx_data[i] = (i < length) ? data[i] : 0U; } + /** + * 尝试直接发送。 + * 如果没有空邮箱,则压入软件队列,等 TX 中断再补发。 + */ transmit_mailbox = can_message_transmit(CAN0, &transmit_message); if (transmit_mailbox == CAN_NOMAILBOX) { - return CAN_TX_QueuePush(id, valid_length, data); + return queuePush(id, valid_length, data); } + /** 有排队需求时,通过邮箱空中断继续推进发送。 */ can_interrupt_enable(CAN0, CAN_INTEN_TMEIE); return 1; } +/** + * @brief 发送带 4 字节业务数据的 OTA ACK。 + * + * @param packet_num 分包序号,当前实现未使用。 + * @param data 指向业务数据缓冲区的指针。 + * @return 1 表示发送成功或成功入队,0 表示失败。 + */ u8 CAN_transmiter::sendDATA_ACK(u32 packet_num, u8 *data) { + /** + * 兼容旧协议格式: + * 前两个字节固定为 0xBA 0xC0,后四字节带上包号/状态信息。 + */ (void)packet_num; memset(transmit_data, 0, sizeof(transmit_data)); transmit_data[0] = 0xBA; @@ -200,11 +325,32 @@ u8 CAN_transmiter::sendDATA_ACK(u32 packet_num, u8 *data) { return CANFD_AsyncSend(CANFD_OTA_ACK_ID, 6, transmit_data); } +/** + * @brief 发送备份恢复提示帧。 + * + * @return 1 表示发送成功或成功入队,0 表示失败。 + */ u8 CAN_transmiter::sendBackup() { + /** + * 发送一个空 ACK 帧,给外部上位机一个“正在走备份恢复”的提示。 + * 当前具体语义依赖对端实现。 + */ return CANFD_AsyncSend(CANFD_OTA_ACK_ID, 0, transmit_data); } +/** + * @brief 发送简化 OTA ACK。 + * + * @param packet_num 分包序号,当前实现未使用。 + * @param if_success 是否成功。 + * @return 1 表示发送成功或成功入队,0 表示失败。 + */ u8 CAN_transmiter::sendDATA_ACK(u32 packet_num, bool if_success) { + /** + * 简化 ACK 版本: + * if_success 为真时写入 0x0001; + * 为假则发送全 0,保留给对端区分处理。 + */ (void)packet_num; memset(transmit_data, 0, 4); if (if_success) { @@ -214,11 +360,22 @@ u8 CAN_transmiter::sendDATA_ACK(u32 packet_num, bool if_success) { return CANFD_AsyncSend(CANFD_OTA_ACK_ID, 4, transmit_data); } -void CAN0_RX0_IRQHandler(void) { +/** + * @brief CAN RX0 中断实际处理逻辑。 + * + * @return 无。 + */ +void CAN_transmiter::onRx0Interrupt() { + /** FIFO0 中存在新帧。 */ if (can_interrupt_flag_get(CAN0, CAN_INT_FLAG_RFL0) != RESET) { can_interrupt_flag_clear(CAN0, CAN_INT_FLAG_RFL0); + can_receive_message_struct temp_message; can_message_receive(CAN0, CAN_FIFO0, &temp_message); + + /** + * 仅保留 OTA 相关帧,避免 Bootloader 被无关 CAN 报文干扰。 + */ if (temp_message.rx_efid == CANFD_OTA_DATA_ID || temp_message.rx_efid == CANFD_OTA_REQ_ID || temp_message.rx_efid == CANFD_OTA_ACK_ID || @@ -231,6 +388,7 @@ void CAN0_RX0_IRQHandler(void) { } } + /** FIFO 满/溢出标志清理。 */ if (can_interrupt_flag_get(CAN0, CAN_INT_FLAG_RFF0) != RESET) { can_interrupt_flag_clear(CAN0, CAN_INT_FLAG_RFF0); } @@ -239,28 +397,53 @@ void CAN0_RX0_IRQHandler(void) { } } -void CAN0_TX_IRQHandler(void) { +/** + * @brief CAN TX 中断实际处理逻辑。 + * + * @return 无。 + */ +void CAN_transmiter::onTxInterrupt() { + /** 只要任意邮箱空出来,就尝试从软件队列补一帧出去。 */ if (can_flag_get(CAN0, CAN_FLAG_TME0) != RESET || can_flag_get(CAN0, CAN_FLAG_TME1) != RESET || can_flag_get(CAN0, CAN_FLAG_TME2) != RESET) { - can_tx_queue_item_t next_msg; - if (CAN_TX_QueuePop(&next_msg)) { - queue_transmit_message.tx_ft = CAN_FT_DATA; - queue_transmit_message.tx_ff = CAN_FF_EXTENDED; - queue_transmit_message.tx_efid = next_msg.id; - queue_transmit_message.tx_dlen = next_msg.length; - queue_transmit_message.fd_flag = CAN_FDF_FDFRAME; - queue_transmit_message.fd_brs = ENABLE; - queue_transmit_message.fd_esi = DISABLE; + tx_queue_item_t next_msg; + if (queuePop(&next_msg)) { + s_queueTransmitMessage.tx_ft = CAN_FT_DATA; + s_queueTransmitMessage.tx_ff = CAN_FF_EXTENDED; + s_queueTransmitMessage.tx_efid = next_msg.id; + s_queueTransmitMessage.tx_dlen = next_msg.length; + s_queueTransmitMessage.fd_flag = CAN_FDF_FDFRAME; + s_queueTransmitMessage.fd_brs = ENABLE; + s_queueTransmitMessage.fd_esi = DISABLE; for (u8 i = 0; i < next_msg.length; ++i) { - queue_transmit_message.tx_data[i] = next_msg.data[i]; + s_queueTransmitMessage.tx_data[i] = next_msg.data[i]; } - can_message_transmit(CAN0, &queue_transmit_message); + can_message_transmit(CAN0, &s_queueTransmitMessage); } else { + /** 队列已经空了,就关掉 TX 中断,避免空转。 */ can_interrupt_disable(CAN0, CAN_INTEN_TMEIE); } + + /** 清三个邮箱空标志。 */ can_flag_clear(CAN0, CAN_FLAG_TME0); can_flag_clear(CAN0, CAN_FLAG_TME1); can_flag_clear(CAN0, CAN_FLAG_TME2); } } + +/** + * @brief CAN0 RX FIFO0 interrupt service routine. + * @return none + */ +extern "C" void CAN0_RX0_IRQHandler(void) { + CAN_transmiter::onRx0Interrupt(); +} + +/** + * @brief CAN0 transmit interrupt service routine. + * @return none + */ +extern "C" void CAN0_TX_IRQHandler(void) { + CAN_transmiter::onTxInterrupt(); +} diff --git a/GD32E50X_BOOT/device/Can.h b/GD32E50X_BOOT/device/Can.h index ce73580..a78b4d2 100644 --- a/GD32E50X_BOOT/device/Can.h +++ b/GD32E50X_BOOT/device/Can.h @@ -1,8 +1,15 @@ #ifndef _CAN_H #define _CAN_H +/** + * @file Can.h + * @brief Bootloader CAN-FD 通信适配层头文件。 + * + * 定义 CAN 初始化、收发队列与 OTA 回包接口。 + */ + #include -#include "sys/config.h" +#include "config.h" #ifdef __cplusplus extern "C" { @@ -11,30 +18,132 @@ extern "C" { #include "gd32e50x_can.h" #include +/** + * @brief 初始化 CAN0 相关 GPIO 与引脚复用。 + * + * @return 0 表示初始化结束。 + */ u8 can_gpio_init(void); + +/** + * @brief 完成 CAN-FD 控制器、滤波器与中断配置。 + * + * @return 无。 + */ void canfd_config(void); + +/** + * @brief 初始化 CAN DMA 通道。 + * + * @note 当前实现未启用 DMA,该函数作为保留占位接口。 + * + * @return 无。 + */ void can_dma_init(void); + +/** + * @brief CAN0 FIFO0 接收中断服务函数。 + * + * @return 无。 + */ void CAN0_RX0_IRQHandler(void); + +/** + * @brief CAN0 发送邮箱空中断服务函数。 + * + * @return 无。 + */ void CAN0_TX_IRQHandler(void); +/** + * @brief Bootloader 的 CAN-FD 通信适配层。 + * + * 负责初始化 CAN0 外设、收发 OTA 相关帧,并在发送邮箱繁忙时 + * 通过软件队列缓存待发消息。 + */ class CAN_transmiter { private: - can_trasnmit_message_struct transmit_message; - u8 transmit_mailbox = CAN_NOMAILBOX; - u8 transmit_data[64]; + static constexpr u8 kTxQueueSize = 8U; + + typedef struct { + u32 id; /**< 扩展帧 ID */ + u8 length; /**< 有效载荷长度(CAN-FD DLC 归一化后的字节数) */ + u8 data[64]; /**< 最多支持 64 字节 CAN-FD 载荷 */ + u8 valid; /**< 当前槽位是否有效 */ + } tx_queue_item_t; + + static tx_queue_item_t s_txQueue[kTxQueueSize]; /**< 软件发送环形队列。 */ + static volatile u8 s_txQueueHead; /**< 软件发送队列头索引。 */ + static volatile u8 s_txQueueTail; /**< 软件发送队列尾索引。 */ + static volatile u8 s_txQueueCount; /**< 软件发送队列当前元素数。 */ + static can_trasnmit_message_struct s_queueTransmitMessage; /**< 发送中断复用帧对象。 */ + + can_trasnmit_message_struct transmit_message; /**< 当前正在组装/发送的 CAN-FD 帧。 */ + u8 transmit_mailbox = CAN_NOMAILBOX; /**< can_message_transmit() 返回的邮箱号。 */ + u8 transmit_data[64]; /**< 通用发送缓冲区,最大支持 64 字节 CAN-FD 载荷。 */ + + /** @brief 向软件发送队列压入一帧待发消息。 */ + static u8 queuePush(u32 id, u8 length, u8 *data); + /** @brief 从软件发送队列弹出一帧待发消息。 */ + static u8 queuePop(tx_queue_item_t *item); public: + /** @brief 初始化 CAN 控制器与软件状态。 + * + * @return 0 表示初始化完成。 + */ u8 init(void); - can_receive_message_struct receive_message; - volatile u8 can0_receive_count; - volatile FlagStatus can0_send_flag; + can_receive_message_struct receive_message; /**< 最近收到的一帧 OTA 相关消息。 */ + volatile u8 can0_receive_count; /**< 等待主循环处理的接收帧计数。 */ + volatile FlagStatus can0_send_flag; /**< 发送完成标记。 */ + /** + * @brief 轮询处理最近收到的 CAN OTA 帧。 + * + * 该函数会根据接收帧 ID 把消息转交给 OTA 状态机处理。 + * + * @return 无。 + */ void communication_check(); + + /** @brief 异步发送一帧 CAN-FD 数据。 + * + * 当硬件发送邮箱不可用时,函数会尝试把该帧压入软件队列。 + * + * @param ID 扩展帧 ID。 + * @param length 原始数据长度。 + * @param data 指向待发送数据缓冲区的指针。 + * @return 1 表示发送成功或成功入队,0 表示失败。 + */ u8 CANFD_AsyncSend(u32 ID, u8 length, u8 *data); + + /** @brief 发送简化 OTA ACK 帧。 + * + * @param packet_num 分包序号,当前实现未实际使用。 + * @param if_success 是否成功,true 表示成功。 + * @return 1 表示发送成功或成功入队,0 表示失败。 + */ u8 sendDATA_ACK(u32 packet_num, bool if_success); + + /** @brief 发送带 4 字节有效载荷的 OTA ACK 帧。 + * + * @param packet_num 分包序号,当前实现未实际使用。 + * @param data 指向 4 字节业务数据的缓冲区指针。 + * @return 1 表示发送成功或成功入队,0 表示失败。 + */ u8 sendDATA_ACK(u32 packet_num, u8 *data); + + /** @brief 发送「备份恢复」提示帧。 + * + * @return 1 表示发送成功或成功入队,0 表示失败。 + */ u8 sendBackup(); + + /** @brief CAN RX0 中断实际处理逻辑。 */ + static void onRx0Interrupt(); + /** @brief CAN TX 中断实际处理逻辑。 */ + static void onTxInterrupt(); }; #ifdef __cplusplus diff --git a/GD32E50X_BOOT/device/SpiOta.cpp b/GD32E50X_BOOT/device/SpiOta.cpp new file mode 100644 index 0000000..d8c8049 --- /dev/null +++ b/GD32E50X_BOOT/device/SpiOta.cpp @@ -0,0 +1,395 @@ +#include "SpiOta.h" +#include "core_cm33.h" +#include "gd32e50x_gpio.h" +#include "gd32e50x_exti.h" +#include "gd32e50x_rcu.h" +#include "gd32e50x_misc.h" +#include "gd32e50x_spi.h" +#include +#include + +/** + * @file SpiOta.cpp + * @brief Bootloader SPI OTA 从机模块实现(PendSV 延迟响应版)。 + * + * CS 释放后,EXTI ISR 只做轻量校验(SOF + LEN + CRC), + * 校验通过则触发 PendSV(最低优先级 ISR),由 PendSV ISR 调用 + * handleLinkMessage 完成帧处理和响应准备。 + */ + +OTAHandler *SpiOta::s_otaHandler = nullptr; +volatile bool SpiOta::s_csActive = false; +volatile u16 SpiOta::s_rxStreamLen = 0U; +volatile u16 SpiOta::s_txStreamPos = 0U; +u8 SpiOta::s_rxStream[SpiOta::kRxBufSize] = {}; +u8 SpiOta::s_txBuf[SpiOta::kTxBufSize] = {}; +volatile u16 SpiOta::s_txLen = 0U; +volatile bool SpiOta::s_txPending = false; +volatile bool SpiOta::s_isrLogPending = false; +u8 SpiOta::s_isrLogBuf[kIsrLogBufSize] = {}; +u16 SpiOta::s_isrLogLen = 0U; +volatile bool SpiOta::s_pendSVPending = false; + +/* ============================================================ + * CRC8 / 帧构建 / 帧解析 + * ============================================================ */ + +u8 SpiOta::crc8(const u8 *data, u16 len) { + u8 crc = 0x00U; + for (u16 i = 0; i < len; ++i) { crc ^= data[i]; } + return crc; +} + +bool SpiOta::buildFrame(spi_ota_frame_type_t type, const u8 *payload, u16 payload_len, + u8 *out, u16 *out_len) { + if (!out || !out_len) { return false; } + u16 total_len = (u16)(kFrameOverhead + payload_len); + if (total_len > kTxBufSize) { return false; } + out[0] = kSof; + out[1] = (u8)type; + out[2] = (u8)(payload_len & 0xFFU); + out[3] = (u8)((payload_len >> 8) & 0xFFU); + if (payload && payload_len > 0U) { memcpy(&out[4], payload, payload_len); } + out[4 + payload_len] = crc8(out, (u16)(4U + payload_len)); + *out_len = total_len; + return true; +} + +bool SpiOta::tryParseFrame(const u8 *frame, u16 frame_len, + spi_ota_frame_type_t *type, + const u8 **payload, + u16 *payload_len) { + if (!frame || frame_len < kFrameOverhead) { return false; } + if (frame[0] != kSof) { return false; } + u16 len = (u16)(frame[2] | ((u16)frame[3] << 8)); + u16 expected = (u16)(kFrameOverhead + len); + if (expected != frame_len) { return false; } + if (crc8(frame, (u16)(4U + len)) != frame[4U + len]) { return false; } + if (type) { *type = (spi_ota_frame_type_t)frame[1]; } + if (payload) { *payload = &frame[4]; } + if (payload_len){ *payload_len = len; } + return true; +} + +ota_link_msg_type_t SpiOta::mapMsgType(spi_ota_frame_type_t type) { + switch (type) { + case SPI_OTA_CMD_REQ: return OTA_LINK_MSG_REQ; + case SPI_OTA_CMD_DATA: return OTA_LINK_MSG_DATA; + default: return OTA_LINK_MSG_CANCEL; + } +} + +/* ============================================================ + * 回包发送适配器(ISR 安全) + * ============================================================ */ + +void SpiOta::sender(ota_link_tx_type_t type, u8 len, const u8 *data) { + spi_ota_frame_type_t rsp_type = SPI_OTA_RSP_ACK; + if (type == OTA_LINK_TX_WAIT) { rsp_type = SPI_OTA_RSP_WAIT; } + u8 frame_buf[kTxBufSize] = {}; + u16 built_len = 0U; + if (buildFrame(rsp_type, data, len, frame_buf, &built_len)) { + queueTxFrame(frame_buf, built_len); + } +} + +uint32_t SpiOta::enterCritical() { + uint32_t primask = __get_PRIMASK(); + __disable_irq(); + return primask; +} + +void SpiOta::exitCritical(uint32_t primask) { + __set_PRIMASK(primask); +} + +void SpiOta::queueTxFrame(const u8 *frame, u16 len) { + if (!frame || len == 0U || len > kTxBufSize) { return; } + bool enable_tbe = false; + uint32_t primask = enterCritical(); + memcpy(s_txBuf, frame, len); + s_txLen = len; + s_txPending = true; + s_txStreamPos = 0U; + enable_tbe = s_csActive; + exitCritical(primask); + if (enable_tbe) { spi_i2s_interrupt_enable(SPI0, SPI_I2S_INT_TBE); } +} + +/* ============================================================ + * EXTI ISR:轻量校验 + 触发 PendSV + * ============================================================ */ + +void SpiOta::isrValidateAndPend() { + u16 rx_len = s_rxStreamLen; + if (rx_len < kFrameOverhead) { return; } + + if (s_rxStream[0] != kSof) { return; } + + u16 payload_len = (u16)(s_rxStream[2] | ((u16)s_rxStream[3] << 8)); + u16 expected = (u16)(kFrameOverhead + payload_len); + if (expected > rx_len) { return; } + + if (crc8(s_rxStream, (u16)(4U + payload_len)) != s_rxStream[4U + payload_len]) { + u8 err = 0xEEU; + u8 err_frame[kTxBufSize] = {}; + u16 built = 0U; + if (buildFrame(SPI_OTA_RSP_ERROR, &err, 1U, err_frame, &built)) { + queueTxFrame(err_frame, built); + } + return; + } + + /* ★ 校验通过,触发 PendSV ★ */ + s_pendSVPending = true; + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + + isrLogFrame("[EXTI-OK]", s_rxStream, expected); +} + +/* ============================================================ + * PendSV ISR:在低优先级 ISR 中完成帧处理 + * ============================================================ */ + +void SpiOta::onPendSvProcess() { + if (!s_pendSVPending) { return; } + s_pendSVPending = false; + + u16 frame_len = s_rxStreamLen; + + spi_ota_frame_type_t frame_type; + const u8 *payload = nullptr; + u16 payload_len = 0U; + + if (!tryParseFrame(s_rxStream, frame_len, &frame_type, &payload, &payload_len)) { + return; + } + + if (s_otaHandler == nullptr) { return; } + + s_otaHandler->setTransportSender(sender); + + ota_link_msg_type_t msg_type = mapMsgType(frame_type); + s_otaHandler->handleLinkMessage(msg_type, const_cast(payload), (u8)payload_len); + + isrLogFrame("[PendSV-DONE]", s_txBuf, s_txLen); +} + +/* ============================================================ + * ISR 内延迟日志 + * ============================================================ */ + +void SpiOta::isrLogFrame(const char *tag, const u8 *data, u16 len) { + if (s_isrLogPending) { return; } + u16 pos = 0U; + if (tag) { + while (*tag && pos < kIsrLogBufSize - 1U) { s_isrLogBuf[pos++] = (u8)*tag++; } + s_isrLogBuf[pos++] = ' '; + } + const u16 preview = (len < 32U) ? len : 32U; + for (u16 i = 0U; i < preview && pos + 2U < kIsrLogBufSize; ++i) { + static const char hx[] = "0123456789ABCDEF"; + s_isrLogBuf[pos++] = (u8)hx[data[i] >> 4]; + s_isrLogBuf[pos++] = (u8)hx[data[i] & 0x0FU]; + } + s_isrLogBuf[pos] = 0U; + s_isrLogLen = pos; + s_isrLogPending = true; +} + +/* ============================================================ + * 硬件初始化 + * ============================================================ */ + +void SpiOta::configureGpio() { + rcu_periph_clock_enable(RCU_GPIOA); + rcu_periph_clock_enable(RCU_GPIOB); + rcu_periph_clock_enable(RCU_AF); + gpio_pin_remap_config(GPIO_SPI0_REMAP, ENABLE); + gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE); + gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3 | GPIO_PIN_5); + gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4); + gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7); + gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_15); +} + +void SpiOta::configureSpi0() { + rcu_periph_clock_enable(RCU_SPI0); + spi_i2s_deinit(SPI0); + spi_parameter_struct spi_init_struct; + spi_struct_para_init(&spi_init_struct); + spi_init_struct.device_mode = SPI_SLAVE; + spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT; + spi_init_struct.nss = SPI_NSS_SOFT; + spi_init_struct.endian = SPI_ENDIAN_MSB; + spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + spi_init_struct.prescale = SPI_PSC_8; + spi_init(SPI0, &spi_init_struct); + spi_nss_internal_low(SPI0); + spi_i2s_interrupt_enable(SPI0, SPI_I2S_INT_RBNE); + spi_i2s_interrupt_enable(SPI0, SPI_I2S_INT_ERR); + spi_i2s_interrupt_disable(SPI0, SPI_I2S_INT_TBE); + nvic_irq_enable(SPI0_IRQn, 1U, 0U); + spi_enable(SPI0); +} + +void SpiOta::configureExti() { + gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_15); + exti_init(EXTI_15, EXTI_INTERRUPT, EXTI_TRIG_BOTH); + exti_interrupt_enable(EXTI_15); + exti_interrupt_flag_clear(EXTI_15); + nvic_irq_enable(EXTI10_15_IRQn, 1U, 1U); + /* PendSV 优先级设最低(不阻塞 SPI/EXTI),通过 SCB->ICSR 触发,无需 NVIC_EnableIRQ */ + NVIC_SetPriority(PendSV_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); +} + +void SpiOta::init() { + s_csActive = false; + s_rxStreamLen = 0U; + s_txStreamPos = 0U; + s_txLen = 0U; + s_txPending = false; + s_isrLogPending = false; + s_pendSVPending = false; + memset(s_rxStream, 0, sizeof(s_rxStream)); + memset(s_txBuf, 0xFF, sizeof(s_txBuf)); + configureGpio(); + configureSpi0(); + configureExti(); +} + +/* ============================================================ + * CS 边沿处理 + * ============================================================ */ + +void SpiOta::onCsAssert() { + if (s_csActive) { return; } + s_csActive = true; + s_rxStreamLen = 0U; + s_txStreamPos = 0U; + if (s_txPending && s_txLen > 0U) { + spi_i2s_interrupt_enable(SPI0, SPI_I2S_INT_TBE); + } +} + +void SpiOta::onCsRelease() { + if (!s_csActive) { return; } + s_csActive = false; + spi_i2s_interrupt_disable(SPI0, SPI_I2S_INT_TBE); + if (s_rxStreamLen > 0U && s_rxStreamLen <= kRxBufSize) { + isrValidateAndPend(); + } +} + +/* ============================================================ + * SPI0 中断处理 + * ============================================================ */ + +void SpiOta::onSpiInterrupt() { + if (spi_i2s_interrupt_flag_get(SPI0, SPI_I2S_INT_FLAG_RBNE) != RESET) { + if (!s_csActive && gpio_input_bit_get(GPIOA, GPIO_PIN_15) == RESET) { onCsAssert(); } + u8 byte = (u8)(spi_i2s_data_receive(SPI0) & 0xFFU); + if (s_csActive && s_rxStreamLen < kRxBufSize) { s_rxStream[s_rxStreamLen++] = byte; } + } + if (spi_i2s_interrupt_flag_get(SPI0, SPI_I2S_INT_FLAG_TBE) != RESET) { + if (!s_csActive && gpio_input_bit_get(GPIOA, GPIO_PIN_15) == RESET) { onCsAssert(); } + u8 tx_byte = 0xFFU; + if (s_csActive && s_txPending && s_txStreamPos < s_txLen) { + tx_byte = s_txBuf[s_txStreamPos++]; + if (s_txStreamPos >= s_txLen) { + s_txPending = false; + s_txLen = 0U; + s_txStreamPos = 0U; + spi_i2s_interrupt_disable(SPI0, SPI_I2S_INT_TBE); + } + } else { + spi_i2s_interrupt_disable(SPI0, SPI_I2S_INT_TBE); + } + spi_i2s_data_transmit(SPI0, tx_byte); + } + if (spi_i2s_interrupt_flag_get(SPI0, SPI_I2S_INT_FLAG_RXORERR) != RESET) { + (void)spi_i2s_data_receive(SPI0); + s_rxStreamLen = 0U; + } + if (spi_i2s_interrupt_flag_get(SPI0, SPI_I2S_INT_FLAG_FERR) != RESET) { + spi_i2s_format_error_clear(SPI0, SPI_FLAG_FERR); + } +} + +void SpiOta::onCsExtiInterrupt() { + if (exti_interrupt_flag_get(EXTI_15) != RESET) { + exti_interrupt_flag_clear(EXTI_15); + if (gpio_input_bit_get(GPIOA, GPIO_PIN_15) == RESET) { onCsAssert(); } + else { onCsRelease(); } + } +} + +/* ============================================================ + * 主循环接口 + * ============================================================ */ + +void SpiOta::poll() { + if (s_isrLogPending) { + printf("[SPI-BOOT] %s\r\n", s_isrLogBuf); + s_isrLogPending = false; + } + if (s_otaHandler != nullptr) { s_otaHandler->process(); } +} + +void SpiOta::setSender(OTAHandler *handler) { s_otaHandler = handler; } + +void SpiOta::feedRxBytes(const u8 *data, u16 len) { + if (!data || len == 0U || !s_csActive) { return; } + if (len > kRxBufSize) { data += (len - kRxBufSize); len = kRxBufSize; } + memcpy(s_rxStream, data, len); + s_rxStreamLen = len; +} + +bool SpiOta::hasTxFrame() { return s_txPending; } + +u16 SpiOta::copyTxFrame(u8 *out, u16 max_len) { + if (!out || max_len == 0U) { return 0U; } + uint32_t primask = enterCritical(); + if (!s_txPending || s_txLen == 0U) { exitCritical(primask); return 0U; } + u16 copy_len = (s_txLen < max_len) ? s_txLen : max_len; + memcpy(out, s_txBuf, copy_len); + s_txPending = false; + s_txLen = 0U; + s_txStreamPos = 0U; + exitCritical(primask); + return copy_len; +} + +/* ============================================================ + * C 风格兼容包装 + * ============================================================ */ + +void spi_ota_init(void) { SpiOta::init(); } +void spi_ota_poll(void) { SpiOta::poll(); } +void spi_ota_set_sender(OTAHandler *handler) { SpiOta::setSender(handler); } +void spi_ota_on_cs_assert(void) { SpiOta::onCsAssert(); } +void spi_ota_on_cs_release(void) { SpiOta::onCsRelease(); } +void spi_ota_gpio_init(void) { SpiOta::configureGpio(); } +void spi_ota_spi0_init(void) { SpiOta::configureSpi0(); } +void spi_ota_exti_init(void) { SpiOta::configureExti(); } +void spi_ota_irq_handler(void) { SpiOta::onSpiInterrupt(); } +void spi_ota_cs_exti_handler(void) { SpiOta::onCsExtiInterrupt(); } +void spi_ota_feed_rx_bytes(const u8 *data, u16 len) { SpiOta::feedRxBytes(data, len); } +bool spi_ota_has_tx_frame(void) { return SpiOta::hasTxFrame(); } +u16 spi_ota_copy_tx_frame(u8 *out, u16 max_len) { return SpiOta::copyTxFrame(out, max_len); } + +/** + * @brief SPI0 中断向量入口。 + */ +extern "C" void SPI0_IRQHandler(void) { + SpiOta::onSpiInterrupt(); +} + +/** + * @brief PendSV 中断向量入口。 + * @note 调用 SpiOta::onPendSvProcess() 在低优先级 ISR 中完成帧处理。 + */ +extern "C" void PendSV_Handler(void) { + SpiOta::onPendSvProcess(); +} \ No newline at end of file diff --git a/GD32E50X_BOOT/device/SpiOta.h b/GD32E50X_BOOT/device/SpiOta.h new file mode 100644 index 0000000..33147e7 --- /dev/null +++ b/GD32E50X_BOOT/device/SpiOta.h @@ -0,0 +1,108 @@ +#ifndef __SPI_OTA_H__ +#define __SPI_OTA_H__ + +#include "OTA.h" + +/** + * @file SpiOta.h + * @brief SPI OTA 从机协议头文件(PendSV 延迟响应版)。 + * + * CS 释放后,EXTI ISR 只做轻量校验(SOF + LEN + CRC), + * 校验通过则触发 PendSV(最低优先级 ISR),由 PendSV 调用 + * handleLinkMessage 完成帧处理和响应准备。 + */ + +typedef enum { + SPI_OTA_CMD_REQ = 0x01, + SPI_OTA_CMD_DATA = 0x02, + SPI_OTA_CMD_CANCEL = 0x03, + SPI_OTA_RSP_ACK = 0x80, + SPI_OTA_RSP_WAIT = 0x81, + SPI_OTA_RSP_ERROR = 0x82 +} spi_ota_frame_type_t; + +class SpiOta { +public: + static constexpr u8 kSof = 0xA5U; + static constexpr u16 kRxBufSize = 256U; + static constexpr u16 kTxBufSize = 128U; + static constexpr u16 kFrameOverhead = 5U; + static constexpr u16 kIsrLogBufSize = 128U; + + static void init(); + static void poll(); + static void setSender(OTAHandler *handler); + static void onCsAssert(); + static void onCsRelease(); + static void configureGpio(); + static void configureSpi0(); + static void configureExti(); + static void onSpiInterrupt(); + static void onCsExtiInterrupt(); + static void feedRxBytes(const u8 *data, u16 len); + static bool hasTxFrame(); + static u16 copyTxFrame(u8 *out, u16 max_len); + + /** @brief EXTI ISR 内轻量校验,通过则触发 PendSV。 */ + static void isrValidateAndPend(); + /** @brief PendSV ISR 内执行帧处理和响应准备。 */ + static void onPendSvProcess(); + /** @brief ISR 内轻量日志写入延迟打印缓冲。 */ + static void isrLogFrame(const char *tag, const u8 *data, u16 len); + + /* ---- PendSV 需要访问的成员放 public ---- */ + static OTAHandler *s_otaHandler; + static volatile bool s_csActive; + static volatile u16 s_rxStreamLen; + static volatile u16 s_txStreamPos; + static u8 s_rxStream[kRxBufSize]; + static u8 s_txBuf[kTxBufSize]; + static volatile u16 s_txLen; + static volatile bool s_txPending; + static volatile bool s_isrLogPending; + static u8 s_isrLogBuf[kIsrLogBufSize]; + static u16 s_isrLogLen; + static volatile bool s_pendSVPending; + +private: + static u8 crc8(const u8 *data, u16 len); + static bool buildFrame(spi_ota_frame_type_t type, const u8 *payload, u16 payload_len, + u8 *out, u16 *out_len); + static bool tryParseFrame(const u8 *frame, u16 frame_len, + spi_ota_frame_type_t *type, + const u8 **payload, + u16 *payload_len); + static ota_link_msg_type_t mapMsgType(spi_ota_frame_type_t type); + static void sender(ota_link_tx_type_t type, u8 len, const u8 *data); + static void queueTxFrame(const u8 *frame, u16 len); + static uint32_t enterCritical(); + static void exitCritical(uint32_t primask); +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 引脚约定:CS=PA15, SCK=PB3, MISO=PB4, MOSI=PB5 + */ + +void spi_ota_init(void); +void spi_ota_poll(void); +void spi_ota_set_sender(OTAHandler *handler); +void spi_ota_on_cs_assert(void); +void spi_ota_on_cs_release(void); +void spi_ota_gpio_init(void); +void spi_ota_spi0_init(void); +void spi_ota_exti_init(void); +void spi_ota_irq_handler(void); +void spi_ota_cs_exti_handler(void); +void spi_ota_feed_rx_bytes(const u8 *data, u16 len); +bool spi_ota_has_tx_frame(void); +u16 spi_ota_copy_tx_frame(u8 *out, u16 max_len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GD32E50X_BOOT/main.cpp b/GD32E50X_BOOT/main.cpp index 457bf37..a6f7ce3 100644 --- a/GD32E50X_BOOT/main.cpp +++ b/GD32E50X_BOOT/main.cpp @@ -1,5 +1,6 @@ #include "main.h" #include "device/Can.h" +#include "device/SpiOta.h" #include "sys/config.h" #include "gd32e50x.h" #include "sys/OTA.h" @@ -9,67 +10,207 @@ extern CAN_transmiter CAN0_transmiter; extern OTAHandler ota; +/** @brief Bootloader 全局运行实例。 */ BootloaderSystem sys; +/** + * @brief 初始化 Bootloader 运行所需的硬件外设。 + * + * 初始化顺序依次为 SysTick、串口、CAN、OTA 核心、SPI OTA + * 和睡眠状态检查。 + * + * @return 无。 + */ void BootloaderSystem::initHardware() { - systick_config(); - USART0_init(); + /** + * 初始化顺序尽量从基础时基到通信外设: + * 1. SysTick:为延时和超时逻辑提供基础时钟 + * 2. USART0:调试打印输出 + * 3. CAN:OTA 主通信链路之一 + * 4. OTA 核心状态机 + * 5. SPI OTA:备用/新增的 OTA 通道 + * 6. 睡眠状态检查 + */ + SysTickTimer::init(); + BootDebugUart::init(); + printf("\r\n[BOOT] power on\r\n"); + printf("[BOOT] BOOT=0x%08lX size=0x%08lX APPBACK=0x%08lX APPLATEST=0x%08lX APP_MAX=0x%08lX\r\n", + (unsigned long)BOOTLOADER_START_ADDR, + (unsigned long)BOOTLOADER_SIZE, + (unsigned long)APPBACK_START_ADDR, + (unsigned long)APPLATEST_START_ADDR, + (unsigned long)APP_MAX_SIZE); + printf("[BOOT] SystemCoreClock=%lu Hz\r\n", (unsigned long)SystemCoreClock); CAN0_transmiter.init(); - check_sleep(); + ota.init(); + SpiOta::init(); + + /** 让 SPI OTA 模块在收到完整帧后,转交给 ota 实例处理。 */ + SpiOta::setSender(&ota); + + /** 检查是否需要进入深度睡眠模式。 */ + { + const int sleep_state = BootSleepManager::check(); + printf("[BOOT] sleep_check=%d\r\n", sleep_state); + } } -void BootloaderSystem::run() { - volatile uint32_t *flash_ptr = (volatile uint32_t *)n_APP_LATEST_EN_ADDR; - uint32_t app_enable = *flash_ptr; - flash_ptr = (volatile uint32_t *)n_APP_LATEST_CHECK_ADDR; - uint32_t app_check = *flash_ptr; +/** @brief 心跳打印间隔(毫秒)。 */ +static constexpr uint32_t kHeartbeatPrintIntervalMs = 2000U; +/** + * @brief 主循环辅助函数:轮询 CAN + SPI OTA 后台任务。 + * + * @note SPI OTA 帧解析和响应准备已在 ISR 内完成, + * poll() 只负责消费 ISR 延迟日志和推进 OTA 后台任务(延迟擦除/跳转)。 + */ +static void pollAllLinks(void) { + CAN0_transmiter.communication_check(); + SpiOta::poll(); +} + +/** + * @brief 定时心跳打印:每隔 kHeartbeatPrintIntervalMs 输出一条状态摘要。 + * + * @param[in,out] heartbeat_counter 上次打印后的累计毫秒数。 + * @param[in] loop_delay_ms 每轮主循环的延时毫秒数。 + * @param[in] path_label 当前停留路径描述,如 "wait_ota_window"。 + */ +static void heartbeatPrint(uint32_t &heartbeat_counter, uint32_t loop_delay_ms, const char *path_label) { + heartbeat_counter += loop_delay_ms; + if (heartbeat_counter >= kHeartbeatPrintIntervalMs) { + heartbeat_counter = 0U; + printf("[BOOT] \xe2\x99\xa5 %s ota_active=%d spi_tx_pending=%d\r\n", + path_label, + ota.isActive() ? 1 : 0, + SpiOta::hasTxFrame() ? 1 : 0); + } +} + +/** + * @brief 执行 Bootloader 主流程。 + * + * 根据当前应用区和备份应用区的状态标志,选择执行应用跳转、 + * OTA 等待或备份恢复逻辑。 + * + * @return 无。 + */ +void BootloaderSystem::run() { + volatile uint32_t *flash_ptr; + uint32_t app_enable, app_check; + + flash_ptr = (volatile uint32_t *)n_APP_LATEST_EN_ADDR; + app_enable = *flash_ptr; + flash_ptr = (volatile uint32_t *)n_APP_LATEST_CHECK_ADDR; + app_check = *flash_ptr; + + printf("[BOOT] app_enable=0x%08lX app_check=0x%08lX\r\n", + (unsigned long)app_enable, + (unsigned long)app_check); + + /** + * 情况 1:应用已校验完成,且允许启动。 + * 直接跳转到主应用,不在 Bootloader 多停留。 + */ if (app_check == OTA_AVAL && app_enable == OTA_AVAL) { + printf("[BOOT] path=jump_latest_now\r\n"); ota.jumpToApplication(); - } else if (app_check == OTA_AVAL && app_enable == OTA_NOT_AVAL) { + } + /** + * 情况 2:应用是有效的,但当前被标记为"暂不启动"。 + * 这通常表示系统希望给 OTA 留一个短暂窗口,若窗口内没有升级请求,再启动应用。 + */ + else if (app_check == OTA_AVAL && app_enable == OTA_NOT_AVAL) { uint32_t delay_count = 0; + uint32_t heartbeat_counter = 0U; int ota_requested = 0; + printf("[BOOT] path=wait_ota_window timeout_ms=%lu\r\n", (unsigned long)APP_DELAY_BOOT_TIME); + while (delay_count < APP_DELAY_BOOT_TIME) { - CAN0_transmiter.communication_check(); - ota.process(); + pollAllLinks(); + heartbeatPrint(heartbeat_counter, 10U, "wait_ota_window"); + if (ota.isActive()) { ota_requested = 1; + printf("[BOOT] ota_requested at %lu ms\r\n", (unsigned long)delay_count); break; } + delay_1ms(10); delay_count += 10; } if (ota_requested) { + /** + * 已经进入 OTA 会话: + * 后续不再尝试跳应用,持续停留在 Bootloader 内处理升级。 + */ + printf("[BOOT] path=stay_in_ota\r\n"); + uint32_t hb_ota = 0U; while (1) { - CAN0_transmiter.communication_check(); - ota.process(); + pollAllLinks(); + heartbeatPrint(hb_ota, 10U, "stay_in_ota"); + delay_1ms(10); } } else { + /** 等待窗口内没有任何 OTA 请求,正常启动当前应用。 */ + printf("[BOOT] ota_window_timeout_then_jump\r\n"); ota.jumpToApplication(); } - } else { + } + /** + * 情况 3:当前主应用区不可用。 + * 尝试检查备份区是否可恢复;如果可恢复,则复制到主应用区后启动。 + */ + else { + uint32_t back_aval, back_check; flash_ptr = (volatile uint32_t *)n_APP_BACKUP_AVAL_ADDR; - uint32_t back_aval = *flash_ptr; + back_aval = *flash_ptr; flash_ptr = (volatile uint32_t *)n_APP_BACKUP_CHECK_ADDR; - uint32_t back_check = *flash_ptr; + back_check = *flash_ptr; + + printf("[BOOT] back_aval=0x%08lX back_check=0x%08lX\r\n", + (unsigned long)back_aval, + (unsigned long)back_check); + if (back_check == OTA_AVAL && back_aval == OTA_AVAL) { + /** + * 备份区可用: + * 1. 先发送一帧提示,表示即将走备份恢复路径; + * 2. 把备份应用搬运到主应用区; + * 3. 跳转运行。 + */ + printf("[BOOT] path=restore_backup_then_jump\r\n"); CAN0_transmiter.sendBackup(); move_app_data(); ota.jumpToApplication(); } else { + /** + * 当前区和备份区都不可用: + * 只能长期停留在 Bootloader,等待外部重新下发固件。 + */ + printf("[BOOT] path=stay_boot_wait_image\r\n"); + uint32_t hb_wait = 0U; while (1) { - CAN0_transmiter.communication_check(); - ota.process(); + pollAllLinks(); + heartbeatPrint(hb_wait, 10U, "stay_boot_wait_image"); + delay_1ms(10); } } } } +/** + * @brief Bootloader 程序入口。 + * + * @return 理论上不会返回;若异常返回则维持空转。 + */ int main(void) { sys.initHardware(); sys.run(); + + /** 理论上 run() 不会返回,这里仅做保险。 */ while (1) { } -} +} \ No newline at end of file diff --git a/GD32E50X_BOOT/main.h b/GD32E50X_BOOT/main.h index 4dd2dfc..7ac4d0d 100644 --- a/GD32E50X_BOOT/main.h +++ b/GD32E50X_BOOT/main.h @@ -3,9 +3,35 @@ #include +/** + * @brief Bootloader 顶层调度对象。 + * + * 负责初始化系统硬件,并根据 Flash 中保存的应用状态决定 + * 是直接跳转主应用、等待 OTA 请求,还是执行备份恢复流程。 + */ class BootloaderSystem { public: + /** + * @brief 初始化 Bootloader 运行所需的硬件外设。 + * + * 初始化内容包括 SysTick、串口、CAN、OTA 状态机、SPI OTA + * 以及睡眠状态检查。 + * + * @return 无。 + */ void initHardware(); + + /** + * @brief 执行 Bootloader 主流程。 + * + * 该函数会读取应用状态标志,并根据状态决定后续行为: + * - 直接跳转主应用; + * - 在限定时间内等待 OTA 请求; + * - 从备份应用区恢复后跳转; + * - 永久停留在 Bootloader 等待升级。 + * + * @return 无。 + */ void run(); }; diff --git a/GD32E50X_BOOT/sys/OTA.cpp b/GD32E50X_BOOT/sys/OTA.cpp index 4bee4da..ea79af2 100644 --- a/GD32E50X_BOOT/sys/OTA.cpp +++ b/GD32E50X_BOOT/sys/OTA.cpp @@ -16,7 +16,76 @@ extern CAN_transmiter CAN0_transmiter; OTAHandler ota; +/** + * OTA.cpp 模块说明 + * ---------------- + * 这里实现 Bootloader 的核心 OTA 逻辑: + * 1. 握手与会话密钥派生 + * 2. 固件大小确认 + * 3. 擦除应用区 + * 4. 固件包校验、解密、写 Flash + * 5. 超时处理、错误上报、应用跳转 + * + * 设计上,OTA 状态机与底层传输层解耦: + * - CAN 与 SPI 只负责收发原始消息 + * - 进入本文件后统一走 handleLinkMessage() + */ + +/** + * @brief CAN 链路回包发送适配器。 + * + * @param type OTA 回包类型。 + * @param len 有效载荷长度。 + * @param data 指向有效载荷缓冲区的指针。 + * @return 无。 + */ +static void ota_can_sender(ota_link_tx_type_t type, u8 len, const u8 *data) { + /** + * 将 OTA 统一回包类型映射到具体 CAN ID。 + * 当前只定义了 ACK 与 WAIT 两类返回帧。 + */ + u32 can_id = 0U; + if (type == OTA_LINK_TX_ACK) { + can_id = CANFD_OTA_ACK_ID; + } else if (type == OTA_LINK_TX_WAIT) { + can_id = CANFD_OTA_WAIT_ID; + } else { + return; + } + CAN0_transmiter.CANFD_AsyncSend(can_id, len, const_cast(data)); +} + +/** + * @brief SPI 链路回包发送占位适配器。 + * + * @param type OTA 回包类型。 + * @param len 有效载荷长度。 + * @param data 指向有效载荷缓冲区的指针。 + * @return 无。 + */ +static void ota_spi_sender(ota_link_tx_type_t type, u8 len, const u8 *data) { + (void)type; + (void)len; + (void)data; + + /** + * 这里仍保留占位实现。 + * 当前 SPI OTA 的真正回包发送,是由 device/SpiOta.cpp 内的 spi_ota_sender() 接管的。 + */ +} + +/** + * @brief 向指定 Flash 地址写入一个 32 位字。 + * + * @param address 目标地址。 + * @param data 目标数据。 + * @return FMC 编程状态码。 + */ static inline fmc_state_enum write_ADDRESS(u32 address, u32 data) { + /** + * 对单个配置字进行安全写入。 + * 主要用于 OTA 状态页 / 睡眠配置页中的标志位更新。 + */ fmc_unlock(); fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGAERR | FMC_FLAG_PGERR); fmc_state_enum status = fmc_word_program(address, data); @@ -24,7 +93,20 @@ static inline fmc_state_enum write_ADDRESS(u32 address, u32 data) { return status; } +/** + * @brief 更新 OTA 配置页中的指定状态字。 + * + * @param addr 目标配置字地址。 + * @param data 目标写入值。 + * @return FLASH_EEPROM_OK 表示成功,FLASH_EEPROM_ERROR 表示失败。 + */ u8 OTA_SET(u32 addr, u32 data) { + /** + * OTA 配置页更新策略: + * - 如果目标值本来就是 data,直接返回成功 + * - 如果只是把某个字从擦除态写成 OTA_AVAL(0),可以直接写 + * - 其它情况(尤其涉及从 0 改回 1)则必须整页擦除后重写全部 6 个配置字 + */ fmc_state_enum fmc_status; u32 temp_val[OTA_CONFIG_NUM]; volatile u32 *flash_ptr = (volatile u32 *)addr; @@ -34,6 +116,9 @@ u8 OTA_SET(u32 addr, u32 data) { return FLASH_EEPROM_OK; } + /** + * Flash 只能把 bit 从 1 写成 0,所以写 OTA_AVAL(0x00000000) 时可以尝试直接编程。 + */ if (data == OTA_AVAL) { fmc_status = write_ADDRESS(addr, data); if (fmc_status == FMC_READY) { @@ -41,6 +126,7 @@ u8 OTA_SET(u32 addr, u32 data) { } } + /** 读取当前配置页中的全部状态,供擦除后重写。 */ flash_ptr = (volatile u32 *)n_APP_LATEST_AVAL_ADDR; temp_val[0] = *flash_ptr; flash_ptr = (volatile u32 *)n_APP_BACKUP_AVAL_ADDR; @@ -54,6 +140,7 @@ u8 OTA_SET(u32 addr, u32 data) { flash_ptr = (volatile u32 *)n_APP_BACKUP_CHECK_ADDR; temp_val[5] = *flash_ptr; + /** 整页擦除后重建配置页。 */ fmc_unlock(); fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGAERR | FMC_FLAG_PGERR); fmc_status = fmc_page_erase(OTA_CONFIG_PAGE_ADDR); @@ -84,41 +171,128 @@ u8 OTA_SET(u32 addr, u32 data) { return FLASH_EEPROM_OK; } +/** + * @brief 从 4 字节小端数组中提取 32 位整数。 + * + * @param array 指向至少 4 字节数组的指针。 + * @return 提取出的 32 位无符号整数。 + */ static inline uint32_t extract_u32_from_4bytes(const uint8_t *array) { + /** + * 协议里数值字段按小端排列存放: + * byte0 -> 最低字节,byte3 -> 最高字节 + */ return ((uint32_t)array[3] << 24) | ((uint32_t)array[2] << 16) | ((uint32_t)array[1] << 8) | (uint32_t)array[0]; } -void OTAHandler::init() { +/** + * @brief 将 32 位整数按小端写入 4 字节数组。 + */ +static inline void write_u32_to_4bytes(uint8_t *array, uint32_t value) { + array[0] = (uint8_t)(value & 0xFFU); + array[1] = (uint8_t)((value >> 8) & 0xFFU); + array[2] = (uint8_t)((value >> 16) & 0xFFU); + array[3] = (uint8_t)((value >> 24) & 0xFFU); } +/** + * @brief 发送带 0xBA 0xC0 头的结构化 ACK。 + */ +static inline void send_structured_ack(uint32_t seq_or_flag) { + u8 send_data[6] = {0xBA, 0xC0, 0x00, 0x00, 0x00, 0x00}; + write_u32_to_4bytes(&send_data[2], seq_or_flag); + send_ack_frame(6, send_data); +} + +/** + * @brief 初始化 OTA 状态机。 + * + * @return 无。 + */ +void OTAHandler::init() { + /** 默认回包出口先绑定到 CAN。 */ + transport_send = ota_can_sender; +} + +/** + * @brief 切换 OTA 回包出口到 CAN。 + * + * @return 无。 + */ +void ota_bind_can_transport(void) { + ota.setTransportSender(ota_can_sender); +} + +/** + * @brief 切换 OTA 回包出口到 SPI。 + * + * @return 无。 + */ +void ota_bind_spi_transport(void) { + ota.setTransportSender(ota_spi_sender); +} + +/** + * @brief 推进 OTA 状态机后台逻辑。 + * + * @return 无。 + */ void OTAHandler::process() { + /** + * 把真正耗时的 Flash 擦除动作推迟到主循环做, + * 避免在接收消息的处理路径里执行过重操作。 + */ if (pending_flash_erase) { pending_flash_erase = false; eraseApplicationArea(); ota_state = OTA_STATE_RECEIVING_FIRMWARE; } + if (pending_app_jump) { + pending_app_jump = false; + delay_1ms(20); + jumpToApplication(); + return; + } + if (ota_state == OTA_STATE_IDLE) { + /** + * 空闲态持续清零超时计数,并定期发 WAIT 帧, + * 相当于告诉上位机“Bootloader 在线,尚未进入升级事务”。 + */ ota_time = 0; static u8 zero[1] = {0}; - CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_WAIT_ID, 0, zero); + send_wait_frame(0, zero); delay_1ms(10); return; } else { + /** + * 非空闲态时,按固定节奏推进超时计数。 + * 这里用 100us 粗略步进,不追求绝对精确,只做会话保活超时保护。 + */ delay_1us(100); ota_time++; } if (ota_time > OTA_TIMEOUT) { + /** + * OTA 会话超时: + * - 复位状态机到空闲态 + * - 上报超时错误 + * - 如果当前主应用仍有效,则尝试回到主应用运行 + */ ota_time = 0; ota_state = OTA_STATE_IDLE; ota_error = OTA_ERROR_TIMEOUT; + volatile u32 *flash_ptr = (volatile u32 *)n_APP_LATEST_CHECK_ADDR; u32 if_checked = *flash_ptr; flash_ptr = (volatile u32 *)n_APP_LATEST_AVAL_ADDR; u32 if_aval = *flash_ptr; - send_error_frame(OTA_ERROR_TIMEOUT); + + send_error_frame(0xFFFFFFFFU, OTA_ERROR_TIMEOUT); + if (if_checked == OTA_AVAL && if_aval == OTA_AVAL) { OTA_SET(n_APP_LATEST_AVAL_ADDR, OTA_AVAL); jumpToApplication(); @@ -126,29 +300,79 @@ void OTAHandler::process() { } } +/** + * @brief 通过当前链路发送 ACK。 + * + * @param len 有效载荷长度。 + * @param data 指向有效载荷缓冲区的指针。 + * @return 无。 + */ +void OTAHandler::sendAck(u8 len, const u8 *data) { + if (transport_send != nullptr) { + transport_send(OTA_LINK_TX_ACK, len, data); + } +} + +/** + * @brief 通过当前链路发送 WAIT。 + * + * @param len 有效载荷长度。 + * @param data 指向有效载荷缓冲区的指针。 + * @return 无。 + */ +void OTAHandler::sendWait(u8 len, const u8 *data) { + if (transport_send != nullptr) { + transport_send(OTA_LINK_TX_WAIT, len, data); + } +} + +/** + * @brief 校验主应用向量表是否合法。 + * + * @retval true 主应用向量表合法。 + * @retval false 主应用向量表非法。 + */ bool validateApplication() { + /** + * 通过应用向量表做一个最基本的合法性检查: + * 1. 初始 MSP 必须落在 SRAM 范围内 + * 2. Reset_Handler 必须落在主应用区范围内 + */ u32 *app_vector = (u32 *)APPLATEST_START_ADDR; u32 stack_ptr = app_vector[0]; u32 reset_handler = app_vector[1]; + bool stack_valid = (stack_ptr >= 0x20000000U && stack_ptr < 0x20020000U); bool reset_valid = (reset_handler >= APPLATEST_START_ADDR && reset_handler < (APPLATEST_START_ADDR + APP_MAX_SIZE)); return stack_valid && reset_valid; } +/** + * @brief 跳转执行主应用。 + * + * @return 无。 + */ void OTAHandler::jumpToApplication() { if (!validateApplication()) { + /** 向量表不合法时,拒绝跳转,避免飞到未知地址。 */ + printf("[BOOT] jump rejected: invalid app vector @0x%08lX\r\n", (unsigned long)APPLATEST_START_ADDR); return; } + printf("[BOOT] jumping to app @0x%08lX\r\n", (unsigned long)APPLATEST_START_ADDR); + + /** 把当前主应用重新标记为“有效且允许启动”。 */ OTA_SET(n_APP_LATEST_AVAL_ADDR, OTA_AVAL); OTA_SET(n_APP_LATEST_EN_ADDR, OTA_AVAL); + /** 关闭并清空所有 NVIC 中断。 */ for (int i = 0; i < 8; ++i) { NVIC->ICER[i] = 0xFFFFFFFFU; NVIC->ICPR[i] = 0xFFFFFFFFU; } + /** 关闭 Bootloader 运行过程中启用过的外设。 */ can_deinit(CAN0); rcu_system_clock_source_config(RCU_CKSYSSRC_IRC8M); @@ -160,18 +384,32 @@ void OTAHandler::jumpToApplication() { rcu_periph_clock_disable(RCU_TIMER0); rcu_periph_clock_disable(RCU_DMA0); + /** 把中断向量表切到主应用起始地址。 */ SCB->VTOR = APPLATEST_START_ADDR; + /** 读取主应用向量表中的 MSP 和 Reset_Handler。 */ uint32_t msp_value = *(__IO uint32_t *)APPLATEST_START_ADDR; uint32_t reset_handler = *(__IO uint32_t *)(APPLATEST_START_ADDR + 4U); + typedef void (*AppEntryFunc)(void); AppEntryFunc app_entry = (AppEntryFunc)reset_handler; + + /** 切栈后直接跳转执行主应用。 */ __set_MSP(msp_value); rcu_all_reset_flag_clear(); app_entry(); } +/** + * @brief 擦除当前主应用区。 + * + * @return 无。 + */ void OTAHandler::eraseApplicationArea() { + /** + * 开始真正接收新固件前,先把当前主应用状态全部标记为无效, + * 防止中途掉电后误跳到一个被擦了一半的应用。 + */ OTA_SET(n_APP_LATEST_CHECK_ADDR, OTA_NOT_AVAL); OTA_SET(n_APP_LATEST_EN_ADDR, OTA_NOT_AVAL); OTA_SET(n_APP_LATEST_AVAL_ADDR, OTA_NOT_AVAL); @@ -184,7 +422,7 @@ void OTAHandler::eraseApplicationArea() { fmc_state_enum status = fmc_page_erase(addr); if (status != FMC_READY) { ota_error = OTA_ERROR_FLASH_ERROR; - send_error_frame(OTA_ERROR_FLASH_ERROR); + send_error_frame(0xFFFFFFFFU, OTA_ERROR_FLASH_ERROR); break; } } @@ -192,7 +430,20 @@ void OTAHandler::eraseApplicationArea() { __enable_irq(); } +/** + * @brief 向主应用区写入一段固件数据。 + * + * @param offset 相对于主应用起始地址的偏移量。 + * @param data 指向待写入数据的指针。 + * @param size 数据长度。 + * @return 无。 + */ void OTAHandler::writeApplicationData(u32 offset, u8 *data, u32 size) { + /** + * 将一个分包写入主应用区: + * - 先按 4 字节对齐批量写 + * - 剩余不足 4 字节时,用 0xFF 补齐一个 word 再写入 + */ fmc_unlock(); u32 write_addr = APPLATEST_START_ADDR + offset; u32 i = 0; @@ -207,14 +458,35 @@ void OTAHandler::writeApplicationData(u32 offset, u8 *data, u32 size) { fmc_lock(); } -void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) { - if (id == CANFD_OTA_CANCEL_ID) { +/** + * @brief 处理统一抽象后的 OTA 链路消息。 + * + * @param type 链路消息类型。 + * @param data 指向消息数据缓冲区的指针。 + * @param len 消息数据长度。 + * @return 无。 + */ +void OTAHandler::handleLinkMessage(ota_link_msg_type_t type, u8 *data, u8 len) { + /** + * CANCEL:无条件终止当前 OTA 会话,回到空闲态。 + */ + if (type == OTA_LINK_MSG_CANCEL) { ota_state = OTA_STATE_IDLE; ota_time = 0; ota_error = OTA_ERROR_NONE; return; - } else if (id == CANFD_OTA_DATA_ID) { + } + /** + * DATA:根据当前状态解释为“固件分包”或“固件大小信息”等。 + */ + else if (type == OTA_LINK_MSG_DATA) { ota_time = 0; + + /** + * 正常固件数据包: + * - 固定 64 字节 + * - 含会话号、包号、48 字节密文、结束标志、CRC32 + */ if (len == 64U && ota_state == OTA_STATE_RECEIVING_FIRMWARE) { u32 receive_session_num = extract_u32_from_4bytes(data); (void)receive_session_num; @@ -222,15 +494,20 @@ void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) { u32 receive_IFEND = extract_u32_from_4bytes(data + 56); const u8 *receive_encrypted_data = data + 8; const u8 *receive_dataCRC32 = data + 60; + u8 decrypted_data[OTA_PACKET_SIZE]; u8 calculated_dataCRC32[4]; + + /** 使用当前会话密钥解密 48 字节数据区。 */ aes128_set_key(&aes_ctx, current_K_session); aes128_ecb_decrypt_48bytes(&aes_ctx, receive_encrypted_data, decrypted_data); + + /** 校验分包 CRC32(密钥参与 CRC,防止简单重放/篡改)。 */ calculate_crc32_with_key(current_K_session, decrypted_data, calculated_dataCRC32); if (memcmp(receive_dataCRC32, calculated_dataCRC32, SIZE_U32) != 0) { ota_error = OTA_ERROR_INVALID_CRC; - send_error_frame(OTA_ERROR_INVALID_CRC); - receive_packet_num -= 1U; + send_error_frame(receive_packet_num, OTA_ERROR_INVALID_CRC); + return; } else { u32 offset = receive_packet_num * OTA_PACKET_SIZE; if (offset + OTA_PACKET_SIZE <= APP_MAX_SIZE) { @@ -238,21 +515,31 @@ void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) { } else { ota_error = OTA_ERROR_INVALID_SIZE; ota_state = OTA_STATE_IDLE; - send_error_frame(OTA_ERROR_INVALID_SIZE); + send_error_frame(receive_packet_num, OTA_ERROR_INVALID_SIZE); } } + + /** + * IFEND == 0xFFFFFFFF 表示最后一包: + * 先反馈“全部写入完成,等待 FINISH_OTA”, + * 真正跳转放到收到 0x0A AC 后再执行。 + */ if (receive_IFEND == 0xFFFFFFFFU) { - u8 pack_number[4] = {0xFF, 0xFF, 0xFF, 0xFF}; - CAN0_transmiter.sendDATA_ACK(CANFD_OTA_ACK_ID, pack_number); ota_state = OTA_STATE_FINISHED; - jumpToApplication(); + send_structured_ack(0xFFFFFFFFU); return; } + + /** 正常情况下 ACK 下一个希望收到的包号。 */ u32 request_packet = receive_packet_num + 1U; - u8 pack_number[4]; - memcpy(pack_number, &request_packet, 4); - CAN0_transmiter.sendDATA_ACK(CANFD_OTA_ACK_ID, pack_number); - } else if (len == 4U && ota_state == OTA_STATE_CHECKING_FIRMWARE) { + send_structured_ack(request_packet); + } + /** + * 固件大小阶段: + * 在握手成功后,由上位机先发 4 字节固件大小, + * Bootloader 校验是否超过 APP_MAX_SIZE,并准备擦除 Flash。 + */ + else if (len == 4U && ota_state == OTA_STATE_CHECKING_FIRMWARE) { u32 new_size = *(u32 *)data; if (new_size <= APP_MAX_SIZE) { expected_size = new_size; @@ -260,83 +547,205 @@ void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) { } else { ota_error = OTA_ERROR_INVALID_SIZE; ota_state = OTA_STATE_IDLE; - send_error_frame(OTA_ERROR_INVALID_SIZE); + send_error_frame(0U, OTA_ERROR_INVALID_SIZE); return; } + + /** 把擦除动作延后到 process() 中执行。 */ pending_flash_erase = true; - u8 send_data[6] = {0xBA, 0xC0, 0x00, 0x00, 0x00, 0x00}; - CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 6, send_data); - } else if (len == 2U && ota_state == OTA_STATE_FINISHED) { - } else { + + /** 固件大小合法,返回严格 seq 语义 ACK:阶段起始包号 0。 */ + send_structured_ack(0U); + } + /** 结束态下要求显式收到 0x0A AC,确认可以切换到 APP。 */ + else if (len == 2U && ota_state == OTA_STATE_FINISHED) { + if (data[0] == 0x0AU && data[1] == 0xACU) { + if (!validateApplication()) { + ota_error = OTA_ERROR_FLASH_ERROR; + ota_state = OTA_STATE_IDLE; + send_error_frame(0xFFFFFFFFU, OTA_ERROR_FLASH_ERROR); + return; + } + + OTA_SET(n_APP_LATEST_CHECK_ADDR, OTA_AVAL); + OTA_SET(n_APP_LATEST_AVAL_ADDR, OTA_AVAL); + OTA_SET(n_APP_LATEST_EN_ADDR, OTA_AVAL); + + u8 finish_ack[2] = {0x0A, 0xAC}; + send_ack_frame(2, finish_ack); + pending_app_jump = true; + return; + } + ota_error = OTA_ERROR_INVALID_PACKET; ota_state = OTA_STATE_IDLE; - send_error_frame(OTA_ERROR_INVALID_PACKET); + send_error_frame(0xFFFFFFFFU, OTA_ERROR_INVALID_PACKET); + return; } - } else if (id == CANFD_OTA_REQ_ID) { + /** 其它长度 / 状态组合都视作非法包。 */ + else { + ota_error = OTA_ERROR_INVALID_PACKET; + ota_state = OTA_STATE_IDLE; + send_error_frame(0xFFFFFFFFU, OTA_ERROR_INVALID_PACKET); + } + } + /** + * REQ:用于握手阶段。 + */ + else if (type == OTA_LINK_MSG_REQ) { ota_time = 0; + + /** + * 第一步:上位机发固定魔术字 0x00 0xAC,申请开始握手。 + */ if (data[0] == 0x00U && data[1] == 0xACU && len == 2U && ota_state == OTA_STATE_IDLE) { u8 send_data[2] = {0x00, 0xAC}; - CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 2, send_data); + send_ack_frame(2, send_data); ota_state = OTA_STATE_WAITING_RANDOM; - } else if (len == 16U && ota_state == OTA_STATE_WAITING_RANDOM) { + } + /** + * 第二步:上位机发送 16 字节随机数 nonce_server。 + * Bootloader: + * - 读取设备 UID + * - 用主密钥加密 nonce 派生会话密钥 K_session + * - 回传 UID + nonce 片段 + 加密后的 K_session + */ + else if (len == 16U && ota_state == OTA_STATE_WAITING_RANDOM) { for (u8 i = 0; i < 16U; ++i) { nonce_server[i] = data[i]; } + getDeviceSerialNumber(device_uid); aes128_set_key(&aes_ctx, K_master); + u8 K_session[16]; aes128_encrypt_block(&aes_ctx, nonce_server, K_session); + u8 encrypted_Ksession[16]; u8 temp_block[AES_BLOCK_SIZE]; aes128_encrypt_block(&aes_ctx, K_session, temp_block); memcpy(encrypted_Ksession, temp_block, 16); + u8 handshake_response[36]; memcpy(handshake_response, device_uid, 12); memcpy(handshake_response + 12, nonce_server + 8, 8); memcpy(handshake_response + 20, encrypted_Ksession, 16); - CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 36, handshake_response); + send_ack_frame(36, handshake_response); + memcpy(current_K_session, K_session, 16); ota_state = OTA_STATE_WAITING_CONFIRM; - } else if (len == 16U && ota_state == OTA_STATE_WAITING_CONFIRM) { + } + /** + * 第三步:上位机使用会话密钥加密 (nonce_server XOR 0x55),回传 16 字节确认块。 + * Bootloader 解密后比对,成功则握手完成。 + */ + else if (len == 16U && ota_state == OTA_STATE_WAITING_CONFIRM) { u8 plaintext[16]; u8 expected[16]; u8 encrypted_confirm[16]; memcpy(encrypted_confirm, data, 16); + aes128_set_key(&aes_ctx, current_K_session); aes128_decrypt_block(&aes_ctx, encrypted_confirm, plaintext); for (int i = 0; i < 16; ++i) { expected[i] = nonce_server[i] ^ 0x55U; } + if (memcmp(plaintext, expected, 16) != 0) { ota_error = OTA_ERROR_INVALID_KEY; ota_state = OTA_STATE_IDLE; - send_error_frame(OTA_ERROR_INVALID_KEY); + send_error_frame(0xFFFFFFFFU, OTA_ERROR_INVALID_KEY); return; } + u8 send_data[2] = {0xBA, 0xC0}; - CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 2, send_data); + send_ack_frame(2, send_data); ota_state = OTA_STATE_CHECKING_FIRMWARE; - } else { + } + /** 其它情况一律判定为握手非法。 */ + else { ota_error = OTA_ERROR_INVALID_HANDSHAKE; ota_state = OTA_STATE_IDLE; - send_error_frame(OTA_ERROR_INVALID_HANDSHAKE); + send_error_frame(0xFFFFFFFFU, OTA_ERROR_INVALID_HANDSHAKE); return; } } } -void send_error_frame(u8 error) { - u8 error_frame[1] = {error}; - CAN0_transmiter.CANFD_AsyncSend(CANFD_OTA_ACK_ID, 1, error_frame); +/** + * @brief 兼容旧接口:按 CAN ID 分发 OTA 消息。 + * + * @param id CAN 扩展帧 ID。 + * @param data 指向消息数据缓冲区的指针。 + * @param len 消息数据长度。 + * @return 无。 + */ +void OTAHandler::handleOTAMessage(u32 id, u8 *data, u8 len) { + /** 兼容旧的“按 CAN ID 分发”调用方式。 */ + if (id == CANFD_OTA_CANCEL_ID) { + handleLinkMessage(OTA_LINK_MSG_CANCEL, data, len); + } else if (id == CANFD_OTA_DATA_ID) { + handleLinkMessage(OTA_LINK_MSG_DATA, data, len); + } else if (id == CANFD_OTA_REQ_ID) { + handleLinkMessage(OTA_LINK_MSG_REQ, data, len); + } } +/** + * @brief 发送 OTA ACK 帧。 + * + * @param len 有效载荷长度。 + * @param data 指向有效载荷缓冲区的指针。 + * @return 无。 + */ +void send_ack_frame(u8 len, const u8 *data) { + ota.sendAck(len, data); +} + +/** + * @brief 发送 OTA WAIT 帧。 + * + * @param len 有效载荷长度。 + * @param data 指向有效载荷缓冲区的指针。 + * @return 无。 + */ +void send_wait_frame(u8 len, const u8 *data) { + ota.sendWait(len, data); +} + +/** + * @brief 发送 OTA 错误帧。 + * + * @param error 错误码。 + * @return 无。 + */ +void send_error_frame(u32 packet_num, u8 error) { + /** + * 结构化错误帧: + * [0..1] = 0xBA 0xC0 + * [2..5] = 相关包号(小端) + * [6] = 错误码 + */ + u8 error_frame[7] = {0xBA, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, error}; + write_u32_to_4bytes(&error_frame[2], packet_num); + send_ack_frame(7, error_frame); +} + +/** + * @brief 读取芯片唯一序列号。 + * + * @param buffer 指向至少 12 字节输出缓冲区的指针。 + * @return 无。 + */ void getDeviceSerialNumber(u8 *buffer) { + /** 从 GD32 固定 UID 地址读取 96bit 设备序列号。 */ volatile uint32_t *lsb = (volatile uint32_t *)DEVICE_SERIAL_ADDR_LSB; volatile uint32_t *mid = (volatile uint32_t *)DEVICE_SERIAL_ADDR_MID; volatile uint32_t *msb = (volatile uint32_t *)DEVICE_SERIAL_ADDR_MSB; uint32_t serial_lsb = *lsb; uint32_t serial_mid = *mid; uint32_t serial_msb = *msb; + for (int i = 0; i < 4; ++i) { buffer[i] = (u8)(serial_lsb >> (i * 8)); buffer[i + 4] = (u8)(serial_mid >> (i * 8)); @@ -344,7 +753,19 @@ void getDeviceSerialNumber(u8 *buffer) { } } +/** + * @brief 将备份应用区整份固件搬运到当前主应用区。 + * + * @return FMC 状态码;CRC 校验失败时返回 0xFF。 + */ fmc_state_enum move_app_data() { + /** + * 把备份应用区整体复制到当前主应用区: + * 1. 先擦当前主应用区 + * 2. 计算备份区 CRC + * 3. 逐 word 拷贝非 0xFFFFFFFF 的数据 + * 4. 再计算目标区 CRC 比较,确认搬运成功 + */ fmc_state_enum fmc_status = FMC_READY; __disable_irq(); fmc_unlock(); @@ -389,20 +810,37 @@ fmc_state_enum move_app_data() { return fmc_status; } +/** + * @brief 对会话密钥和数据区执行 CRC32 计算。 + * + * @param key 指向 16 字节会话密钥的指针。 + * @param data 指向 48 字节数据区的指针。 + * @param output 指向 4 字节输出缓冲区的指针。 + * @return 无。 + */ void calculate_crc32_with_key(const u8 *key, const u8 *data, u8 *output) { + /** + * 计算方式: + * 1. 先把 16 字节会话密钥喂入 CRC32 + * 2. 再把 48 字节有效数据喂入 CRC32 + * 3. 最终按小端输出 4 字节结果 + */ uint32_t crc = 0xFFFFFFFFU; + for (int i = 0; i < 16; ++i) { crc ^= key[i]; for (int j = 0; j < 8; ++j) { crc = (crc >> 1) ^ (0xEDB88320U & (0U - (crc & 1U))); } } + for (u32 i = 0; i < OTA_PACKET_SIZE; ++i) { crc ^= data[i]; for (int j = 0; j < 8; ++j) { crc = (crc >> 1) ^ (0xEDB88320U & (0U - (crc & 1U))); } } + crc ^= 0xFFFFFFFFU; output[0] = (u8)(crc & 0xFFU); output[1] = (u8)((crc >> 8) & 0xFFU); diff --git a/GD32E50X_BOOT/sys/OTA.h b/GD32E50X_BOOT/sys/OTA.h index 3cbfd93..2830fcd 100644 --- a/GD32E50X_BOOT/sys/OTA.h +++ b/GD32E50X_BOOT/sys/OTA.h @@ -7,29 +7,153 @@ #include "gd32e50x.h" #include +/** + * @brief OTA 统一链路消息类型。 + * + * 无论底层来自 CAN 还是 SPI,进入 OTA 状态机前都先映射成这三类。 + */ +typedef enum { + OTA_LINK_MSG_REQ = 0, + OTA_LINK_MSG_DATA, + OTA_LINK_MSG_CANCEL +} ota_link_msg_type_t; + +/** + * @brief OTA 状态机向下层链路发送时使用的消息类型。 + */ +typedef enum { + OTA_LINK_TX_ACK = 0, + OTA_LINK_TX_WAIT +} ota_link_tx_type_t; + +/** + * @brief OTA 传输层发送函数类型。 + * + * @param type 回包类型,ACK 或 WAIT。 + * @param len 有效载荷长度,单位为字节。 + * @param data 指向有效载荷缓冲区的指针。 + */ +typedef void (*ota_send_fn_t)(ota_link_tx_type_t type, u8 len, const u8 *data); + +/** + * @brief Bootloader OTA 升级核心状态机。 + * + * 负责握手协商、固件大小检查、擦除应用区、接收与写入固件分包、 + * 错误处理以及升级完成后的应用跳转。 + */ class OTAHandler { public: - u32 ota_stateota_time; - u32 received_size; - u32 expected_size; + u32 ota_stateota_time; /**< 历史遗留字段,当前实现未实际使用。 */ + u32 received_size; /**< 已接收总字节数。 */ + u32 expected_size; /**< 预期固件总字节数。 */ + /** + * @brief 初始化 OTA 状态机与默认发送通道。 + * + * @return 无。 + */ void init(); + + /** + * @brief 推进 OTA 状态机的后台处理逻辑。 + * + * 主要处理延迟擦除、空闲等待与超时判断。 + * + * @return 无。 + */ void process(); + + /** + * @brief 判断当前是否处于 OTA 活跃状态。 + * + * @retval true 状态机当前不处于空闲态。 + * @retval false 状态机当前处于空闲态。 + */ bool isActive() const { return ota_state != OTA_STATE_IDLE; } + /** + * @brief 设置当前底层回包发送函数。 + * + * @param sender 底层发送函数指针。 + * @return 无。 + */ + void setTransportSender(ota_send_fn_t sender) { transport_send = sender; } + + /** + * @brief 通过当前绑定的传输层发送 ACK。 + * + * @param len 有效载荷长度。 + * @param data 指向有效载荷缓冲区的指针。 + * @return 无。 + */ + void sendAck(u8 len, const u8 *data); + + /** + * @brief 通过当前绑定的传输层发送 WAIT。 + * + * @param len 有效载荷长度。 + * @param data 指向有效载荷缓冲区的指针。 + * @return 无。 + */ + void sendWait(u8 len, const u8 *data); + + /** + * @brief 处理统一抽象后的 OTA 链路消息。 + * + * @param type 链路消息类型。 + * @param data 指向消息数据缓冲区的指针。 + * @param len 消息数据长度。 + * @return 无。 + */ + void handleLinkMessage(ota_link_msg_type_t type, u8 *data, u8 len); + + /** + * @brief 兼容旧接口:按 CAN ID 处理 OTA 消息。 + * + * @param id CAN 扩展帧 ID。 + * @param data 指向消息数据缓冲区的指针。 + * @param len 消息数据长度。 + * @return 无。 + */ void handleOTAMessage(u32 id, u8 *data, u8 len); + + /** + * @brief 关闭 Bootloader 运行环境并跳转执行主应用。 + * + * @return 无。 + */ void jumpToApplication(); private: - u32 ota_time; + u32 ota_time; /**< OTA 会话计时器。 */ + + /** + * @brief 擦除当前主应用区。 + * + * @return 无。 + */ void eraseApplicationArea(); + + /** + * @brief 向当前主应用区写入一段固件分片。 + * + * @param offset 相对于主应用起始地址的偏移量。 + * @param data 指向待写入数据的指针。 + * @param size 本次写入的数据长度。 + * @return 无。 + */ void writeApplicationData(u32 offset, u8 *data, u32 size); - bool pending_flash_erase = false; - u32 pending_flash_offset = 0; - u8 pending_flash_data[64]; - u8 pending_flash_size = 0; + bool pending_flash_erase = false; /**< 是否存在待处理的延迟擦除请求。 */ + bool pending_app_jump = false; /**< 是否存在待处理的应用跳转请求。 */ + u32 pending_flash_offset = 0; /**< 预留:批量写入方案使用的偏移字段。 */ + u8 pending_flash_data[64]; /**< 预留:批量写入方案使用的数据缓冲。 */ + u8 pending_flash_size = 0; /**< 预留:批量写入方案使用的数据长度。 */ + ota_send_fn_t transport_send = nullptr; /**< 当前底层回包发送函数。 */ + /** + * @brief OTA 流程状态定义。 + */ typedef enum { OTA_STATE_IDLE = 0, OTA_STATE_WAITING_RANDOM, @@ -39,6 +163,9 @@ class OTAHandler { OTA_STATE_FINISHED } ota_state_t; + /** + * @brief OTA 错误类型定义。 + */ typedef enum { OTA_ERROR_NONE = 0, OTA_ERROR_TIMEOUT, @@ -50,19 +177,95 @@ class OTAHandler { OTA_ERROR_INVALID_SIZE } ota_error_t; - u8 device_uid[12]; - u8 current_K_session[16]; - u8 nonce_server[16]; - aes128_context aes_ctx; - ota_state_t ota_state = OTA_STATE_IDLE; - ota_error_t ota_error = OTA_ERROR_NONE; + u8 device_uid[12]; /**< 芯片 96bit UID。 */ + u8 current_K_session[16]; /**< 当前会话密钥。 */ + u8 nonce_server[16]; /**< 上位机发来的随机数。 */ + aes128_context aes_ctx; /**< AES 上下文。 */ + ota_state_t ota_state = OTA_STATE_IDLE; /**< 当前 OTA 状态。 */ + ota_error_t ota_error = OTA_ERROR_NONE; /**< 当前 OTA 错误码。 */ }; +/** + * @brief 读取芯片 UID。 + * + * @param buffer 指向至少 12 字节输出缓冲区的指针。 + * @return 无。 + */ void getDeviceSerialNumber(u8 *buffer); + +/** + * @brief 使用会话密钥和数据区计算 CRC32。 + * + * @param key 指向 16 字节会话密钥的指针。 + * @param data 指向 48 字节数据区的指针。 + * @param output 指向 4 字节输出缓冲区的指针。 + * @return 无。 + */ void calculate_crc32_with_key(const u8 *key, const u8 *data, u8 *output); -void send_error_frame(u8 error); + +/** + * @brief 将 OTA 回包出口切换到 CAN。 + * + * @return 无。 + */ +void ota_bind_can_transport(void); + +/** + * @brief 将 OTA 回包出口切换到 SPI。 + * + * @return 无。 + */ +void ota_bind_spi_transport(void); + +/** + * @brief 发送结构化 OTA 错误帧。 + * + * @param packet_num 相关包号;非分包场景可传 0xFFFFFFFF。 + * @param error 错误码。 + * @return 无。 + */ +void send_error_frame(u32 packet_num, u8 error); + +/** + * @brief 发送 OTA ACK 帧。 + * + * @param len 有效载荷长度。 + * @param data 指向有效载荷缓冲区的指针。 + * @return 无。 + */ +void send_ack_frame(u8 len, const u8 *data); + +/** + * @brief 发送 OTA WAIT 帧。 + * + * @param len 有效载荷长度。 + * @param data 指向有效载荷缓冲区的指针。 + * @return 无。 + */ +void send_wait_frame(u8 len, const u8 *data); + +/** + * @brief 校验主应用向量表是否有效。 + * + * @retval true 应用向量表看起来合法。 + * @retval false 应用向量表不合法。 + */ bool validateApplication(); + +/** + * @brief 从备份应用区搬运整份固件到当前主应用区。 + * + * @return FMC 返回的状态码;CRC 不一致时返回 0xFF。 + */ fmc_state_enum move_app_data(); + +/** + * @brief 更新 OTA 配置页中的某个标志字。 + * + * @param addr 目标配置字地址。 + * @param data 目标写入值。 + * @return FLASH_EEPROM_OK 表示成功,FLASH_EEPROM_ERROR 表示失败。 + */ u8 OTA_SET(u32 addr, u32 data); #endif diff --git a/GD32E50X_BOOT/sys/aes128.cpp b/GD32E50X_BOOT/sys/aes128.cpp index c70a577..10b1e17 100644 --- a/GD32E50X_BOOT/sys/aes128.cpp +++ b/GD32E50X_BOOT/sys/aes128.cpp @@ -1,6 +1,6 @@ #include "aes128.h" -// S盒 (Substitution Box) +/** S盒 (Substitution Box) */ static const u8 sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, @@ -25,7 +25,7 @@ static const u8 sbox[256] = { 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; -// 逆S盒 (InvSBox) +/** 逆S盒 (InvSBox) */ const u8 inv_sbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, @@ -50,50 +50,69 @@ const u8 inv_sbox[256] = { 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}; -// 轮常量 +/** 轮常量 */ static const u8 rcon[10] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; -// 伽罗瓦域乘法 (xtime) - 确保正确 +/** 伽罗瓦域乘法 (xtime) - 确保正确 */ static u8 xtime(u8 x) { return (x << 1) ^ (((x >> 7) & 1) * 0x1b); } -// 关键修复:AES状态矩阵是列优先排列! -// 内存布局应该是:s00, s10, s20, s30, s01, s11, s21, s31, ... -// 而不是行优先 +/** 关键修复:AES状态矩阵是列优先排列! */ +/** 内存布局应该是:s00, s10, s20, s30, s01, s11, s21, s31, ... */ +/** 而不是行优先 */ -// 轮密钥加 - 无需修改 +/** 轮密钥加 - 无需修改 */ +/** + * @brief 对状态矩阵执行轮密钥加。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @param round_key 指向 16 字节轮密钥的指针。 + * @return 无。 + */ void add_round_key(u8 *state, const u8 *round_key) { for (u8 i = 0; i < 16; i++) { state[i] ^= round_key[i]; } } -// 字节替换 - 无需修改 +/** 字节替换 - 无需修改 */ +/** + * @brief 对状态矩阵执行字节替换。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void sub_bytes(u8 *state) { for (u8 i = 0; i < 16; i++) { state[i] = sbox[state[i]]; } } -// 行移位 - 修复为列优先排列 +/** 行移位 - 修复为列优先排列 */ +/** + * @brief 对状态矩阵执行行移位。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void shift_rows(u8 *state) { u8 temp; - // AES状态矩阵(列优先): - // 列0: state[0], state[1], state[2], state[3] -> 行0,1,2,3 - // 列1: state[4], state[5], state[6], state[7] -> 行0,1,2,3 - // 列2: state[8], state[9], state[10], state[11] -> 行0,1,2,3 - // 列3: state[12], state[13], state[14], state[15] -> 行0,1,2,3 + /** AES状态矩阵(列优先): */ + /** 列0: state[0], state[1], state[2], state[3] -> 行0,1,2,3 */ + /** 列1: state[4], state[5], state[6], state[7] -> 行0,1,2,3 */ + /** 列2: state[8], state[9], state[10], state[11] -> 行0,1,2,3 */ + /** 列3: state[12], state[13], state[14], state[15] -> 行0,1,2,3 */ - // 第1行(索引0,4,8,12)不移位 - // 第2行(索引1,5,9,13)左移1位 + /** 第1行(索引0,4,8,12)不移位 */ + /** 第2行(索引1,5,9,13)左移1位 */ temp = state[1]; state[1] = state[5]; state[5] = state[9]; state[9] = state[13]; state[13] = temp; - // 第3行(索引2,6,10,14)左移2位 + /** 第3行(索引2,6,10,14)左移2位 */ temp = state[2]; state[2] = state[10]; state[10] = temp; @@ -101,7 +120,7 @@ void shift_rows(u8 *state) { state[6] = state[14]; state[14] = temp; - // 第4行(索引3,7,11,15)左移3位 + /** 第4行(索引3,7,11,15)左移3位 */ temp = state[3]; state[3] = state[15]; state[15] = state[11]; @@ -109,25 +128,31 @@ void shift_rows(u8 *state) { state[7] = temp; } -// 列混合 - 修复为正确的实现 +/** 列混合 - 修复为正确的实现 */ +/** + * @brief 对状态矩阵执行列混合。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void mix_columns(u8 *state) { u8 a[4], b[4]; - // 处理每一列 + /** 处理每一列 */ for (u8 col = 0; col < 4; col++) { - // 获取当前列的4个字节 + /** 获取当前列的4个字节 */ a[0] = state[col * 4 + 0]; a[1] = state[col * 4 + 1]; a[2] = state[col * 4 + 2]; a[3] = state[col * 4 + 3]; - // 计算混合后的值 + /** 计算混合后的值 */ b[0] = xtime(a[0]) ^ xtime(a[1]) ^ a[1] ^ a[2] ^ a[3]; b[1] = a[0] ^ xtime(a[1]) ^ xtime(a[2]) ^ a[2] ^ a[3]; b[2] = a[0] ^ a[1] ^ xtime(a[2]) ^ xtime(a[3]) ^ a[3]; b[3] = xtime(a[0]) ^ a[0] ^ a[1] ^ a[2] ^ xtime(a[3]); - // 存回结果 + /** 存回结果 */ state[col * 4 + 0] = b[0]; state[col * 4 + 1] = b[1]; state[col * 4 + 2] = b[2]; @@ -135,7 +160,7 @@ void mix_columns(u8 *state) { } } -// 伽罗瓦域乘法 (用于逆列混合) +/** 伽罗瓦域乘法 (用于逆列混合) */ static u8 gf_mul(u8 a, u8 b) { u8 p = 0; u8 high_bit; @@ -147,32 +172,44 @@ static u8 gf_mul(u8 a, u8 b) { high_bit = a & 0x80; a <<= 1; if (high_bit) { - a ^= 0x1b; // x^8 + x^4 + x^3 + x + 1 + a ^= 0x1b; /**< x^8 + x^4 + x^3 + x + 1 */ } b >>= 1; } return p; } -// 逆字节替换 +/** 逆字节替换 */ +/** + * @brief 对状态矩阵执行逆字节替换。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void inv_sub_bytes(u8 *state) { for (u8 i = 0; i < 16; i++) { state[i] = inv_sbox[state[i]]; } } -// 逆行移位 - 与shift_rows对应 +/** 逆行移位 - 与shift_rows对应 */ +/** + * @brief 对状态矩阵执行逆行移位。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void inv_shift_rows(u8 *state) { u8 temp; - // 第2行右移1位 + /** 第2行右移1位 */ temp = state[13]; state[13] = state[9]; state[9] = state[5]; state[5] = state[1]; state[1] = temp; - // 第3行右移2位 + /** 第3行右移2位 */ temp = state[2]; state[2] = state[10]; state[10] = temp; @@ -180,7 +217,7 @@ void inv_shift_rows(u8 *state) { state[6] = state[14]; state[14] = temp; - // 第4行右移3位 + /** 第4行右移3位 */ temp = state[7]; state[7] = state[11]; state[11] = state[15]; @@ -188,19 +225,25 @@ void inv_shift_rows(u8 *state) { state[3] = temp; } -// 逆列混合 - 正确实现 +/** 逆列混合 - 正确实现 */ +/** + * @brief 对状态矩阵执行逆列混合。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void inv_mix_columns(u8 *state) { u8 a[4], b[4]; - // 处理每一列 + /** 处理每一列 */ for (u8 col = 0; col < 4; col++) { - // 获取当前列的4个字节 + /** 获取当前列的4个字节 */ a[0] = state[col * 4 + 0]; a[1] = state[col * 4 + 1]; a[2] = state[col * 4 + 2]; a[3] = state[col * 4 + 3]; - // 计算逆混合后的值 + /** 计算逆混合后的值 */ b[0] = gf_mul(0x0e, a[0]) ^ gf_mul(0x0b, a[1]) ^ gf_mul(0x0d, a[2]) ^ gf_mul(0x09, a[3]); b[1] = gf_mul(0x09, a[0]) ^ gf_mul(0x0e, a[1]) ^ gf_mul(0x0b, a[2]) ^ @@ -210,7 +253,7 @@ void inv_mix_columns(u8 *state) { b[3] = gf_mul(0x0b, a[0]) ^ gf_mul(0x0d, a[1]) ^ gf_mul(0x09, a[2]) ^ gf_mul(0x0e, a[3]); - // 存回结果 + /** 存回结果 */ state[col * 4 + 0] = b[0]; state[col * 4 + 1] = b[1]; state[col * 4 + 2] = b[2]; @@ -218,45 +261,45 @@ void inv_mix_columns(u8 *state) { } } -// 密钥扩展 - 修复为标准实现 +/** 密钥扩展 - 修复为标准实现 */ static void key_expansion(aes128_context *ctx) { u8 temp[4]; u8 i, rcon_iter = 0; - // 复制原始密钥到第一轮密钥 + /** 复制原始密钥到第一轮密钥 */ memcpy(ctx->round_keys[0], ctx->key, 16); - // 生成10轮密钥 + /** 生成10轮密钥 */ for (i = 1; i <= 10; i++) { - // 复制前一轮最后一列 + /** 复制前一轮最后一列 */ temp[0] = ctx->round_keys[i - 1][12]; temp[1] = ctx->round_keys[i - 1][13]; temp[2] = ctx->round_keys[i - 1][14]; temp[3] = ctx->round_keys[i - 1][15]; - // 字循环 (RotWord) + /** 字循环 (RotWord) */ u8 t = temp[0]; temp[0] = temp[1]; temp[1] = temp[2]; temp[2] = temp[3]; temp[3] = t; - // 字节替换 (SubWord) + /** 字节替换 (SubWord) */ temp[0] = sbox[temp[0]]; temp[1] = sbox[temp[1]]; temp[2] = sbox[temp[2]]; temp[3] = sbox[temp[3]]; - // 轮常量异或 + /** 轮常量异或 */ temp[0] ^= rcon[i - 1]; - // 生成新的第一列 + /** 生成新的第一列 */ ctx->round_keys[i][0] = ctx->round_keys[i - 1][0] ^ temp[0]; ctx->round_keys[i][1] = ctx->round_keys[i - 1][1] ^ temp[1]; ctx->round_keys[i][2] = ctx->round_keys[i - 1][2] ^ temp[2]; ctx->round_keys[i][3] = ctx->round_keys[i - 1][3] ^ temp[3]; - // 生成其他列 + /** 生成其他列 */ for (u8 j = 1; j < 4; j++) { ctx->round_keys[i][j * 4 + 0] = ctx->round_keys[i][(j - 1) * 4 + 0] ^ @@ -274,21 +317,34 @@ static void key_expansion(aes128_context *ctx) { } } -// 设置密钥 +/** + * @brief 设置 AES-128 密钥并执行轮密钥扩展。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param key 指向 16 字节密钥的指针。 + * @return 无。 + */ void aes128_set_key(aes128_context *ctx, const u8 *key) { memcpy(ctx->key, key, AES128_KEY_LEN); key_expansion(ctx); } -// 加密单个块 +/** + * @brief 加密单个 16 字节分组。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param input 指向输入分组的指针。 + * @param output 指向输出缓冲区的指针。 + * @return 无。 + */ void aes128_encrypt_block(aes128_context *ctx, const u8 *input, u8 *output) { - // 复制输入到状态 + /** 复制输入到状态 */ memcpy(ctx->state, input, AES_BLOCK_SIZE); - // 初始轮密钥加 + /** 初始轮密钥加 */ add_round_key(ctx->state, ctx->round_keys[0]); - // 9轮标准轮 + /** 9轮标准轮 */ for (u8 round = 1; round <= 9; round++) { sub_bytes(ctx->state); shift_rows(ctx->state); @@ -296,33 +352,47 @@ void aes128_encrypt_block(aes128_context *ctx, const u8 *input, u8 *output) { add_round_key(ctx->state, ctx->round_keys[round]); } - // 最终轮 (没有mix_columns) + /** 最终轮 (没有mix_columns) */ sub_bytes(ctx->state); shift_rows(ctx->state); add_round_key(ctx->state, ctx->round_keys[10]); - // 复制结果到输出 + /** 复制结果到输出 */ memcpy(output, ctx->state, AES_BLOCK_SIZE); } -// ECB模式加密48字节数据 +/** + * @brief 以 ECB 模式加密 48 字节数据。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param input 指向 48 字节输入数据的指针。 + * @param output 指向 48 字节输出缓冲区的指针。 + * @return 无。 + */ void aes128_ecb_encrypt_48bytes(aes128_context *ctx, const u8 *input, u8 *output) { - // 分3块加密 (48 = 16 * 3) + /** 分3块加密 (48 = 16 * 3) */ aes128_encrypt_block(ctx, input, output); aes128_encrypt_block(ctx, input + 16, output + 16); aes128_encrypt_block(ctx, input + 32, output + 32); } -// 解密单个块 +/** + * @brief 解密单个 16 字节分组。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param input 指向输入分组的指针。 + * @param output 指向输出缓冲区的指针。 + * @return 无。 + */ void aes128_decrypt_block(aes128_context *ctx, const u8 *input, u8 *output) { - // 复制输入到状态 + /** 复制输入到状态 */ memcpy(ctx->state, input, AES_BLOCK_SIZE); - // 初始轮密钥加(使用最后一轮密钥) + /** 初始轮密钥加(使用最后一轮密钥) */ add_round_key(ctx->state, ctx->round_keys[10]); - // 9轮标准解密轮 + /** 9轮标准解密轮 */ for (u8 round = 9; round >= 1; round--) { inv_shift_rows(ctx->state); inv_sub_bytes(ctx->state); @@ -330,41 +400,56 @@ void aes128_decrypt_block(aes128_context *ctx, const u8 *input, u8 *output) { inv_mix_columns(ctx->state); } - // 最终轮(没有inv_mix_columns) + /** 最终轮(没有inv_mix_columns) */ inv_shift_rows(ctx->state); inv_sub_bytes(ctx->state); add_round_key(ctx->state, ctx->round_keys[0]); - // 复制结果到输出 + /** 复制结果到输出 */ memcpy(output, ctx->state, AES_BLOCK_SIZE); } -// ECB模式解密48字节数据 +/** + * @brief 以 ECB 模式解密 48 字节数据。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param input 指向 48 字节输入数据的指针。 + * @param output 指向 48 字节输出缓冲区的指针。 + * @return 无。 + */ void aes128_ecb_decrypt_48bytes(aes128_context *ctx, const u8 *input, u8 *output) { - // 分3块解密 (48 = 16 * 3) + /** 分3块解密 (48 = 16 * 3) */ aes128_decrypt_block(ctx, input, output); aes128_decrypt_block(ctx, input + 16, output + 16); aes128_decrypt_block(ctx, input + 32, output + 32); } -// 验证函数:加密后解密,对比原始数据 +/** + * @brief 执行 AES 加密-解密自检。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param original_data 指向原始数据缓冲区的指针。 + * @param length 参与比对的数据长度。 + * @retval 1 验证成功。 + * @retval 0 验证失败。 + */ u8 aes128_verify_encryption(aes128_context *ctx, const u8 *original_data, - size_t length) { + size_t length) { u8 temp_ciphertext[48]; u8 temp_plaintext[48]; - u8 result = 1; // 1表示验证成功,0表示失败 + u8 result = 1; /**< 1表示验证成功,0表示失败 */ - // 1. 加密原始数据 + /** 1. 加密原始数据 */ aes128_ecb_encrypt_48bytes(ctx, original_data, temp_ciphertext); - // 2. 解密密文 + /** 2. 解密密文 */ aes128_ecb_decrypt_48bytes(ctx, temp_ciphertext, temp_plaintext); - // 3. 对比原始数据和解密后的数据 + /** 3. 对比原始数据和解密后的数据 */ for (size_t i = 0; i < length; i++) { if (original_data[i] != temp_plaintext[i]) { - result = 0; // 验证失败 + result = 0; /**< 验证失败 */ break; } } diff --git a/GD32E50X_BOOT/sys/aes128.h b/GD32E50X_BOOT/sys/aes128.h index 4d64bd8..b29a0a7 100644 --- a/GD32E50X_BOOT/sys/aes128.h +++ b/GD32E50X_BOOT/sys/aes128.h @@ -3,39 +3,142 @@ #include "cstdint" #include -// AES-128 密钥长度 (16 bytes) +/** @brief AES-128 密钥长度,单位为字节。 */ #define AES128_KEY_LEN 16 -// AES 块大小 (16 bytes) + +/** @brief AES 单个分组长度,单位为字节。 */ #define AES_BLOCK_SIZE 16 -// AES 状态结构 +/** + * @brief AES-128 上下文。 + */ typedef struct { - u8 key[AES128_KEY_LEN]; // 128位/16字节密钥 - u8 round_keys[11][16]; // 10轮 + 初始轮密钥 - u8 state[AES_BLOCK_SIZE]; // 状态矩阵 + u8 key[AES128_KEY_LEN]; /**< 原始 128bit 密钥。 */ + u8 round_keys[11][16]; /**< 扩展后的 11 组轮密钥。 */ + u8 state[AES_BLOCK_SIZE]; /**< 当前状态矩阵。 */ } aes128_context; -// 内部函数声明(需要在头文件中声明,因为解密函数会使用) +/** + * @brief 对状态矩阵执行轮密钥加操作。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @param round_key 指向 16 字节轮密钥的指针。 + * @return 无。 + */ void add_round_key(u8 *state, const u8 *round_key); + +/** + * @brief 对状态矩阵执行 SubBytes 变换。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void sub_bytes(u8 *state); + +/** + * @brief 对状态矩阵执行 ShiftRows 变换。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void shift_rows(u8 *state); + +/** + * @brief 对状态矩阵执行 MixColumns 变换。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void mix_columns(u8 *state); + +/** + * @brief 对状态矩阵执行逆字节替换。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void inv_sub_bytes(u8 *state); + +/** + * @brief 对状态矩阵执行逆行移位。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void inv_shift_rows(u8 *state); + +/** + * @brief 对状态矩阵执行逆列混合。 + * + * @param state 指向 16 字节状态矩阵的指针。 + * @return 无。 + */ void inv_mix_columns(u8 *state); -// 公共函数声明 +/** + * @brief 设置 AES-128 密钥并完成轮密钥扩展。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param key 指向 16 字节密钥的指针。 + * @return 无。 + */ void aes128_set_key(aes128_context *ctx, const u8 *key); + +/** + * @brief 加密单个 16 字节分组。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param input 指向 16 字节输入分组的指针。 + * @param output 指向 16 字节输出缓冲区的指针。 + * @return 无。 + */ void aes128_encrypt_block(aes128_context *ctx, const u8 *input, u8 *output); + +/** + * @brief 以 ECB 模式加密 48 字节数据。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param input 指向 48 字节输入数据的指针。 + * @param output 指向 48 字节输出缓冲区的指针。 + * @return 无。 + */ void aes128_ecb_encrypt_48bytes(aes128_context *ctx, const u8 *input, u8 *output); + +/** + * @brief 解密单个 16 字节分组。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param input 指向 16 字节输入分组的指针。 + * @param output 指向 16 字节输出缓冲区的指针。 + * @return 无。 + */ void aes128_decrypt_block(aes128_context *ctx, const u8 *input, u8 *output); + +/** + * @brief 以 ECB 模式解密 48 字节数据。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param input 指向 48 字节输入数据的指针。 + * @param output 指向 48 字节输出缓冲区的指针。 + * @return 无。 + */ void aes128_ecb_decrypt_48bytes(aes128_context *ctx, const u8 *input, u8 *output); + +/** + * @brief 执行 AES 加密-解密自检。 + * + * @param ctx 指向 AES 上下文的指针。 + * @param original_data 指向原始数据缓冲区的指针。 + * @param length 参与比对的数据长度。 + * @retval 1 验证成功。 + * @retval 0 验证失败。 + */ u8 aes128_verify_encryption(aes128_context *ctx, const u8 *original_data, size_t length); -// 逆S盒 (用于解密) +/** @brief 逆 S 盒查找表。 */ extern const u8 inv_sbox[256]; -#endif /* __AES_H */ \ No newline at end of file +#endif /* __AES_H */ diff --git a/GD32E50X_BOOT/sys/config.h b/GD32E50X_BOOT/sys/config.h index 04ed050..0dad1b3 100644 --- a/GD32E50X_BOOT/sys/config.h +++ b/GD32E50X_BOOT/sys/config.h @@ -3,68 +3,107 @@ #include +/** 项目内部统一使用的简写类型。 */ typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; +/** 调试开关:需要时可按模块打开。 */ #define EEP_DEBUG 0 #define DEBUG_OTA 0 #define CAN_DEBUG 0 #define SLEEP_DEBUG 0 -/* Flash layout for GD32E508VE 512KB boot project */ -static const u32 BOOTLOADER_START_ADDR = 0x08000000U; -static const u32 BOOTLOADER_SIZE = 0x00012000U; /* 72KB */ -static const u32 APPBACK_START_ADDR = 0x08012000U; -static const u32 APPLATEST_START_ADDR = 0x08046000U; -static const u32 APP_MAX_SIZE = 0x00018000U; /* 96KB */ -static const u32 FMC_PAGE_SIZE = 0x00000800U; /* 2KB, GD32E50x */ -static const u32 OTA_CONFIG_PAGE_ADDR = 0x0807E000U; -static const u32 SLEEP_CONFIG_START = 0x0807E800U; -static const u32 SLEEP_CONFIG_END = 0x0807F000U; +/** + * Flash 布局说明(GD32E508VE,512KB) + * ----------------------------------- + * 0x08000000 ~ 0x08011FFF : Bootloader 区(72KB) + * 0x08012000 ~ 0x08047FFF : 备份应用区(216KB) + * 0x08048000 ~ 0x0807DFFF : 当前主应用区(216KB) + * 0x0807E000 ~ 0x0807E7FF : OTA 状态配置页 + * 0x0807E800 ~ 0x0807EFFF : 睡眠配置页 + */ +inline constexpr u32 BOOTLOADER_START_ADDR = 0x08000000U; +inline constexpr u32 BOOTLOADER_SIZE = 0x00012000U; /**< 72KB */ +inline constexpr u32 APPBACK_START_ADDR = 0x08012000U; /**< 备份应用起始地址 */ +inline constexpr u32 APPLATEST_START_ADDR = 0x08048000U; /**< 当前有效应用起始地址 */ +inline constexpr u32 APP_MAX_SIZE = 0x00036000U; /**< 216KB */ +inline constexpr u32 FMC_PAGE_SIZE = 0x00000800U; /**< 2KB,GD32E50x 单页大小 */ +inline constexpr u32 OTA_CONFIG_PAGE_ADDR = 0x0807E000U; /**< OTA 元数据页 */ +inline constexpr u32 SLEEP_CONFIG_START = 0x0807E800U; /**< 睡眠配置页起始 */ +inline constexpr u32 SLEEP_CONFIG_END = 0x0807F000U; /**< 睡眠配置页结束(开区间) */ -static const u32 FLASH_EMPTY = 0xFFFFFFFFU; -static const u32 SLEEP_ENABLE = 0x11111111U; -static const u32 SLEEP_DISABLE = 0x00000000U; +/** Flash 默认擦除值,以及睡眠开关标志值。 */ +inline constexpr u32 FLASH_EMPTY = 0xFFFFFFFFU; +inline constexpr u32 SLEEP_ENABLE = 0x11111111U; +inline constexpr u32 SLEEP_DISABLE = 0x00000000U; -static const u32 OTA_CONFIG_NUM = 6U; -static const u32 n_APP_LATEST_AVAL_ADDR = OTA_CONFIG_PAGE_ADDR + 0x00U; -static const u32 n_APP_BACKUP_AVAL_ADDR = OTA_CONFIG_PAGE_ADDR + 0x04U; -static const u32 n_APP_LATEST_EN_ADDR = OTA_CONFIG_PAGE_ADDR + 0x08U; -static const u32 n_APP_BACKUP_EN_ADDR = OTA_CONFIG_PAGE_ADDR + 0x0CU; -static const u32 n_APP_LATEST_CHECK_ADDR = OTA_CONFIG_PAGE_ADDR + 0x10U; -static const u32 n_APP_BACKUP_CHECK_ADDR = OTA_CONFIG_PAGE_ADDR + 0x14U; +/** + * OTA 配置页一共使用 6 个 word,分别保存: + * latest_aval / backup_aval / latest_en / backup_en / latest_check / backup_check + */ +inline constexpr u32 OTA_CONFIG_NUM = 6U; +inline constexpr u32 n_APP_LATEST_AVAL_ADDR = OTA_CONFIG_PAGE_ADDR + 0x00U; +inline constexpr u32 n_APP_BACKUP_AVAL_ADDR = OTA_CONFIG_PAGE_ADDR + 0x04U; +inline constexpr u32 n_APP_LATEST_EN_ADDR = OTA_CONFIG_PAGE_ADDR + 0x08U; +inline constexpr u32 n_APP_BACKUP_EN_ADDR = OTA_CONFIG_PAGE_ADDR + 0x0CU; +inline constexpr u32 n_APP_LATEST_CHECK_ADDR = OTA_CONFIG_PAGE_ADDR + 0x10U; +inline constexpr u32 n_APP_BACKUP_CHECK_ADDR = OTA_CONFIG_PAGE_ADDR + 0x14U; -static const u32 OTA_NOT_AVAL = 0xFFFFFFFFU; -static const u32 OTA_AVAL = 0x00000000U; -static const u32 FLASH_EEPROM_OK = 0U; -static const u32 FLASH_EEPROM_ERROR = 1U; +/** + * 本项目把 0x00000000 视为“有效/可用”, + * 把 0xFFFFFFFF 视为“无效/未写入”。 + * 这样设计是因为 Flash 擦除态天然就是 0xFFFFFFFF。 + */ +inline constexpr u32 OTA_NOT_AVAL = 0xFFFFFFFFU; +inline constexpr u32 OTA_AVAL = 0x00000000U; +inline constexpr u32 FLASH_EEPROM_OK = 0U; +inline constexpr u32 FLASH_EEPROM_ERROR = 1U; -static const u32 CANFD_OTA_REQ_ID = 0x00000100U; -static const u32 CANFD_OTA_DATA_ID = 0x00000101U; -static const u32 CANFD_OTA_ACK_ID = 0x00000102U; -static const u32 CANFD_OTA_WAIT_ID = 0x00000103U; -static const u32 CANFD_OTA_CANCEL_ID = 0x00000000U; +/** CAN-FD OTA 链路使用的扩展帧 ID。 */ +inline constexpr u32 CANFD_OTA_REQ_ID = 0x00000100U; +inline constexpr u32 CANFD_OTA_DATA_ID = 0x00000101U; +inline constexpr u32 CANFD_OTA_ACK_ID = 0x00000102U; +inline constexpr u32 CANFD_OTA_WAIT_ID = 0x00000103U; +inline constexpr u32 CANFD_OTA_CANCEL_ID = 0x00000000U; -/* GD32E50x UID base address */ -static const u32 DEVICE_SERIAL_ADDR_LSB = 0x1FFFF7ACU; -static const u32 DEVICE_SERIAL_ADDR_MID = 0x1FFFF7B0U; -static const u32 DEVICE_SERIAL_ADDR_MSB = 0x1FFFF7B4U; +/** GD32E50x 芯片 UID 三段地址。 */ +inline constexpr u32 DEVICE_SERIAL_ADDR_LSB = 0x1FFFF7E8U; +inline constexpr u32 DEVICE_SERIAL_ADDR_MID = 0x1FFFF7ECU; +inline constexpr u32 DEVICE_SERIAL_ADDR_MSB = 0x1FFFF7F0U; -static const u32 OTA_PACKET_SIZE = 48U; +/** + * OTA 数据包设计: + * - 每帧总长 64 字节 + * - 其中真实加密固件数据为 48 字节 + * - 其余用于会话号、包序号、结束标志和 CRC32 + */ +inline constexpr u32 OTA_PACKET_SIZE = 48U; +/** 便于按字节/按字访问同一个 32bit 数值。 */ typedef union { u32 u; u8 b[4]; } u32_union_t; -static const uint8_t K_master[16] = { +/** + * 主密钥:用于 OTA 握手阶段派生会话密钥。 + * 当前是写死在固件中的固定密钥。 + */ +inline constexpr uint8_t K_master[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }; -static const u32 OTA_TIMEOUT = 10000U; -static const u32 APP_DELAY_BOOT_TIME = 10000U; +/** + * 超时与启动等待参数: + * - OTA_TIMEOUT:OTA 会话超时时间计数上限 + * - APP_DELAY_BOOT_TIME:发现应用存在但被禁用时,Bootloader 等待 OTA 请求的窗口 + */ +inline constexpr u32 OTA_TIMEOUT = 10000U; +inline constexpr u32 APP_DELAY_BOOT_TIME = 10000U; + +/** 常用尺寸常量。 */ static const u8 SIZE_U32 = sizeof(uint32_t); static const u8 SIZE_FLOAT = sizeof(float); diff --git a/GD32E50X_BOOT/sys/initial.cpp b/GD32E50X_BOOT/sys/initial.cpp index b37da0a..6c3fe2e 100644 --- a/GD32E50X_BOOT/sys/initial.cpp +++ b/GD32E50X_BOOT/sys/initial.cpp @@ -1,6 +1,7 @@ #include "initial.h" #include "OTA.h" #include "config.h" +#include "device/SpiOta.h" #include "core_cm33.h" #include "gd32e50x.h" #include "gd32e50x_exti.h" @@ -11,13 +12,22 @@ #include "gd32e50x_usart.h" #include "systick.h" -u8 USART0_init(void) { +/** + * @brief 初始化 USART0 调试串口。 + * + * @return 1 表示初始化完成。 + */ +u8 BootDebugUart::init() +{ + /** 打开 GPIOA 与 USART0 时钟。 */ rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_USART0); + /** PA9 = TX,PA10 = RX。 */ gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); + /** 配置串口为 115200 8N1(其余参数使用默认值)。 */ usart_deinit(USART0); usart_baudrate_set(USART0, 115200U); usart_receive_config(USART0, USART_RECEIVE_ENABLE); @@ -26,7 +36,16 @@ u8 USART0_init(void) { return 1; } -int fputc(int ch, FILE *f) throw() { +/** + * @brief printf 重定向输出函数。 + * + * @param ch 待输出字符。 + * @param f 目标文件流,当前实现未使用。 + * @return 输出字符值。 + */ +int BootDebugUart::putChar(int ch, FILE *f) +{ + /** printf 最终走到这里,通过 USART0 单字节输出。 */ (void)f; usart_data_transmit(USART0, (uint8_t)ch); while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) { @@ -34,25 +53,113 @@ int fputc(int ch, FILE *f) throw() { return ch; } -u16 get_reset_cause(void) { +/** + * @brief Redirect standard output character to the boot debug UART. + * @param ch Output character. + * @param f Stream pointer from libc. + * @return Forwarded character value. + */ +int fputc(int ch, FILE *f) throw() { return BootDebugUart::putChar(ch, f); } + +/** + * @brief Initialize USART0 through the boot debug UART helper. + * @return 1 when initialization succeeds. + */ +u8 USART0_init(void) { return BootDebugUart::init(); } + +/** + * @brief 获取复位原因。 + * + * @return 复位原因编码。 + */ +u16 BootPlatform::getResetCause(void) +{ + /** 预留:如需区分上电/看门狗/软复位等原因,可在此补齐。 */ return 0; } -void unused_pin_init(void) { +/** + * @brief Get reset cause through the platform helper. + * @return Reset-cause code. + */ +u16 get_reset_cause(void) { return BootPlatform::getResetCause(); } + +/** + * @brief 初始化未使用引脚。 + * + * @return 无。 + */ +void BootPlatform::initUnusedPins(void) +{ + /** + * 预留:如果需要降低悬空功耗,可把未使用 GPIO 统一初始化。 + * 当前只保证时钟可用,未进一步配置具体引脚。 + */ rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_GPIOC); } -void print_system_clock_info(void) { +/** + * @brief Initialize unused pins through the platform helper. + * @return none + */ +void unused_pin_init(void) { BootPlatform::initUnusedPins(); } + +/** + * @brief 打印系统时钟信息。 + * + * @return 无。 + */ +void BootPlatform::printSystemClockInfo(void) +{ + /** 预留:可在此打印系统时钟源与频率。 */ } -void scanAppFlashContent(int print_content, u32 page_count) { +/** + * @brief Print system clock info through the platform helper. + * @return none + */ +void print_system_clock_info(void) { BootPlatform::printSystemClockInfo(); } + +/** + * @brief 扫描主应用区 Flash 内容。 + * + * @param print_content 是否打印内容。 + * @param page_count 需要扫描的页数。 + * @return 无。 + */ +void BootPlatform::scanAppFlashContent(int print_content, u32 page_count) +{ + /** 预留:调试用,后续可打印主应用区内容。 */ (void)print_content; (void)page_count; } -static fmc_state_enum write_ADDRESS(u32 address, u32 data) { +/** + * @brief Scan application flash content through the platform helper. + * @param print_content Whether to print flash payload. + * @param page_count Number of pages to scan. + * @return none + */ +void scanAppFlashContent(int print_content, u32 page_count) { BootPlatform::scanAppFlashContent(print_content, page_count); } + +/** + * @brief 向指定 Flash 地址写入一个 32 位字。 + * + * @param address 目标地址。 + * @param data 目标数据。 + * @return FMC 编程状态码。 + */ +fmc_state_enum BootSleepManager::writeAddress(u32 address, u32 data) +{ + /** + * 对单个 Flash word 做安全写入: + * - 解锁 FMC + * - 清状态位 + * - 编程 + * - 重新上锁 + */ fmc_unlock(); fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGAERR | FMC_FLAG_PGERR); fmc_state_enum status = fmc_word_program(address, data); @@ -60,11 +167,24 @@ static fmc_state_enum write_ADDRESS(u32 address, u32 data) { return status; } -void enter_deep_sleep(void) { +/** + * @brief 进入深度睡眠模式。 + * + * @return 无。 + */ +void BootSleepManager::enterDeepSleep(void) +{ + /** + * 进入深睡前先关掉暂时不需要的外设时钟,降低待机功耗。 + */ rcu_periph_clock_disable(RCU_TIMER0); rcu_periph_clock_disable(RCU_TIMER1); rcu_periph_clock_disable(RCU_ADC0); + /** + * 使用 PB8 作为唤醒外部事件输入。 + * 这里配置为浮空输入,并挂接 EXTI8 上升沿触发。 + */ rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_AF); gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_8); @@ -74,22 +194,47 @@ void enter_deep_sleep(void) { exti_interrupt_enable(EXTI_8); nvic_irq_enable(EXTI5_9_IRQn, 0U, 0U); exti_interrupt_flag_clear(EXTI_8); + __enable_irq(); delay_1ms(10U); + + /** 进入深度睡眠,等待外部中断唤醒。 */ pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, PMU_LOWDRIVER_DISABLE, WFI_CMD); } -void EXTI5_9_IRQHandler(void) { +/** + * @brief 处理 EXTI5_9 中断实际逻辑。 + * + * @return 无。 + */ +void BootSleepManager::onExtiInterrupt(void) +{ + /** + * EXTI5_9 同时复用了两个来源: + * 1. PB8:深睡唤醒信号 + * 2. PD7:SPI OTA 片选信号 + */ if (exti_interrupt_flag_get(EXTI_8) != RESET) { exti_interrupt_flag_clear(EXTI_8); exti_interrupt_disable(EXTI_8); + + /** 唤醒后重新允许启动主应用。 */ OTA_SET(n_APP_LATEST_EN_ADDR, OTA_AVAL); + + /** + * 睡眠配置区按日志式写法追加状态: + * 从后往前找最后一个有效条目,再把 SLEEP_ENABLE 改写为 SLEEP_DISABLE。 + */ for (u32 address = SLEEP_CONFIG_END - SIZE_U32; address >= SLEEP_CONFIG_START; address -= SIZE_U32) { volatile u32 *flash_ptr = (volatile u32 *)address; u32 sleep_check = *flash_ptr; + if (sleep_check == FLASH_EMPTY && address > SLEEP_CONFIG_START) { continue; } else if (sleep_check == SLEEP_ENABLE && address > SLEEP_CONFIG_START) { + /** + * 若最后一个可写位置已经用满,则整页擦除后从头开始写。 + */ if (address == SLEEP_CONFIG_END - SIZE_U32) { fmc_unlock(); if (fmc_page_erase(SLEEP_CONFIG_START) != FMC_READY) { @@ -98,34 +243,86 @@ void EXTI5_9_IRQHandler(void) { } address = SLEEP_CONFIG_START - SIZE_U32; } - (void)write_ADDRESS(address + SIZE_U32, SLEEP_DISABLE); + (void)writeAddress(address + SIZE_U32, SLEEP_DISABLE); break; } else if (sleep_check == SLEEP_DISABLE) { + /** 已经记录为禁用睡眠,无需重复写。 */ break; } else { - (void)write_ADDRESS(address, SLEEP_DISABLE); + /** 配置区为空或数据异常时,直接当前位置补写禁用标记。 */ + (void)writeAddress(address, SLEEP_DISABLE); break; } } + + /** 通过软复位重新进入正常启动流程。 */ system_soft_reset(); } + + /** 继续分发给 SPI OTA 的 CS 边沿处理逻辑。 */ + spi_ota_cs_exti_handler(); } -int check_sleep(void) { +/** + * @brief 检查睡眠配置并决定是否进入深睡。 + * + * @return 0 表示已有有效配置;1 表示写默认配置失败;2 表示已写入默认禁用配置。 + */ +int BootSleepManager::check(void) +{ + /** + * 启动时检查睡眠配置页中最新的有效状态: + * - SLEEP_ENABLE -> 直接进深睡 + * - SLEEP_DISABLE -> 正常启动 + * - 全空 -> 默认写入禁用状态 + */ for (u32 address = SLEEP_CONFIG_END - SIZE_U32; address >= SLEEP_CONFIG_START; address -= SIZE_U32) { volatile u32 *flash_ptr = (volatile u32 *)address; u32 sleep_check = *flash_ptr; + if (sleep_check == FLASH_EMPTY) { continue; } else if (sleep_check == SLEEP_ENABLE) { - enter_deep_sleep(); + enterDeepSleep(); return 0; } else if (sleep_check == SLEEP_DISABLE) { return 0; } } - if (write_ADDRESS(SLEEP_CONFIG_START, SLEEP_DISABLE) != FMC_READY) { + + /** 首次运行或配置页为空:写入默认值 SLEEP_DISABLE。 */ + if (writeAddress(SLEEP_CONFIG_START, SLEEP_DISABLE) != FMC_READY) { return 1; } return 2; } + +/** + * @brief Enter deep sleep through the sleep manager. + * @return none + */ +void enter_deep_sleep(void) { BootSleepManager::enterDeepSleep(); } + +/** + * @brief Check sleep configuration through the sleep manager. + * @return Status code from BootSleepManager::check(). + */ +int check_sleep(void) { return BootSleepManager::check(); } + +/** + * @brief External interrupt handler for EXTI line group 5 to 9. + * @return none + */ +extern "C" void EXTI5_9_IRQHandler(void) +{ + BootSleepManager::onExtiInterrupt(); +} + +/** + * @brief External interrupt handler for EXTI line group 10 to 15. + * @return none + */ +extern "C" void EXTI10_15_IRQHandler(void) +{ + BootSleepManager::onExtiInterrupt(); +} diff --git a/GD32E50X_BOOT/sys/initial.h b/GD32E50X_BOOT/sys/initial.h index c51498f..c213ac8 100644 --- a/GD32E50X_BOOT/sys/initial.h +++ b/GD32E50X_BOOT/sys/initial.h @@ -7,16 +7,129 @@ extern "C" { #include #include +#include "gd32e50x_fmc.h" #include "sys/config.h" +/** + * @brief Bootloader 调试串口模块。 + * + * 负责 USART0 初始化与 printf 输出重定向。 + */ +class BootDebugUart { +public: + /** @brief 初始化 USART0 调试串口。 */ + static u8 init(); + /** @brief 输出单个字符。 */ + static int putChar(int ch, FILE *f); +}; + +/** + * @brief Bootloader 睡眠与唤醒管理模块。 + * + * 负责深度睡眠进入、睡眠配置检查以及 EXTI5_9 唤醒路径处理。 + */ +class BootSleepManager { +public: + /** @brief 进入深度睡眠模式。 */ + static void enterDeepSleep(); + /** @brief 检查睡眠配置并决定是否进入深睡。 */ + static int check(); + /** @brief 处理 EXTI5_9 中断实际逻辑。 */ + static void onExtiInterrupt(); + +private: + /** @brief 向指定 Flash 地址写入一个 32 位字。 */ + static fmc_state_enum writeAddress(u32 address, u32 data); +}; + +/** + * @brief Bootloader 平台辅助模块。 + * + * 负责复位原因读取、未使用引脚初始化、系统时钟信息打印与应用区扫描等平台杂项。 + */ +class BootPlatform { +public: + static u16 getResetCause(); + static void initUnusedPins(); + static void printSystemClockInfo(); + static void scanAppFlashContent(int print_content, u32 page_count); +}; + +/** + * @brief printf 重定向输出函数。 + * + * @param ch 待输出字符。 + * @param f 目标文件流,当前实现未使用。 + * @return 输出的字符值。 + */ int fputc(int ch, FILE *f) throw(); + +/** + * @brief 初始化 USART0 调试串口。 + * + * @return 1 表示初始化完成。 + */ u8 USART0_init(void); + +/** + * @brief 获取复位原因。 + * + * @note 当前实现为占位实现。 + * + * @return 复位原因编码。 + */ u16 get_reset_cause(void); + +/** + * @brief 初始化未使用引脚。 + * + * @return 无。 + */ void unused_pin_init(void); + +/** + * @brief 打印系统时钟信息。 + * + * @note 当前实现为占位实现。 + * + * @return 无。 + */ void print_system_clock_info(void); + +/** + * @brief 进入深度睡眠模式。 + * + * @return 无。 + */ void enter_deep_sleep(void); + +/** + * @brief 检查睡眠配置并决定是否进入深睡。 + * + * @return 0 表示已有有效配置;1 表示写默认配置失败;2 表示已写入默认禁用配置。 + */ int check_sleep(void); + +/** + * @brief EXTI5_9 中断服务函数。 + * + * @return 无。 + */ void EXTI5_9_IRQHandler(void); + +/** + * @brief EXTI10_15 中断服务函数。 + * @return 无。 + */ +void EXTI10_15_IRQHandler(void); + +/** + * @brief 扫描主应用区 Flash 内容。 + * + * @param print_content 是否打印内容。 + * @param page_count 需要扫描的页数。 + * @return 无。 + */ void scanAppFlashContent(int print_content, u32 page_count); #ifdef __cplusplus diff --git a/GD32E50X_BOOT/sys/systick.cpp b/GD32E50X_BOOT/sys/systick.cpp index 885a031..8b419cb 100644 --- a/GD32E50X_BOOT/sys/systick.cpp +++ b/GD32E50X_BOOT/sys/systick.cpp @@ -1,47 +1,164 @@ #include "systick.h" #include "gd32e50x.h" -static volatile uint32_t delay_countdown; +/** + * SysTick 驱动模块 + * ----------------- + * 提供 Bootloader 中最基础的延时与软复位能力: + * - SysTickTimer::init(): 配置 1ms 系统节拍 + * - SysTickTimer::delayUs()/delayMs()/delaySeconds(): 简单阻塞延时 + * - SysTickTimer::softReset(): 触发 MCU 软复位 + */ -void systick_config(void) { +volatile uint32_t SysTickTimer::s_delayCountdown = 0U; + +/** + * @brief 配置 SysTick 为 1ms 周期中断。 + * + * @return 无。 + */ +void SysTickTimer::init() +{ + /** 将 SysTick 配置为 1ms 一次中断。 */ if (SysTick_Config(SystemCoreClock / 1000U)) { + /** 配置失败通常意味着时钟参数异常,直接停机等待。 */ while (1) { } } + + /** 设为最高优先级,保证延时基准尽量稳定。 */ NVIC_SetPriority(SysTick_IRQn, 0x00U); } -void delay_1us(uint32_t count) { +/** + * @brief 执行微秒级粗略阻塞延时。 + * + * @param count 延时微秒数。 + * @return 无。 + */ +void SysTickTimer::delayUs(uint32_t count) +{ + /** + * 这里使用空指令忙等实现粗略微秒延时。 + * 由于循环/指令开销存在,精度不会像硬件定时器那样严格。 + */ uint32_t cycles = (SystemCoreClock / 4000000UL) * count; for (uint32_t i = 0; i < cycles; ++i) { __NOP(); } } -void delay_1ms(uint32_t count) { - delay_countdown = count; - while (delay_countdown != 0U) { +/** + * @brief 执行毫秒级阻塞延时。 + * + * @param count 延时毫秒数。 + * @return 无。 + */ +void SysTickTimer::delayMs(uint32_t count) +{ + /** 设置倒计时,由 SysTick_Handler 每毫秒递减。 */ + s_delayCountdown = count; + while (s_delayCountdown != 0U) { } } -void delay_1s(uint32_t count) { +/** + * @brief 执行秒级阻塞延时。 + * + * @param count 延时秒数。 + * @return 无。 + */ +void SysTickTimer::delaySeconds(uint32_t count) +{ + /** 基于 1ms 延时拼出秒级延时。 */ while (count--) { - delay_1ms(1000U); + delayMs(1000U); } } -void delay_decrement(void) { - if (delay_countdown != 0U) { - delay_countdown--; +/** + * @brief 递减毫秒倒计时。 + * + * @return 无。 + */ +void SysTickTimer::decrement() +{ + /** 供 SysTick 中断调用,防止无符号下溢。 */ + if (s_delayCountdown != 0U) { + s_delayCountdown--; } } -void SysTick_Handler(void) { - delay_decrement(); +/** + * @brief SysTick 中断实际处理逻辑。 + * + * @return 无。 + */ +void SysTickTimer::onInterrupt() +{ + /** 每次滴答中断只做极简工作,降低中断负担。 */ + decrement(); } -void system_soft_reset(void) { +/** + * @brief 触发 MCU 软件复位。 + * + * @return 无。 + */ +void SysTickTimer::softReset() +{ + /** 通过 CMSIS 接口触发系统软复位。 */ NVIC_SystemReset(); + + /** 理论上不会执行到这里,保留死循环作为保险。 */ while (1) { } } + +/** + * @brief Configure SysTick via the timer helper. + * @return none + */ +void systick_config(void) { SysTickTimer::init(); } + +/** + * @brief Delay for microseconds via the timer helper. + * @param count Delay time in microseconds. + * @return none + */ +void delay_1us(uint32_t count) { SysTickTimer::delayUs(count); } + +/** + * @brief Delay for milliseconds via the timer helper. + * @param count Delay time in milliseconds. + * @return none + */ +void delay_1ms(uint32_t count) { SysTickTimer::delayMs(count); } + +/** + * @brief Delay for seconds via the timer helper. + * @param count Delay time in seconds. + * @return none + */ +void delay_1s(uint32_t count) { SysTickTimer::delaySeconds(count); } + +/** + * @brief Decrement the global millisecond delay counter. + * @return none + */ +void delay_decrement(void) { SysTickTimer::decrement(); } + +/** + * @brief Trigger a software reset via the timer helper. + * @return none + */ +void system_soft_reset(void) { SysTickTimer::softReset(); } + +/** + * @brief SysTick interrupt service routine. + * @return none + */ +extern "C" void SysTick_Handler(void) +{ + SysTickTimer::onInterrupt(); +} diff --git a/GD32E50X_BOOT/sys/systick.h b/GD32E50X_BOOT/sys/systick.h index 55aba93..3fdf6b9 100644 --- a/GD32E50X_BOOT/sys/systick.h +++ b/GD32E50X_BOOT/sys/systick.h @@ -7,11 +7,75 @@ extern "C" { #include +/** + * @brief Bootloader SysTick 时基模块。 + * + * 负责提供毫秒节拍、阻塞延时与软复位能力。 + */ +class SysTickTimer { +public: + /** @brief 初始化 1ms SysTick 节拍。 */ + static void init(); + /** @brief 毫秒阻塞延时。 */ + static void delayMs(uint32_t count); + /** @brief 微秒级粗略阻塞延时。 */ + static void delayUs(uint32_t count); + /** @brief 秒级阻塞延时。 */ + static void delaySeconds(uint32_t count); + /** @brief 递减毫秒倒计时。 */ + static void decrement(); + /** @brief SysTick 中断实际处理逻辑。 */ + static void onInterrupt(); + /** @brief 触发软件复位。 */ + static void softReset(); + +private: + static volatile uint32_t s_delayCountdown; +}; + +/** + * @brief 配置 SysTick 为 1ms 周期中断。 + * + * @return 无。 + */ void systick_config(void); + +/** + * @brief 执行毫秒级阻塞延时。 + * + * @param count 延时毫秒数。 + * @return 无。 + */ void delay_1ms(uint32_t count); + +/** + * @brief 执行微秒级粗略阻塞延时。 + * + * @param count 延时微秒数。 + * @return 无。 + */ void delay_1us(uint32_t count); + +/** + * @brief 执行秒级阻塞延时。 + * + * @param count 延时秒数。 + * @return 无。 + */ void delay_1s(uint32_t count); + +/** + * @brief 递减 SysTick 维护的毫秒倒计时。 + * + * @return 无。 + */ void delay_decrement(void); + +/** + * @brief 触发 MCU 软件复位。 + * + * @return 无。 + */ void system_soft_reset(void); #ifdef __cplusplus diff --git a/_backup_20260506_0053/GD32E50X_BOOT/GD32E50X_BOOT.cproject.yml b/_backup_20260506_0053/GD32E50X_BOOT/GD32E50X_BOOT.cproject.yml deleted file mode 100644 index be92455..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/GD32E50X_BOOT.cproject.yml +++ /dev/null @@ -1,45 +0,0 @@ -# A project translates into one executable or library. -project: - - groups: - - group: Source Files - files: - - file: ./main.c - - # List executable file formats to be generated. - output: - type: - - elf - - hex - - map - packs: - - pack: ARM::CMSIS-DSP - - pack: ARM::CMSIS-NN - - pack: GigaDevice::GD32E50x_DFP - - pack: ARM::CMSIS - components: - - component: CMSIS:CORE - - component: Device:GD32E50x_StdPeripherals:ADC - - component: Device:GD32E50x_StdPeripherals:CAN - - component: Device:GD32E50x_StdPeripherals:CRC - - component: Device:GD32E50x_StdPeripherals:CTC - - component: Device:GD32E50x_StdPeripherals:DBG - - component: Device:GD32E50x_StdPeripherals:FMC - - component: Device:GD32E50x_StdPeripherals:MISC - - component: Device:GD32E50x_StdPeripherals:PMU - - component: Device:GD32E50x_StdPeripherals:RCU - - component: Device:GD32E50x_StdPeripherals:TIMER - - component: Device:GD32E50x_StdPeripherals:USART - - component: Device:GD32E50x_libopt - - component: Device:Startup - - component: Device:GD32E50x_StdPeripherals:DMA - misc: - - for-compiler: AC6 - C-CPP: - - -DGD32E50X_CL - - -DGD32E50X - - -gdwarf-5 - ASM: - - -DGD32E50X_CL - - -DGD32E50X - - -gdwarf-5 diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/ac6_linker_script.sct.src b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/ac6_linker_script.sct.src deleted file mode 100644 index 7820e1f..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/ac6_linker_script.sct.src +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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 diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c deleted file mode 100644 index 7da27c0..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c +++ /dev/null @@ -1,239 +0,0 @@ -/*! - \file gd32e503z_eval.c - \brief firmware functions to manage leds, keys, COM ports - - \version 2025-07-09, V1.6.1, 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 "gd32e503z_eval.h" - -/* private variables */ -static uint32_t GPIO_PORT[LEDn] = {LED1_GPIO_PORT, LED2_GPIO_PORT, - LED3_GPIO_PORT, LED4_GPIO_PORT}; -static uint32_t GPIO_PIN[LEDn] = {LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN}; - -static rcu_periph_enum COM_CLK[COMn] = {EVAL_COM0_CLK}; -static uint32_t COM_TX_PIN[COMn] = {EVAL_COM0_TX_PIN}; -static uint32_t COM_RX_PIN[COMn] = {EVAL_COM0_RX_PIN}; -static uint32_t COM_GPIO_PORT[COMn] = {EVAL_COM0_GPIO_PORT}; -static rcu_periph_enum COM_GPIO_CLK[COMn] = {EVAL_COM0_GPIO_CLK}; - -static rcu_periph_enum GPIO_CLK[LEDn] = {LED1_GPIO_CLK, LED2_GPIO_CLK, - LED3_GPIO_CLK, LED4_GPIO_CLK}; - -static uint32_t KEY_PORT[KEYn] = {KEY_A_GPIO_PORT, - KEY_B_GPIO_PORT, - KEY_C_GPIO_PORT, - KEY_D_GPIO_PORT, - KEY_CET_GPIO_PORT}; -static uint32_t KEY_PIN[KEYn] = {KEY_A_PIN, - KEY_B_PIN, - KEY_C_PIN, - KEY_D_PIN, - KEY_CET_PIN}; -static rcu_periph_enum KEY_CLK[KEYn] = {KEY_A_GPIO_CLK, - KEY_B_GPIO_CLK, - KEY_C_GPIO_CLK, - KEY_D_GPIO_CLK, - KEY_CET_GPIO_CLK}; -static exti_line_enum KEY_EXTI_LINE[KEYn] = {KEY_A_EXTI_LINE, - KEY_B_EXTI_LINE, - KEY_C_EXTI_LINE, - KEY_D_EXTI_LINE, - KEY_CET_EXTI_LINE}; -static uint8_t KEY_PORT_SOURCE[KEYn] = {KEY_A_EXTI_PORT_SOURCE, - KEY_B_EXTI_PORT_SOURCE, - KEY_C_EXTI_PORT_SOURCE, - KEY_D_EXTI_PORT_SOURCE, - KEY_CET_EXTI_PORT_SOURCE}; -static uint8_t KEY_PIN_SOURCE[KEYn] = {KEY_A_EXTI_PIN_SOURCE, - KEY_B_EXTI_PIN_SOURCE, - KEY_C_EXTI_PIN_SOURCE, - KEY_D_EXTI_PIN_SOURCE, - KEY_CET_EXTI_PIN_SOURCE}; -static const IRQn_Type KEY_IRQn[KEYn] = {KEY_A_EXTI_IRQn, - KEY_B_EXTI_IRQn, - KEY_C_EXTI_IRQn, - KEY_D_EXTI_IRQn, - KEY_CET_EXTI_IRQn}; - -/*! - \brief configure led GPIO - \param[in] lednum: specify the led to be configured - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_init (led_typedef_enum lednum) -{ - /* enable the led clock */ - rcu_periph_clock_enable(GPIO_CLK[lednum]); - /* configure led GPIO port */ - gpio_init(GPIO_PORT[lednum], GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN[lednum]); - - GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief turn on selected led - \param[in] lednum: specify the led to be turned on - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_on(led_typedef_enum lednum) -{ - GPIO_BOP(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief turn off selected led - \param[in] lednum: specify the led to be turned off - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_off(led_typedef_enum lednum) -{ - GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief toggle selected led - \param[in] lednum: specify the led to be toggled - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_toggle(led_typedef_enum lednum) -{ - gpio_bit_write(GPIO_PORT[lednum], GPIO_PIN[lednum], - (bit_status)(1-gpio_input_bit_get(GPIO_PORT[lednum], GPIO_PIN[lednum]))); -} - -/*! - \brief configure key - \param[in] key_num: specify the key to be configured - \arg KEY_A: wakeup key - \arg KEY_B: tamper key - \arg KEY_C: user key - \arg KEY_D: extension key - \arg KEY_CET: extension key - \param[in] key_mode: specify button mode - \arg KEY_MODE_GPIO: key will be used as simple IO - \arg KEY_MODE_EXTI: key will be connected to EXTI line with interrupt - \param[out] none - \retval none -*/ -void gd_eval_key_init(key_typedef_enum key_num, keymode_typedef_enum key_mode) -{ - /* enable the key clock */ - rcu_periph_clock_enable(KEY_CLK[key_num]); - rcu_periph_clock_enable(RCU_AF); - - /* configure button pin as input */ - gpio_init(KEY_PORT[key_num], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, KEY_PIN[key_num]); - - if(key_mode == KEY_MODE_EXTI) { - /* enable and set key EXTI interrupt to the lowest priority */ - nvic_irq_enable(KEY_IRQn[key_num], 2U, 0U); - - /* connect key EXTI line to key GPIO pin */ - gpio_exti_source_select(KEY_PORT_SOURCE[key_num], KEY_PIN_SOURCE[key_num]); - - /* configure key EXTI line */ - exti_init(KEY_EXTI_LINE[key_num], EXTI_INTERRUPT, EXTI_TRIG_FALLING); - exti_interrupt_flag_clear(KEY_EXTI_LINE[key_num]); - } -} - -/*! - \brief return the selected key state - \param[in] key: specify the key to be checked - \arg KEY_A: wakeup key - \arg KEY_B: tamper key - \arg KEY_C: user key - \arg KEY_D: extension key - \arg KEY_CET: extension key - \param[out] none - \retval the key's GPIO pin value -*/ -uint8_t gd_eval_key_state_get(key_typedef_enum key) -{ - return gpio_input_bit_get(KEY_PORT[key], KEY_PIN[key]); -} - -/*! - \brief configure COM port - \param[in] com: COM on the board - \arg EVAL_COM0: COM0 on the board - \param[out] none - \retval none -*/ -void gd_eval_com_init(uint32_t com) -{ - uint32_t com_id = 0U; - if(EVAL_COM0 == com){ - com_id = 0U; - }else{ - while(1); - } - - /* enable GPIO clock */ - rcu_periph_clock_enable(COM_GPIO_CLK[com_id]); - - /* enable USART clock */ - rcu_periph_clock_enable(COM_CLK[com_id]); - - /* connect port to USARTx_Tx */ - gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_TX_PIN[com_id]); - - /* connect port to USARTx_Rx */ - gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, COM_RX_PIN[com_id]); - - /* USART configure */ - usart_deinit(com); - usart_baudrate_set(com, 115200U); - usart_receive_config(com, USART_RECEIVE_ENABLE); - usart_transmit_config(com, USART_TRANSMIT_ENABLE); - usart_enable(com); -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c.base@1.2.4 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c.base@1.2.4 deleted file mode 100644 index 7da27c0..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e503z_eval.c.base@1.2.4 +++ /dev/null @@ -1,239 +0,0 @@ -/*! - \file gd32e503z_eval.c - \brief firmware functions to manage leds, keys, COM ports - - \version 2025-07-09, V1.6.1, 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 "gd32e503z_eval.h" - -/* private variables */ -static uint32_t GPIO_PORT[LEDn] = {LED1_GPIO_PORT, LED2_GPIO_PORT, - LED3_GPIO_PORT, LED4_GPIO_PORT}; -static uint32_t GPIO_PIN[LEDn] = {LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN}; - -static rcu_periph_enum COM_CLK[COMn] = {EVAL_COM0_CLK}; -static uint32_t COM_TX_PIN[COMn] = {EVAL_COM0_TX_PIN}; -static uint32_t COM_RX_PIN[COMn] = {EVAL_COM0_RX_PIN}; -static uint32_t COM_GPIO_PORT[COMn] = {EVAL_COM0_GPIO_PORT}; -static rcu_periph_enum COM_GPIO_CLK[COMn] = {EVAL_COM0_GPIO_CLK}; - -static rcu_periph_enum GPIO_CLK[LEDn] = {LED1_GPIO_CLK, LED2_GPIO_CLK, - LED3_GPIO_CLK, LED4_GPIO_CLK}; - -static uint32_t KEY_PORT[KEYn] = {KEY_A_GPIO_PORT, - KEY_B_GPIO_PORT, - KEY_C_GPIO_PORT, - KEY_D_GPIO_PORT, - KEY_CET_GPIO_PORT}; -static uint32_t KEY_PIN[KEYn] = {KEY_A_PIN, - KEY_B_PIN, - KEY_C_PIN, - KEY_D_PIN, - KEY_CET_PIN}; -static rcu_periph_enum KEY_CLK[KEYn] = {KEY_A_GPIO_CLK, - KEY_B_GPIO_CLK, - KEY_C_GPIO_CLK, - KEY_D_GPIO_CLK, - KEY_CET_GPIO_CLK}; -static exti_line_enum KEY_EXTI_LINE[KEYn] = {KEY_A_EXTI_LINE, - KEY_B_EXTI_LINE, - KEY_C_EXTI_LINE, - KEY_D_EXTI_LINE, - KEY_CET_EXTI_LINE}; -static uint8_t KEY_PORT_SOURCE[KEYn] = {KEY_A_EXTI_PORT_SOURCE, - KEY_B_EXTI_PORT_SOURCE, - KEY_C_EXTI_PORT_SOURCE, - KEY_D_EXTI_PORT_SOURCE, - KEY_CET_EXTI_PORT_SOURCE}; -static uint8_t KEY_PIN_SOURCE[KEYn] = {KEY_A_EXTI_PIN_SOURCE, - KEY_B_EXTI_PIN_SOURCE, - KEY_C_EXTI_PIN_SOURCE, - KEY_D_EXTI_PIN_SOURCE, - KEY_CET_EXTI_PIN_SOURCE}; -static const IRQn_Type KEY_IRQn[KEYn] = {KEY_A_EXTI_IRQn, - KEY_B_EXTI_IRQn, - KEY_C_EXTI_IRQn, - KEY_D_EXTI_IRQn, - KEY_CET_EXTI_IRQn}; - -/*! - \brief configure led GPIO - \param[in] lednum: specify the led to be configured - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_init (led_typedef_enum lednum) -{ - /* enable the led clock */ - rcu_periph_clock_enable(GPIO_CLK[lednum]); - /* configure led GPIO port */ - gpio_init(GPIO_PORT[lednum], GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN[lednum]); - - GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief turn on selected led - \param[in] lednum: specify the led to be turned on - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_on(led_typedef_enum lednum) -{ - GPIO_BOP(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief turn off selected led - \param[in] lednum: specify the led to be turned off - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_off(led_typedef_enum lednum) -{ - GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum]; -} - -/*! - \brief toggle selected led - \param[in] lednum: specify the led to be toggled - \arg LED1 - \arg LED2 - \arg LED3 - \arg LED4 - \param[out] none - \retval none -*/ -void gd_eval_led_toggle(led_typedef_enum lednum) -{ - gpio_bit_write(GPIO_PORT[lednum], GPIO_PIN[lednum], - (bit_status)(1-gpio_input_bit_get(GPIO_PORT[lednum], GPIO_PIN[lednum]))); -} - -/*! - \brief configure key - \param[in] key_num: specify the key to be configured - \arg KEY_A: wakeup key - \arg KEY_B: tamper key - \arg KEY_C: user key - \arg KEY_D: extension key - \arg KEY_CET: extension key - \param[in] key_mode: specify button mode - \arg KEY_MODE_GPIO: key will be used as simple IO - \arg KEY_MODE_EXTI: key will be connected to EXTI line with interrupt - \param[out] none - \retval none -*/ -void gd_eval_key_init(key_typedef_enum key_num, keymode_typedef_enum key_mode) -{ - /* enable the key clock */ - rcu_periph_clock_enable(KEY_CLK[key_num]); - rcu_periph_clock_enable(RCU_AF); - - /* configure button pin as input */ - gpio_init(KEY_PORT[key_num], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, KEY_PIN[key_num]); - - if(key_mode == KEY_MODE_EXTI) { - /* enable and set key EXTI interrupt to the lowest priority */ - nvic_irq_enable(KEY_IRQn[key_num], 2U, 0U); - - /* connect key EXTI line to key GPIO pin */ - gpio_exti_source_select(KEY_PORT_SOURCE[key_num], KEY_PIN_SOURCE[key_num]); - - /* configure key EXTI line */ - exti_init(KEY_EXTI_LINE[key_num], EXTI_INTERRUPT, EXTI_TRIG_FALLING); - exti_interrupt_flag_clear(KEY_EXTI_LINE[key_num]); - } -} - -/*! - \brief return the selected key state - \param[in] key: specify the key to be checked - \arg KEY_A: wakeup key - \arg KEY_B: tamper key - \arg KEY_C: user key - \arg KEY_D: extension key - \arg KEY_CET: extension key - \param[out] none - \retval the key's GPIO pin value -*/ -uint8_t gd_eval_key_state_get(key_typedef_enum key) -{ - return gpio_input_bit_get(KEY_PORT[key], KEY_PIN[key]); -} - -/*! - \brief configure COM port - \param[in] com: COM on the board - \arg EVAL_COM0: COM0 on the board - \param[out] none - \retval none -*/ -void gd_eval_com_init(uint32_t com) -{ - uint32_t com_id = 0U; - if(EVAL_COM0 == com){ - com_id = 0U; - }else{ - while(1); - } - - /* enable GPIO clock */ - rcu_periph_clock_enable(COM_GPIO_CLK[com_id]); - - /* enable USART clock */ - rcu_periph_clock_enable(COM_CLK[com_id]); - - /* connect port to USARTx_Tx */ - gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_TX_PIN[com_id]); - - /* connect port to USARTx_Rx */ - gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, COM_RX_PIN[com_id]); - - /* USART configure */ - usart_deinit(com); - usart_baudrate_set(com, 115200U); - usart_receive_config(com, USART_RECEIVE_ENABLE); - usart_transmit_config(com, USART_TRANSMIT_ENABLE); - usart_enable(com); -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_adc.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_adc.c deleted file mode 100644 index b028f9f..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_adc.c +++ /dev/null @@ -1,1107 +0,0 @@ -/*! - \file gd32e50x_adc.c - \brief ADC 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_adc.h" - -/*! - \brief reset ADC - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_deinit(uint32_t adc_periph) -{ - switch(adc_periph){ - case ADC0: - rcu_periph_reset_enable(RCU_ADC0RST); - rcu_periph_reset_disable(RCU_ADC0RST); - break; - case ADC1: - rcu_periph_reset_enable(RCU_ADC1RST); - rcu_periph_reset_disable(RCU_ADC1RST); - break; -#if (defined(GD32E50X_HD) || defined(GD32EPRT)) - case ADC2: - rcu_periph_reset_enable(RCU_ADC2RST); - rcu_periph_reset_disable(RCU_ADC2RST); - break; -#endif - default: - break; - } -} - -/*! - \brief enable ADC interface - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_enable(uint32_t adc_periph) -{ - if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; - } -} - -/*! - \brief disable ADC interface - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_disable(uint32_t adc_periph) -{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON); -} - -/*! - \brief ADC calibration and reset calibration - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_calibration_enable(uint32_t adc_periph) -{ - /* reset the selected ADC calibration registers */ - ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; - /* check the RSTCLB bit state */ - while((ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ - } - /* enable ADC calibration process */ - ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; - /* check the CLB bit state */ - while((ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ - } -} - -/*! - \brief configure ADC calibration number - \param[in] clb_num: calibration number - only one parameter can be selected which is shown as below: - \arg ADC_CALIBRATION_NUM1: calibrate once - \arg ADC_CALIBRATION_NUM2: calibrate twice - \arg ADC_CALIBRATION_NUM4: calibrate 4 times - \arg ADC_CALIBRATION_NUM8: calibrate 8 times - \arg ADC_CALIBRATION_NUM16: calibrate 16 times - \arg ADC_CALIBRATION_NUM32: calibrate 32 times - \param[out] none - \retval none -*/ -void adc_calibration_number(uint32_t adc_periph, uint32_t clb_num) -{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_CLBNUM); - ADC_CTL1(adc_periph) |= clb_num; -} - -/*! - \brief enable DMA request - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_dma_mode_enable(uint32_t adc_periph) -{ - ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA); -} - -/*! - \brief disable DMA request - \param[in] adc_periph: ADCx,x=0,1,2 - \param[out] none - \retval none -*/ -void adc_dma_mode_disable(uint32_t adc_periph) -{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA); -} - -/*! - \brief enable the temperature sensor and vrefint channel - \param[in] none - \param[out] none - \retval none -*/ -void adc_tempsensor_vrefint_enable(void) -{ - /* enable the temperature sensor and vrefint channel */ - ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN; -} - -/*! - \brief disable the temperature sensor and vrefint channel - \param[in] none - \param[out] none - \retval none -*/ -void adc_tempsensor_vrefint_disable(void) -{ - /* disable the temperature sensor and vrefint channel */ - ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN; -} - -/*! - \brief configure ADC discontinuous mode - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: select the channel group - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular and inserted channel - \param[in] length: number of conversions in discontinuous mode,the number can be 1..8 - for regular channel, the number has no effect for inserted channel - \param[out] none - \retval none -*/ -void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length) -{ - ADC_CTL0(adc_periph) &= ~((uint32_t)( ADC_CTL0_DISRC | ADC_CTL0_DISIC )); - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - /* configure the number of conversions in discontinuous mode */ - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); - ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - 1U)); - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC; - break; - case ADC_INSERTED_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; - break; - case ADC_CHANNEL_DISCON_DISABLE: - default: - break; - } -} - -/*! - \brief configure the ADC0 sync mode - \param[in] mode: ADC0 mode - only one parameter can be selected which is shown as below: - \arg ADC_MODE_FREE: all the ADCs work independently - \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode - \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode - \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode - \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode - \arg ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only - \arg ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only - \arg ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only - \arg ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only - \arg ADC_DAUL_INSERTED_TRRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only - \param[out] none - \retval none -*/ -void adc_mode_config(uint32_t mode) -{ - ADC_CTL0(ADC0) &= ~((uint32_t)ADC_CTL0_SYNCM); - ADC_CTL0(ADC0) |= mode; -} - -/*! - \brief configure ADC special function - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] function: the function to configure - one or more parameters can be selected which is shown as below: - \arg ADC_SCAN_MODE: scan mode select - \arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically - \arg ADC_CONTINUOUS_MODE: continuous mode select - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void adc_special_function_config(uint32_t adc_periph , uint32_t function , ControlStatus newvalue) -{ - if(newvalue){ - /* enable ADC scan mode */ - if(RESET != (function & ADC_SCAN_MODE)){ - ADC_CTL0(adc_periph) |= (uint32_t)ADC_SCAN_MODE; - } - /* enable ADC inserted channel group convert automatically */ - if(RESET != (function & ADC_INSERTED_CHANNEL_AUTO)){ - ADC_CTL0(adc_periph) |= (uint32_t)ADC_INSERTED_CHANNEL_AUTO; - } - /* enable ADC continuous mode */ - if(RESET != (function & ADC_CONTINUOUS_MODE)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CONTINUOUS_MODE; - } - }else{ - /* disable ADC scan mode */ - if(RESET != (function & ADC_SCAN_MODE)){ - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_SCAN_MODE); - } - /* disable ADC inserted channel group convert automatically */ - if(RESET != (function & ADC_INSERTED_CHANNEL_AUTO)){ - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_INSERTED_CHANNEL_AUTO); - } - /* disable ADC continuous mode */ - if(RESET != (function & ADC_CONTINUOUS_MODE)){ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CONTINUOUS_MODE); - } - } -} - -/*! - \brief configure ADC data alignment - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] data_alignment: data alignment select - only one parameter can be selected which is shown as below: - \arg ADC_DATAALIGN_RIGHT: right alignment - \arg ADC_DATAALIGN_LEFT: left alignment - \param[out] none - \retval none -*/ -void adc_data_alignment_config(uint32_t adc_periph , uint32_t data_alignment) -{ - if(ADC_DATAALIGN_RIGHT != data_alignment){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_DAL; - }else{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); - } -} - -/*! - \brief configure the length of regular channel group or inserted channel group - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: select the channel group - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \param[in] length: the length of the channel - regular channel 1-16 - inserted channel 1-4 - \param[out] none - \retval none -*/ -void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length) -{ - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - /* configure the length of regular channel group */ - ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); - ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-1U)); - break; - case ADC_INSERTED_CHANNEL: - /* configure the length of inserted channel group */ - ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL); - ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-1U)); - break; - default: - break; - } -} - -/*! - \brief configure ADC regular channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15 - \param[in] adc_channel: the selected ADC channel - only one parameter can be selected which is shown as below: - \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx - \param[in] sample_time: the sample time value - only one parameter can be selected which is shown as below: - \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles - \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles - \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles - \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles - \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles - \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles - \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles - \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles - \param[out] none - \retval none -*/ -void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) -{ - uint32_t rsq,sampt; - - /* configure ADC regular sequence */ - if(rank < 6U){ - rsq = ADC_RSQ2(adc_periph); - rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*rank))); - rsq |= ((uint32_t)adc_channel << (5U*rank)); - ADC_RSQ2(adc_periph) = rsq; - }else if(rank < 12U){ - rsq = ADC_RSQ1(adc_periph); - rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-6U)))); - rsq |= ((uint32_t)adc_channel << (5U*(rank-6U))); - ADC_RSQ1(adc_periph) = rsq; - }else if(rank < 16U){ - rsq = ADC_RSQ0(adc_periph); - rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-12U)))); - rsq |= ((uint32_t)adc_channel << (5U*(rank-12U))); - ADC_RSQ0(adc_periph) = rsq; - }else{ - } - - /* configure ADC sampling time */ - if(adc_channel < 10U){ - sampt = ADC_SAMPT1(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel))); - sampt |= (uint32_t)(sample_time << (3U*adc_channel)); - ADC_SAMPT1(adc_periph) = sampt; - }else if(adc_channel < 18U){ - sampt = ADC_SAMPT0(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U)))); - sampt |= (uint32_t)(sample_time << (3U*(adc_channel-10U))); - ADC_SAMPT0(adc_periph) = sampt; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief configure ADC inserted channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 - \param[in] adc_channel: the selected ADC channel - only one parameter can be selected which is shown as below: - \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx - \param[in] sample_time: The sample time value - only one parameter can be selected which is shown as below: - \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles - \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles - \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles - \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles - \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles - \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles - \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles - \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles - \param[out] none - \retval none -*/ -void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) -{ - uint8_t inserted_length; - uint32_t isq, sampt; - - /* get inserted channel group length */ - inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph), 20U, 21U); - - /* the channel number is written to these bits to select a channel as the nth conversion in the inserted channel group */ - isq = ADC_ISQ(adc_periph); - isq &= ~((uint32_t)(ADC_ISQ_ISQN << (5U * ((3U + rank) - inserted_length)))); - isq |= ((uint32_t)adc_channel << (5U * ((3U + rank) - inserted_length))); - ADC_ISQ(adc_periph) = isq; - - /* ADC sampling time config */ - if(adc_channel < 10U){ - sampt = ADC_SAMPT1(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel))); - sampt |= (uint32_t) sample_time << (3U*adc_channel); - ADC_SAMPT1(adc_periph) = sampt; - }else if(adc_channel < 18U){ - sampt = ADC_SAMPT0(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U)))); - sampt |= ((uint32_t)sample_time << (3U*(adc_channel-10U))); - ADC_SAMPT0(adc_periph) = sampt; - }else{ - } -} - -/*! - \brief configure ADC inserted channel offset - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] inserted_channel : insert channel select - only one parameter can be selected which is shown as below: - \arg ADC_INSERTED_CHANNEL_0: ADC inserted channel0 - \arg ADC_INSERTED_CHANNEL_1: ADC inserted channel1 - \arg ADC_INSERTED_CHANNEL_2: ADC inserted channel2 - \arg ADC_INSERTED_CHANNEL_3: ADC inserted channel3 - \param[in] offset : the offset data - \param[out] none - \retval none -*/ -void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset) -{ - uint8_t inserted_length; - uint32_t num = 0U; - - inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph), 20U, 21U); - num = 3U - (inserted_length - inserted_channel); - - if(num <= 3U){ - /* calculate the offset of the register */ - num = num * 4U; - /* configure the offset of the selected channels */ - REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset); - } -} - -/*! - \brief configure differential mode for ADC channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel: the channel use differential mode - one or more parameters can be selected which is shown as below: - \arg ADC_DIFFERENTIAL_MODE_CHANNEL_x(x=0..14), ADC_DIFFERENTIAL_MODE_CHANNEL_ALL: ADC channel for differential mode(just for channel0~channel14) - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void adc_channel_differential_mode_config(uint32_t adc_periph, uint32_t adc_channel, ControlStatus newvalue) -{ - if(ENABLE == newvalue){ - ADC_DIFCTL(adc_periph) |= (uint32_t)adc_channel; - }else{ - ADC_DIFCTL(adc_periph) &= ~((uint32_t)adc_channel); - } -} - -/*! - \brief configure ADC external trigger - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: select the channel group - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue) -{ - if(newvalue){ - /* external trigger enable for regular channel */ - if(RESET != (adc_channel_group & ADC_REGULAR_CHANNEL)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ETERC; - } - /* external trigger enable for inserted channel */ - if(RESET != (adc_channel_group & ADC_INSERTED_CHANNEL)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ETEIC; - } - }else{ - /* external trigger disable for regular channel */ - if(RESET != (adc_channel_group & ADC_REGULAR_CHANNEL)){ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETERC); - } - /* external trigger disable for inserted channel */ - if(RESET != (adc_channel_group & ADC_INSERTED_CHANNEL)){ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETEIC); - } - } -} - -/*! - \brief configure ADC external trigger source - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: select the channel group - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \param[in] external_trigger_source: regular or inserted group trigger source - only one parameter can be selected which is shown as below: - for regular channel: - \arg ADC0_1_EXTTRIG_REGULAR_T0_CH0: TIMER0 CH0 event select - \arg ADC0_1_EXTTRIG_REGULAR_T0_CH1: TIMER0 CH1 event select - \arg ADC0_1_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select - \arg ADC0_1_EXTTRIG_REGULAR_T1_CH1: TIMER1 CH1 event select - \arg ADC0_1_EXTTRIG_REGULAR_T2_TRGO: TIMER2 TRGO event select - \arg ADC0_1_EXTTRIG_REGULAR_T3_CH3: TIMER3 CH3 event select - \arg ADC0_1_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select - \arg ADC0_1_EXTTRIG_REGULAR_EXTI_11: external interrupt line 11 - \arg ADC0_1_EXTTRIG_REGULAR_SHRTIMER_ADCTRG0: SHRTIMER_ADCTRG0 output select(for GD32E50X_HD and GD32E50X_CL devices) - \arg ADC0_1_EXTTRIG_REGULAR_SHRTIMER_ADCTRG2: SHRTIMER_ADCTRG2 output select(for GD32E50X_HD and GD32E50X_CL devices) - \arg ADC2_EXTTRIG_REGULAR_T2_CH0: TIMER2 CH0 event select - \arg ADC2_EXTTRIG_REGULAR_T1_CH2: TIMER1 CH2 event select - \arg ADC2_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select - \arg ADC2_EXTTRIG_REGULAR_T7_CH0: TIMER7 CH0 event select - \arg ADC2_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select - \arg ADC2_EXTTRIG_REGULAR_T4_CH0: TIMER4 CH0 event select - \arg ADC2_EXTTRIG_REGULAR_T4_CH2: TIMER4 CH2 event select - \arg ADC0_1_2_EXTTRIG_REGULAR_NONE: software trigger - for inserted channel: - \arg ADC0_1_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select - \arg ADC0_1_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select - \arg ADC0_1_EXTTRIG_INSERTED_T1_TRGO: TIMER1 TRGO event select - \arg ADC0_1_EXTTRIG_INSERTED_T1_CH0: TIMER1 CH0 event select - \arg ADC0_1_EXTTRIG_INSERTED_T2_CH3: TIMER2 CH3 event select - \arg ADC0_1_EXTTRIG_INSERTED_T3_TRGO: TIMER3 TRGO event select - \arg ADC0_1_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select - \arg ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 - \arg ADC0_1_EXTTRIG_INSERTED_SHRTIMER_ADCTRG1: SHRTIMER_ADCTRG1 output select(for GD32E50X_HD and GD32E50X_CL devices) - \arg ADC0_1_EXTTRIG_INSERTED_SHRTIMER_ADCTRG3: SHRTIMER_ADCTRG3 output select(for GD32E50X_HD and GD32E50X_CL devices) - \arg ADC2_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select - \arg ADC2_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select - \arg ADC2_EXTTRIG_INSERTED_T3_CH2: TIMER3 CH2 event select - \arg ADC2_EXTTRIG_INSERTED_T7_CH1: TIMER7 CH1 event select - \arg ADC2_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select - \arg ADC2_EXTTRIG_INSERTED_T4_TRGO: TIMER4 TRGO event select - \arg ADC2_EXTTRIG_INSERTED_T4_CH3: TIMER4 CH3 event select - \arg ADC0_1_2_EXTTRIG_INSERTED_NONE: software trigger - \param[out] none - \retval none -*/ -void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source) -{ - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - /* external trigger select for regular channel */ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); - ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; - break; - case ADC_INSERTED_CHANNEL: - /* external trigger select for inserted channel */ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC); - ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; - break; - default: - break; - } -} - -/*! - \brief enable ADC software trigger - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: select the channel group - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \param[out] none - \retval none -*/ -void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group) -{ - /* enable regular group channel software trigger */ - if(RESET != (adc_channel_group & ADC_REGULAR_CHANNEL)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_SWRCST; - } - /* enable inserted channel group software trigger */ - if(RESET != (adc_channel_group & ADC_INSERTED_CHANNEL)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_SWICST; - } -} - -/*! - \brief read ADC regular group data register - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] none - \param[out] none - \retval the conversion value: 0~0xFFFF -*/ -uint16_t adc_regular_data_read(uint32_t adc_periph) -{ - return (uint16_t)(ADC_RDATA(adc_periph)); -} - -/*! - \brief read ADC inserted group data register - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] inserted_channel: inserted channel select - only one parameter can be selected which is shown as below: - \arg ADC_INSERTED_CHANNEL_0: ADC inserted channel0 - \arg ADC_INSERTED_CHANNEL_1: ADC inserted channel1 - \arg ADC_INSERTED_CHANNEL_2: ADC inserted channel2 - \arg ADC_INSERTED_CHANNEL_3: ADC inserted channel3 - \param[out] none - \retval the conversion value: 0~0xFFFF -*/ -uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel) -{ - uint32_t idata; - /* read the data of the selected channel */ - switch(inserted_channel){ - case ADC_INSERTED_CHANNEL_0: - idata = ADC_IDATA0(adc_periph); - break; - case ADC_INSERTED_CHANNEL_1: - idata = ADC_IDATA1(adc_periph); - break; - case ADC_INSERTED_CHANNEL_2: - idata = ADC_IDATA2(adc_periph); - break; - case ADC_INSERTED_CHANNEL_3: - idata = ADC_IDATA3(adc_periph); - break; - default: - idata = 0U; - break; - } - return (uint16_t)idata; -} - -/*! - \brief read the last ADC0 and ADC1 conversion result data in sync mode - \param[in] none - \param[out] none - \retval the conversion value: 0~0xFFFFFFFF -*/ -uint32_t adc_sync_mode_convert_value_read(void) -{ - /* return conversion value */ - return ADC_RDATA(ADC0); -} - -/*! - \brief configure ADC analog watchdog 0 single channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel: the selected ADC channel - only one parameter can be selected which is shown as below: - \arg ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0) - \param[out] none - \retval none -*/ -void adc_watchdog0_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel) -{ - ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC | ADC_CTL0_WD0CHSEL); - - ADC_CTL0(adc_periph) |= (uint32_t)adc_channel; - ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC); -} - -/*! - \brief configure ADC analog watchdog 0 group channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: the channel group use analog watchdog 0 - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group - \param[out] none - \retval none -*/ -void adc_watchdog0_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group) -{ - ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC); - /* select the group */ - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_RWD0EN; - break; - case ADC_INSERTED_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_IWD0EN; - break; - case ADC_REGULAR_INSERTED_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN); - break; - default: - break; - } -} - -/*! - \brief disable ADC analog watchdog 0 - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_watchdog0_disable(uint32_t adc_periph) -{ - ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC | ADC_CTL0_WD0CHSEL); -} - -/*! - \brief configure ADC analog watchdog 1 channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel: the channel use analog watchdog 1 - one or more parameters can be selected which is shown as below: - \arg ADC_AWD1_2_SELECTION_CHANNEL_x, ADC_AWD1_2_SELECTION_CHANNEL_ALL: ADC channel analog watchdog 1/2 selection - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void adc_watchdog1_channel_config(uint32_t adc_periph, uint32_t adc_channel, ControlStatus newvalue) -{ - if(ENABLE == newvalue){ - ADC_WD1SR(adc_periph) |= (uint32_t)adc_channel; - }else{ - ADC_WD1SR(adc_periph) &= ~((uint32_t)adc_channel); - } -} - -/*! - \brief configure ADC analog watchdog 2 channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel: the channel use analog watchdog 2 - one or more parameters can be selected which is shown as below: - \arg ADC_AWD1_2_SELECTION_CHANNEL_x, ADC_AWD1_2_SELECTION_CHANNEL_ALL: ADC channel analog watchdog 1/2 selection - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void adc_watchdog2_channel_config(uint32_t adc_periph, uint32_t adc_channel, ControlStatus newvalue) -{ - if(ENABLE == newvalue){ - ADC_WD2SR(adc_periph) |= (uint32_t)adc_channel; - }else{ - ADC_WD2SR(adc_periph) &= ~((uint32_t)adc_channel); - } -} - -/*! - \brief disable ADC analog watchdog 1 - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_watchdog1_disable(uint32_t adc_periph) -{ - ADC_WD1SR(adc_periph) &= (uint32_t)~(ADC_WD1SR_AWD1CS); -} - -/*! - \brief disable ADC analog watchdog 2 - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_watchdog2_disable(uint32_t adc_periph) -{ - ADC_WD2SR(adc_periph) &= (uint32_t)~(ADC_WD2SR_AWD2CS); -} - -/*! - \brief configure ADC analog watchdog 0 threshold - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] low_threshold: analog watchdog 0 low threshold, 0..4095 - \param[in] high_threshold: analog watchdog 0 high threshold, 0..4095 - \param[out] none - \retval none -*/ -void adc_watchdog0_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold) -{ - ADC_WDLT0(adc_periph) = (uint32_t)WDLT0_WDLT0(low_threshold); - ADC_WDHT0(adc_periph) = (uint32_t)WDHT0_WDHT0(high_threshold); -} - -/*! - \brief configure ADC analog watchdog 1 threshold - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] low_threshold: analog watchdog 1 low threshold, 0..255 - \param[in] high_threshold: analog watchdog 1 high threshold, 0..255 - \param[out] none - \retval none -*/ -void adc_watchdog1_threshold_config(uint32_t adc_periph, uint8_t low_threshold, uint8_t high_threshold) -{ - ADC_WDT1(adc_periph) &= ~((uint32_t)(ADC_WDT1_WDLT1 | ADC_WDT1_WDHT1)); - /* configure ADC analog watchdog 1 threshold */ - ADC_WDT1(adc_periph) |= (uint32_t)WDT1_WDLT1(low_threshold); - ADC_WDT1(adc_periph) |= (uint32_t)WDT1_WDHT1(high_threshold); -} - -/*! - \brief configure ADC analog watchdog 2 threshold - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] low_threshold: analog watchdog 2 low threshold, 0..255 - \param[in] high_threshold: analog watchdog 2 high threshold, 0..255 - \param[out] none - \retval none -*/ -void adc_watchdog2_threshold_config(uint32_t adc_periph, uint8_t low_threshold, uint8_t high_threshold) -{ - ADC_WDT2(adc_periph) &= ~((uint32_t)(ADC_WDT2_WDLT2 | ADC_WDT2_WDHT2)); - /* configure ADC analog watchdog 2 threshold */ - ADC_WDT2(adc_periph) |= (uint32_t)WDT2_WDLT2(low_threshold); - ADC_WDT2(adc_periph) |= (uint32_t)WDT2_WDHT2(high_threshold); -} - -/*! - \brief configure ADC resolution - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] resolution: ADC resolution - only one parameter can be selected which is shown as below: - \arg ADC_RESOLUTION_12B: 12-bit ADC resolution - \arg ADC_RESOLUTION_10B: 10-bit ADC resolution - \arg ADC_RESOLUTION_8B: 8-bit ADC resolution - \arg ADC_RESOLUTION_6B: 6-bit ADC resolution - \param[out] none - \retval none -*/ -void adc_resolution_config(uint32_t adc_periph, uint32_t resolution) -{ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_DRES); - ADC_OVSAMPCTL(adc_periph) |= (uint32_t)resolution; -} - -/*! - \brief configure ADC oversample mode - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] mode: ADC oversampling mode - only one parameter can be selected which is shown as below: - \arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger - \arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger - \param[in] shift: ADC oversampling shift - only one parameter can be selected which is shown as below: - \arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift - \param[in] ratio: ADC oversampling ratio - only one parameter can be selected which is shown as below: - \arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2 - \arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4 - \arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8 - \arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16 - \arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32 - \arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64 - \arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128 - \arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256 - \param[out] none - \retval none -*/ -void adc_oversample_mode_config(uint32_t adc_periph, uint32_t mode, uint16_t shift, uint8_t ratio) -{ - /* configure ADC oversampling mode */ - if(ADC_OVERSAMPLING_ONE_CONVERT == mode){ - ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS; - }else{ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS); - } - /* configure the shift and ratio */ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS)); - ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio); -} - -/*! - \brief enable ADC oversample mode - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_oversample_mode_enable(uint32_t adc_periph) -{ - ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_OVSEN; -} - -/*! - \brief disable ADC oversample mode - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_oversample_mode_disable(uint32_t adc_periph) -{ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN); -} - -/*! - \brief get the ADC flag - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] flag: the ADC flag bits - only one parameter can be selected which is shown as below: - \arg ADC_FLAG_WDE0: analog watchdog 0 event flag - \arg ADC_FLAG_EOC: end of group conversion flag - \arg ADC_FLAG_EOIC: end of inserted group conversion flag - \arg ADC_FLAG_STIC: start flag of inserted channel group - \arg ADC_FLAG_STRC: start flag of regular channel group - \arg ADC_FLAG_WDE1: analog watchdog 1 event flag - \arg ADC_FLAG_WDE2: analog watchdog 2 event flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t flag) -{ - FlagStatus reval = RESET; - if(ADC_STAT(adc_periph) & flag){ - reval = SET; - } - return reval; -} - -/*! - \brief clear the ADC flag - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] flag: the ADC flag - one or more parameters can be selected which is shown as below: - \arg ADC_FLAG_WDE0: analog watchdog 0 event flag - \arg ADC_FLAG_EOC: end of group conversion flag - \arg ADC_FLAG_EOIC: end of inserted group conversion flag - \arg ADC_FLAG_STIC: start flag of inserted channel group - \arg ADC_FLAG_STRC: start flag of regular channel group - \arg ADC_FLAG_WDE1: analog watchdog 1 event flag - \arg ADC_FLAG_WDE2: analog watchdog 2 event flag - \param[out] none - \retval none -*/ -void adc_flag_clear(uint32_t adc_periph , uint32_t flag) -{ - ADC_STAT(adc_periph) &= ~((uint32_t)flag); -} - -/*! - \brief enable ADC interrupt - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] interrupt: the ADC interrupt - one or more parameters can be selected which is shown as below: - \arg ADC_INT_WDE0: analog watchdog 0 interrupt flag - \arg ADC_INT_EOC: end of group conversion interrupt flag - \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag - \arg ADC_INT_WDE1: analog watchdog 1 interrupt flag - \arg ADC_INT_WDE2: analog watchdog 2 interrupt flag - \param[out] none - \retval none -*/ -void adc_interrupt_enable(uint32_t adc_periph , uint32_t interrupt) -{ - switch(interrupt){ - /* enable analog watchdog 0 interrupt */ - case ADC_INT_WDE0: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_WDE0IE; - break; - /* enable end of group conversion interrupt */ - case ADC_INT_EOC: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_EOCIE; - break; - /* enable end of inserted group conversion interrupt */ - case ADC_INT_EOIC: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_EOICIE; - break; - /* enable analog watchdog 1 interrupt */ - case ADC_INT_WDE1: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_WDE1IE; - break; - /* enable analog watchdog 2 interrupt */ - case ADC_INT_WDE2: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_WDE2IE; - break; - default: - break; - } -} - -/*! - \brief disable ADC interrupt - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] interrupt: the ADC interrupt flag - one or more parameters can be selected which is shown as below: - \arg ADC_INT_WDE0: analog watchdog 0 interrupt flag - \arg ADC_INT_EOC: end of group conversion interrupt flag - \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag - \arg ADC_INT_WDE1: analog watchdog 1 interrupt flag - \arg ADC_INT_WDE2: analog watchdog 2 interrupt flag - \param[out] none - \retval none -*/ -void adc_interrupt_disable(uint32_t adc_periph, uint32_t interrupt) -{ - switch(interrupt){ - /* disable analog watchdog 0 interrupt */ - case ADC_INT_WDE0: - ADC_CTL0(adc_periph) &= ~(uint32_t)ADC_CTL0_WDE0IE; - break; - /* disable end of group conversion interrupt */ - case ADC_INT_EOC: - ADC_CTL0(adc_periph) &= ~(uint32_t)ADC_CTL0_EOCIE; - break; - /* disable end of inserted group conversion interrupt */ - case ADC_INT_EOIC: - ADC_CTL0(adc_periph) &= ~(uint32_t)ADC_CTL0_EOICIE; - break; - /* disable analog watchdog 1 interrupt */ - case ADC_INT_WDE1: - ADC_CTL0(adc_periph) &= ~(uint32_t)ADC_CTL0_WDE1IE; - break; - /* disable analog watchdog 2 interrupt */ - case ADC_INT_WDE2: - ADC_CTL0(adc_periph) &= ~(uint32_t)ADC_CTL0_WDE1IE; - break; - default: - break; - } -} - -/*! - \brief get ADC interrupt flag - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] int_flag: the ADC interrupt - only one parameter can be selected which is shown as below: - \arg ADC_INT_FLAG_WDE0: analog watchdog 0 interrupt flag - \arg ADC_INT_FLAG_EOC: end of group conversion interrupt flag - \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt - \arg ADC_INT_FLAG_WDE1: analog watchdog 1 interrupt flag - \arg ADC_INT_FLAG_WDE2: analog watchdog 2 interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t int_flag) -{ - FlagStatus interrupt_flag = RESET; - uint32_t state; - /* check the interrupt bits */ - switch(int_flag){ - case ADC_INT_FLAG_WDE0: - state = ADC_STAT(adc_periph) & ADC_STAT_WDE0; - if((ADC_CTL0(adc_periph) & ADC_CTL0_WDE0IE) && state){ - interrupt_flag = SET; - } - break; - case ADC_INT_FLAG_EOC: - state = ADC_STAT(adc_periph) & ADC_STAT_EOC; - if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){ - interrupt_flag = SET; - } - break; - case ADC_INT_FLAG_EOIC: - state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; - if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){ - interrupt_flag = SET; - } - break; - case ADC_INT_FLAG_WDE1: - state = ADC_STAT(adc_periph) & ADC_STAT_WDE1; - if((ADC_CTL0(adc_periph) & ADC_CTL0_WDE1IE) && state){ - interrupt_flag = SET; - } - break; - case ADC_INT_FLAG_WDE2: - state = ADC_STAT(adc_periph) & ADC_STAT_WDE2; - if((ADC_CTL0(adc_periph) & ADC_CTL0_WDE2IE) && state){ - interrupt_flag = SET; - } - break; - default: - break; - } - return interrupt_flag; -} - -/*! - \brief clear ADC interrupt flag - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] int_flag: the ADC interrupt flag - only one parameter can be selected which is shown as below: - \arg ADC_INT_FLAG_WDE0: analog watchdog 0 interrupt flag - \arg ADC_INT_FLAG_EOC: end of group conversion interrupt flag - \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt flag - \arg ADC_INT_FLAG_WDE1: analog watchdog 1 interrupt flag - \arg ADC_INT_FLAG_WDE2: analog watchdog 2 interrupt flag - \param[out] none - \retval none -*/ -void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t int_flag) -{ - ADC_STAT(adc_periph) &= ~((uint32_t)int_flag); -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_adc.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_adc.c.base@1.5.0 deleted file mode 100644 index b028f9f..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_adc.c.base@1.5.0 +++ /dev/null @@ -1,1107 +0,0 @@ -/*! - \file gd32e50x_adc.c - \brief ADC 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_adc.h" - -/*! - \brief reset ADC - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_deinit(uint32_t adc_periph) -{ - switch(adc_periph){ - case ADC0: - rcu_periph_reset_enable(RCU_ADC0RST); - rcu_periph_reset_disable(RCU_ADC0RST); - break; - case ADC1: - rcu_periph_reset_enable(RCU_ADC1RST); - rcu_periph_reset_disable(RCU_ADC1RST); - break; -#if (defined(GD32E50X_HD) || defined(GD32EPRT)) - case ADC2: - rcu_periph_reset_enable(RCU_ADC2RST); - rcu_periph_reset_disable(RCU_ADC2RST); - break; -#endif - default: - break; - } -} - -/*! - \brief enable ADC interface - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_enable(uint32_t adc_periph) -{ - if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; - } -} - -/*! - \brief disable ADC interface - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_disable(uint32_t adc_periph) -{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON); -} - -/*! - \brief ADC calibration and reset calibration - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_calibration_enable(uint32_t adc_periph) -{ - /* reset the selected ADC calibration registers */ - ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; - /* check the RSTCLB bit state */ - while((ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ - } - /* enable ADC calibration process */ - ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; - /* check the CLB bit state */ - while((ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ - } -} - -/*! - \brief configure ADC calibration number - \param[in] clb_num: calibration number - only one parameter can be selected which is shown as below: - \arg ADC_CALIBRATION_NUM1: calibrate once - \arg ADC_CALIBRATION_NUM2: calibrate twice - \arg ADC_CALIBRATION_NUM4: calibrate 4 times - \arg ADC_CALIBRATION_NUM8: calibrate 8 times - \arg ADC_CALIBRATION_NUM16: calibrate 16 times - \arg ADC_CALIBRATION_NUM32: calibrate 32 times - \param[out] none - \retval none -*/ -void adc_calibration_number(uint32_t adc_periph, uint32_t clb_num) -{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_CLBNUM); - ADC_CTL1(adc_periph) |= clb_num; -} - -/*! - \brief enable DMA request - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_dma_mode_enable(uint32_t adc_periph) -{ - ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA); -} - -/*! - \brief disable DMA request - \param[in] adc_periph: ADCx,x=0,1,2 - \param[out] none - \retval none -*/ -void adc_dma_mode_disable(uint32_t adc_periph) -{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA); -} - -/*! - \brief enable the temperature sensor and vrefint channel - \param[in] none - \param[out] none - \retval none -*/ -void adc_tempsensor_vrefint_enable(void) -{ - /* enable the temperature sensor and vrefint channel */ - ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN; -} - -/*! - \brief disable the temperature sensor and vrefint channel - \param[in] none - \param[out] none - \retval none -*/ -void adc_tempsensor_vrefint_disable(void) -{ - /* disable the temperature sensor and vrefint channel */ - ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN; -} - -/*! - \brief configure ADC discontinuous mode - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: select the channel group - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular and inserted channel - \param[in] length: number of conversions in discontinuous mode,the number can be 1..8 - for regular channel, the number has no effect for inserted channel - \param[out] none - \retval none -*/ -void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length) -{ - ADC_CTL0(adc_periph) &= ~((uint32_t)( ADC_CTL0_DISRC | ADC_CTL0_DISIC )); - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - /* configure the number of conversions in discontinuous mode */ - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); - ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - 1U)); - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC; - break; - case ADC_INSERTED_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; - break; - case ADC_CHANNEL_DISCON_DISABLE: - default: - break; - } -} - -/*! - \brief configure the ADC0 sync mode - \param[in] mode: ADC0 mode - only one parameter can be selected which is shown as below: - \arg ADC_MODE_FREE: all the ADCs work independently - \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode - \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode - \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode - \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode - \arg ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only - \arg ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only - \arg ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only - \arg ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only - \arg ADC_DAUL_INSERTED_TRRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only - \param[out] none - \retval none -*/ -void adc_mode_config(uint32_t mode) -{ - ADC_CTL0(ADC0) &= ~((uint32_t)ADC_CTL0_SYNCM); - ADC_CTL0(ADC0) |= mode; -} - -/*! - \brief configure ADC special function - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] function: the function to configure - one or more parameters can be selected which is shown as below: - \arg ADC_SCAN_MODE: scan mode select - \arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically - \arg ADC_CONTINUOUS_MODE: continuous mode select - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void adc_special_function_config(uint32_t adc_periph , uint32_t function , ControlStatus newvalue) -{ - if(newvalue){ - /* enable ADC scan mode */ - if(RESET != (function & ADC_SCAN_MODE)){ - ADC_CTL0(adc_periph) |= (uint32_t)ADC_SCAN_MODE; - } - /* enable ADC inserted channel group convert automatically */ - if(RESET != (function & ADC_INSERTED_CHANNEL_AUTO)){ - ADC_CTL0(adc_periph) |= (uint32_t)ADC_INSERTED_CHANNEL_AUTO; - } - /* enable ADC continuous mode */ - if(RESET != (function & ADC_CONTINUOUS_MODE)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CONTINUOUS_MODE; - } - }else{ - /* disable ADC scan mode */ - if(RESET != (function & ADC_SCAN_MODE)){ - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_SCAN_MODE); - } - /* disable ADC inserted channel group convert automatically */ - if(RESET != (function & ADC_INSERTED_CHANNEL_AUTO)){ - ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_INSERTED_CHANNEL_AUTO); - } - /* disable ADC continuous mode */ - if(RESET != (function & ADC_CONTINUOUS_MODE)){ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CONTINUOUS_MODE); - } - } -} - -/*! - \brief configure ADC data alignment - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] data_alignment: data alignment select - only one parameter can be selected which is shown as below: - \arg ADC_DATAALIGN_RIGHT: right alignment - \arg ADC_DATAALIGN_LEFT: left alignment - \param[out] none - \retval none -*/ -void adc_data_alignment_config(uint32_t adc_periph , uint32_t data_alignment) -{ - if(ADC_DATAALIGN_RIGHT != data_alignment){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_DAL; - }else{ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); - } -} - -/*! - \brief configure the length of regular channel group or inserted channel group - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: select the channel group - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \param[in] length: the length of the channel - regular channel 1-16 - inserted channel 1-4 - \param[out] none - \retval none -*/ -void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length) -{ - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - /* configure the length of regular channel group */ - ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); - ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-1U)); - break; - case ADC_INSERTED_CHANNEL: - /* configure the length of inserted channel group */ - ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL); - ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-1U)); - break; - default: - break; - } -} - -/*! - \brief configure ADC regular channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15 - \param[in] adc_channel: the selected ADC channel - only one parameter can be selected which is shown as below: - \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx - \param[in] sample_time: the sample time value - only one parameter can be selected which is shown as below: - \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles - \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles - \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles - \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles - \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles - \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles - \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles - \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles - \param[out] none - \retval none -*/ -void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) -{ - uint32_t rsq,sampt; - - /* configure ADC regular sequence */ - if(rank < 6U){ - rsq = ADC_RSQ2(adc_periph); - rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*rank))); - rsq |= ((uint32_t)adc_channel << (5U*rank)); - ADC_RSQ2(adc_periph) = rsq; - }else if(rank < 12U){ - rsq = ADC_RSQ1(adc_periph); - rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-6U)))); - rsq |= ((uint32_t)adc_channel << (5U*(rank-6U))); - ADC_RSQ1(adc_periph) = rsq; - }else if(rank < 16U){ - rsq = ADC_RSQ0(adc_periph); - rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-12U)))); - rsq |= ((uint32_t)adc_channel << (5U*(rank-12U))); - ADC_RSQ0(adc_periph) = rsq; - }else{ - } - - /* configure ADC sampling time */ - if(adc_channel < 10U){ - sampt = ADC_SAMPT1(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel))); - sampt |= (uint32_t)(sample_time << (3U*adc_channel)); - ADC_SAMPT1(adc_periph) = sampt; - }else if(adc_channel < 18U){ - sampt = ADC_SAMPT0(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U)))); - sampt |= (uint32_t)(sample_time << (3U*(adc_channel-10U))); - ADC_SAMPT0(adc_periph) = sampt; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief configure ADC inserted channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 - \param[in] adc_channel: the selected ADC channel - only one parameter can be selected which is shown as below: - \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx - \param[in] sample_time: The sample time value - only one parameter can be selected which is shown as below: - \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles - \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles - \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles - \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles - \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles - \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles - \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles - \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles - \param[out] none - \retval none -*/ -void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) -{ - uint8_t inserted_length; - uint32_t isq, sampt; - - /* get inserted channel group length */ - inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph), 20U, 21U); - - /* the channel number is written to these bits to select a channel as the nth conversion in the inserted channel group */ - isq = ADC_ISQ(adc_periph); - isq &= ~((uint32_t)(ADC_ISQ_ISQN << (5U * ((3U + rank) - inserted_length)))); - isq |= ((uint32_t)adc_channel << (5U * ((3U + rank) - inserted_length))); - ADC_ISQ(adc_periph) = isq; - - /* ADC sampling time config */ - if(adc_channel < 10U){ - sampt = ADC_SAMPT1(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel))); - sampt |= (uint32_t) sample_time << (3U*adc_channel); - ADC_SAMPT1(adc_periph) = sampt; - }else if(adc_channel < 18U){ - sampt = ADC_SAMPT0(adc_periph); - sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U)))); - sampt |= ((uint32_t)sample_time << (3U*(adc_channel-10U))); - ADC_SAMPT0(adc_periph) = sampt; - }else{ - } -} - -/*! - \brief configure ADC inserted channel offset - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] inserted_channel : insert channel select - only one parameter can be selected which is shown as below: - \arg ADC_INSERTED_CHANNEL_0: ADC inserted channel0 - \arg ADC_INSERTED_CHANNEL_1: ADC inserted channel1 - \arg ADC_INSERTED_CHANNEL_2: ADC inserted channel2 - \arg ADC_INSERTED_CHANNEL_3: ADC inserted channel3 - \param[in] offset : the offset data - \param[out] none - \retval none -*/ -void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset) -{ - uint8_t inserted_length; - uint32_t num = 0U; - - inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph), 20U, 21U); - num = 3U - (inserted_length - inserted_channel); - - if(num <= 3U){ - /* calculate the offset of the register */ - num = num * 4U; - /* configure the offset of the selected channels */ - REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset); - } -} - -/*! - \brief configure differential mode for ADC channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel: the channel use differential mode - one or more parameters can be selected which is shown as below: - \arg ADC_DIFFERENTIAL_MODE_CHANNEL_x(x=0..14), ADC_DIFFERENTIAL_MODE_CHANNEL_ALL: ADC channel for differential mode(just for channel0~channel14) - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void adc_channel_differential_mode_config(uint32_t adc_periph, uint32_t adc_channel, ControlStatus newvalue) -{ - if(ENABLE == newvalue){ - ADC_DIFCTL(adc_periph) |= (uint32_t)adc_channel; - }else{ - ADC_DIFCTL(adc_periph) &= ~((uint32_t)adc_channel); - } -} - -/*! - \brief configure ADC external trigger - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: select the channel group - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue) -{ - if(newvalue){ - /* external trigger enable for regular channel */ - if(RESET != (adc_channel_group & ADC_REGULAR_CHANNEL)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ETERC; - } - /* external trigger enable for inserted channel */ - if(RESET != (adc_channel_group & ADC_INSERTED_CHANNEL)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ETEIC; - } - }else{ - /* external trigger disable for regular channel */ - if(RESET != (adc_channel_group & ADC_REGULAR_CHANNEL)){ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETERC); - } - /* external trigger disable for inserted channel */ - if(RESET != (adc_channel_group & ADC_INSERTED_CHANNEL)){ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETEIC); - } - } -} - -/*! - \brief configure ADC external trigger source - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: select the channel group - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \param[in] external_trigger_source: regular or inserted group trigger source - only one parameter can be selected which is shown as below: - for regular channel: - \arg ADC0_1_EXTTRIG_REGULAR_T0_CH0: TIMER0 CH0 event select - \arg ADC0_1_EXTTRIG_REGULAR_T0_CH1: TIMER0 CH1 event select - \arg ADC0_1_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select - \arg ADC0_1_EXTTRIG_REGULAR_T1_CH1: TIMER1 CH1 event select - \arg ADC0_1_EXTTRIG_REGULAR_T2_TRGO: TIMER2 TRGO event select - \arg ADC0_1_EXTTRIG_REGULAR_T3_CH3: TIMER3 CH3 event select - \arg ADC0_1_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select - \arg ADC0_1_EXTTRIG_REGULAR_EXTI_11: external interrupt line 11 - \arg ADC0_1_EXTTRIG_REGULAR_SHRTIMER_ADCTRG0: SHRTIMER_ADCTRG0 output select(for GD32E50X_HD and GD32E50X_CL devices) - \arg ADC0_1_EXTTRIG_REGULAR_SHRTIMER_ADCTRG2: SHRTIMER_ADCTRG2 output select(for GD32E50X_HD and GD32E50X_CL devices) - \arg ADC2_EXTTRIG_REGULAR_T2_CH0: TIMER2 CH0 event select - \arg ADC2_EXTTRIG_REGULAR_T1_CH2: TIMER1 CH2 event select - \arg ADC2_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select - \arg ADC2_EXTTRIG_REGULAR_T7_CH0: TIMER7 CH0 event select - \arg ADC2_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select - \arg ADC2_EXTTRIG_REGULAR_T4_CH0: TIMER4 CH0 event select - \arg ADC2_EXTTRIG_REGULAR_T4_CH2: TIMER4 CH2 event select - \arg ADC0_1_2_EXTTRIG_REGULAR_NONE: software trigger - for inserted channel: - \arg ADC0_1_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select - \arg ADC0_1_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select - \arg ADC0_1_EXTTRIG_INSERTED_T1_TRGO: TIMER1 TRGO event select - \arg ADC0_1_EXTTRIG_INSERTED_T1_CH0: TIMER1 CH0 event select - \arg ADC0_1_EXTTRIG_INSERTED_T2_CH3: TIMER2 CH3 event select - \arg ADC0_1_EXTTRIG_INSERTED_T3_TRGO: TIMER3 TRGO event select - \arg ADC0_1_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select - \arg ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 - \arg ADC0_1_EXTTRIG_INSERTED_SHRTIMER_ADCTRG1: SHRTIMER_ADCTRG1 output select(for GD32E50X_HD and GD32E50X_CL devices) - \arg ADC0_1_EXTTRIG_INSERTED_SHRTIMER_ADCTRG3: SHRTIMER_ADCTRG3 output select(for GD32E50X_HD and GD32E50X_CL devices) - \arg ADC2_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select - \arg ADC2_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select - \arg ADC2_EXTTRIG_INSERTED_T3_CH2: TIMER3 CH2 event select - \arg ADC2_EXTTRIG_INSERTED_T7_CH1: TIMER7 CH1 event select - \arg ADC2_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select - \arg ADC2_EXTTRIG_INSERTED_T4_TRGO: TIMER4 TRGO event select - \arg ADC2_EXTTRIG_INSERTED_T4_CH3: TIMER4 CH3 event select - \arg ADC0_1_2_EXTTRIG_INSERTED_NONE: software trigger - \param[out] none - \retval none -*/ -void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source) -{ - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - /* external trigger select for regular channel */ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); - ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; - break; - case ADC_INSERTED_CHANNEL: - /* external trigger select for inserted channel */ - ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC); - ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; - break; - default: - break; - } -} - -/*! - \brief enable ADC software trigger - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: select the channel group - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \param[out] none - \retval none -*/ -void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group) -{ - /* enable regular group channel software trigger */ - if(RESET != (adc_channel_group & ADC_REGULAR_CHANNEL)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_SWRCST; - } - /* enable inserted channel group software trigger */ - if(RESET != (adc_channel_group & ADC_INSERTED_CHANNEL)){ - ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_SWICST; - } -} - -/*! - \brief read ADC regular group data register - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] none - \param[out] none - \retval the conversion value: 0~0xFFFF -*/ -uint16_t adc_regular_data_read(uint32_t adc_periph) -{ - return (uint16_t)(ADC_RDATA(adc_periph)); -} - -/*! - \brief read ADC inserted group data register - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] inserted_channel: inserted channel select - only one parameter can be selected which is shown as below: - \arg ADC_INSERTED_CHANNEL_0: ADC inserted channel0 - \arg ADC_INSERTED_CHANNEL_1: ADC inserted channel1 - \arg ADC_INSERTED_CHANNEL_2: ADC inserted channel2 - \arg ADC_INSERTED_CHANNEL_3: ADC inserted channel3 - \param[out] none - \retval the conversion value: 0~0xFFFF -*/ -uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel) -{ - uint32_t idata; - /* read the data of the selected channel */ - switch(inserted_channel){ - case ADC_INSERTED_CHANNEL_0: - idata = ADC_IDATA0(adc_periph); - break; - case ADC_INSERTED_CHANNEL_1: - idata = ADC_IDATA1(adc_periph); - break; - case ADC_INSERTED_CHANNEL_2: - idata = ADC_IDATA2(adc_periph); - break; - case ADC_INSERTED_CHANNEL_3: - idata = ADC_IDATA3(adc_periph); - break; - default: - idata = 0U; - break; - } - return (uint16_t)idata; -} - -/*! - \brief read the last ADC0 and ADC1 conversion result data in sync mode - \param[in] none - \param[out] none - \retval the conversion value: 0~0xFFFFFFFF -*/ -uint32_t adc_sync_mode_convert_value_read(void) -{ - /* return conversion value */ - return ADC_RDATA(ADC0); -} - -/*! - \brief configure ADC analog watchdog 0 single channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel: the selected ADC channel - only one parameter can be selected which is shown as below: - \arg ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0) - \param[out] none - \retval none -*/ -void adc_watchdog0_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel) -{ - ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC | ADC_CTL0_WD0CHSEL); - - ADC_CTL0(adc_periph) |= (uint32_t)adc_channel; - ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC); -} - -/*! - \brief configure ADC analog watchdog 0 group channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel_group: the channel group use analog watchdog 0 - only one parameter can be selected which is shown as below: - \arg ADC_REGULAR_CHANNEL: regular channel group - \arg ADC_INSERTED_CHANNEL: inserted channel group - \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group - \param[out] none - \retval none -*/ -void adc_watchdog0_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group) -{ - ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC); - /* select the group */ - switch(adc_channel_group){ - case ADC_REGULAR_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_RWD0EN; - break; - case ADC_INSERTED_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_IWD0EN; - break; - case ADC_REGULAR_INSERTED_CHANNEL: - ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN); - break; - default: - break; - } -} - -/*! - \brief disable ADC analog watchdog 0 - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_watchdog0_disable(uint32_t adc_periph) -{ - ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWD0EN | ADC_CTL0_IWD0EN | ADC_CTL0_WD0SC | ADC_CTL0_WD0CHSEL); -} - -/*! - \brief configure ADC analog watchdog 1 channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel: the channel use analog watchdog 1 - one or more parameters can be selected which is shown as below: - \arg ADC_AWD1_2_SELECTION_CHANNEL_x, ADC_AWD1_2_SELECTION_CHANNEL_ALL: ADC channel analog watchdog 1/2 selection - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void adc_watchdog1_channel_config(uint32_t adc_periph, uint32_t adc_channel, ControlStatus newvalue) -{ - if(ENABLE == newvalue){ - ADC_WD1SR(adc_periph) |= (uint32_t)adc_channel; - }else{ - ADC_WD1SR(adc_periph) &= ~((uint32_t)adc_channel); - } -} - -/*! - \brief configure ADC analog watchdog 2 channel - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] adc_channel: the channel use analog watchdog 2 - one or more parameters can be selected which is shown as below: - \arg ADC_AWD1_2_SELECTION_CHANNEL_x, ADC_AWD1_2_SELECTION_CHANNEL_ALL: ADC channel analog watchdog 1/2 selection - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void adc_watchdog2_channel_config(uint32_t adc_periph, uint32_t adc_channel, ControlStatus newvalue) -{ - if(ENABLE == newvalue){ - ADC_WD2SR(adc_periph) |= (uint32_t)adc_channel; - }else{ - ADC_WD2SR(adc_periph) &= ~((uint32_t)adc_channel); - } -} - -/*! - \brief disable ADC analog watchdog 1 - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_watchdog1_disable(uint32_t adc_periph) -{ - ADC_WD1SR(adc_periph) &= (uint32_t)~(ADC_WD1SR_AWD1CS); -} - -/*! - \brief disable ADC analog watchdog 2 - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_watchdog2_disable(uint32_t adc_periph) -{ - ADC_WD2SR(adc_periph) &= (uint32_t)~(ADC_WD2SR_AWD2CS); -} - -/*! - \brief configure ADC analog watchdog 0 threshold - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] low_threshold: analog watchdog 0 low threshold, 0..4095 - \param[in] high_threshold: analog watchdog 0 high threshold, 0..4095 - \param[out] none - \retval none -*/ -void adc_watchdog0_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold) -{ - ADC_WDLT0(adc_periph) = (uint32_t)WDLT0_WDLT0(low_threshold); - ADC_WDHT0(adc_periph) = (uint32_t)WDHT0_WDHT0(high_threshold); -} - -/*! - \brief configure ADC analog watchdog 1 threshold - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] low_threshold: analog watchdog 1 low threshold, 0..255 - \param[in] high_threshold: analog watchdog 1 high threshold, 0..255 - \param[out] none - \retval none -*/ -void adc_watchdog1_threshold_config(uint32_t adc_periph, uint8_t low_threshold, uint8_t high_threshold) -{ - ADC_WDT1(adc_periph) &= ~((uint32_t)(ADC_WDT1_WDLT1 | ADC_WDT1_WDHT1)); - /* configure ADC analog watchdog 1 threshold */ - ADC_WDT1(adc_periph) |= (uint32_t)WDT1_WDLT1(low_threshold); - ADC_WDT1(adc_periph) |= (uint32_t)WDT1_WDHT1(high_threshold); -} - -/*! - \brief configure ADC analog watchdog 2 threshold - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] low_threshold: analog watchdog 2 low threshold, 0..255 - \param[in] high_threshold: analog watchdog 2 high threshold, 0..255 - \param[out] none - \retval none -*/ -void adc_watchdog2_threshold_config(uint32_t adc_periph, uint8_t low_threshold, uint8_t high_threshold) -{ - ADC_WDT2(adc_periph) &= ~((uint32_t)(ADC_WDT2_WDLT2 | ADC_WDT2_WDHT2)); - /* configure ADC analog watchdog 2 threshold */ - ADC_WDT2(adc_periph) |= (uint32_t)WDT2_WDLT2(low_threshold); - ADC_WDT2(adc_periph) |= (uint32_t)WDT2_WDHT2(high_threshold); -} - -/*! - \brief configure ADC resolution - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] resolution: ADC resolution - only one parameter can be selected which is shown as below: - \arg ADC_RESOLUTION_12B: 12-bit ADC resolution - \arg ADC_RESOLUTION_10B: 10-bit ADC resolution - \arg ADC_RESOLUTION_8B: 8-bit ADC resolution - \arg ADC_RESOLUTION_6B: 6-bit ADC resolution - \param[out] none - \retval none -*/ -void adc_resolution_config(uint32_t adc_periph, uint32_t resolution) -{ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_DRES); - ADC_OVSAMPCTL(adc_periph) |= (uint32_t)resolution; -} - -/*! - \brief configure ADC oversample mode - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] mode: ADC oversampling mode - only one parameter can be selected which is shown as below: - \arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger - \arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger - \param[in] shift: ADC oversampling shift - only one parameter can be selected which is shown as below: - \arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift - \param[in] ratio: ADC oversampling ratio - only one parameter can be selected which is shown as below: - \arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2 - \arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4 - \arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8 - \arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16 - \arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32 - \arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64 - \arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128 - \arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256 - \param[out] none - \retval none -*/ -void adc_oversample_mode_config(uint32_t adc_periph, uint32_t mode, uint16_t shift, uint8_t ratio) -{ - /* configure ADC oversampling mode */ - if(ADC_OVERSAMPLING_ONE_CONVERT == mode){ - ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS; - }else{ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS); - } - /* configure the shift and ratio */ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS)); - ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio); -} - -/*! - \brief enable ADC oversample mode - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_oversample_mode_enable(uint32_t adc_periph) -{ - ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_OVSEN; -} - -/*! - \brief disable ADC oversample mode - \param[in] adc_periph: ADCx, x=0,1,2 - \param[out] none - \retval none -*/ -void adc_oversample_mode_disable(uint32_t adc_periph) -{ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN); -} - -/*! - \brief get the ADC flag - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] flag: the ADC flag bits - only one parameter can be selected which is shown as below: - \arg ADC_FLAG_WDE0: analog watchdog 0 event flag - \arg ADC_FLAG_EOC: end of group conversion flag - \arg ADC_FLAG_EOIC: end of inserted group conversion flag - \arg ADC_FLAG_STIC: start flag of inserted channel group - \arg ADC_FLAG_STRC: start flag of regular channel group - \arg ADC_FLAG_WDE1: analog watchdog 1 event flag - \arg ADC_FLAG_WDE2: analog watchdog 2 event flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t flag) -{ - FlagStatus reval = RESET; - if(ADC_STAT(adc_periph) & flag){ - reval = SET; - } - return reval; -} - -/*! - \brief clear the ADC flag - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] flag: the ADC flag - one or more parameters can be selected which is shown as below: - \arg ADC_FLAG_WDE0: analog watchdog 0 event flag - \arg ADC_FLAG_EOC: end of group conversion flag - \arg ADC_FLAG_EOIC: end of inserted group conversion flag - \arg ADC_FLAG_STIC: start flag of inserted channel group - \arg ADC_FLAG_STRC: start flag of regular channel group - \arg ADC_FLAG_WDE1: analog watchdog 1 event flag - \arg ADC_FLAG_WDE2: analog watchdog 2 event flag - \param[out] none - \retval none -*/ -void adc_flag_clear(uint32_t adc_periph , uint32_t flag) -{ - ADC_STAT(adc_periph) &= ~((uint32_t)flag); -} - -/*! - \brief enable ADC interrupt - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] interrupt: the ADC interrupt - one or more parameters can be selected which is shown as below: - \arg ADC_INT_WDE0: analog watchdog 0 interrupt flag - \arg ADC_INT_EOC: end of group conversion interrupt flag - \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag - \arg ADC_INT_WDE1: analog watchdog 1 interrupt flag - \arg ADC_INT_WDE2: analog watchdog 2 interrupt flag - \param[out] none - \retval none -*/ -void adc_interrupt_enable(uint32_t adc_periph , uint32_t interrupt) -{ - switch(interrupt){ - /* enable analog watchdog 0 interrupt */ - case ADC_INT_WDE0: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_WDE0IE; - break; - /* enable end of group conversion interrupt */ - case ADC_INT_EOC: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_EOCIE; - break; - /* enable end of inserted group conversion interrupt */ - case ADC_INT_EOIC: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_EOICIE; - break; - /* enable analog watchdog 1 interrupt */ - case ADC_INT_WDE1: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_WDE1IE; - break; - /* enable analog watchdog 2 interrupt */ - case ADC_INT_WDE2: - ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_WDE2IE; - break; - default: - break; - } -} - -/*! - \brief disable ADC interrupt - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] interrupt: the ADC interrupt flag - one or more parameters can be selected which is shown as below: - \arg ADC_INT_WDE0: analog watchdog 0 interrupt flag - \arg ADC_INT_EOC: end of group conversion interrupt flag - \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag - \arg ADC_INT_WDE1: analog watchdog 1 interrupt flag - \arg ADC_INT_WDE2: analog watchdog 2 interrupt flag - \param[out] none - \retval none -*/ -void adc_interrupt_disable(uint32_t adc_periph, uint32_t interrupt) -{ - switch(interrupt){ - /* disable analog watchdog 0 interrupt */ - case ADC_INT_WDE0: - ADC_CTL0(adc_periph) &= ~(uint32_t)ADC_CTL0_WDE0IE; - break; - /* disable end of group conversion interrupt */ - case ADC_INT_EOC: - ADC_CTL0(adc_periph) &= ~(uint32_t)ADC_CTL0_EOCIE; - break; - /* disable end of inserted group conversion interrupt */ - case ADC_INT_EOIC: - ADC_CTL0(adc_periph) &= ~(uint32_t)ADC_CTL0_EOICIE; - break; - /* disable analog watchdog 1 interrupt */ - case ADC_INT_WDE1: - ADC_CTL0(adc_periph) &= ~(uint32_t)ADC_CTL0_WDE1IE; - break; - /* disable analog watchdog 2 interrupt */ - case ADC_INT_WDE2: - ADC_CTL0(adc_periph) &= ~(uint32_t)ADC_CTL0_WDE1IE; - break; - default: - break; - } -} - -/*! - \brief get ADC interrupt flag - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] int_flag: the ADC interrupt - only one parameter can be selected which is shown as below: - \arg ADC_INT_FLAG_WDE0: analog watchdog 0 interrupt flag - \arg ADC_INT_FLAG_EOC: end of group conversion interrupt flag - \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt - \arg ADC_INT_FLAG_WDE1: analog watchdog 1 interrupt flag - \arg ADC_INT_FLAG_WDE2: analog watchdog 2 interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t int_flag) -{ - FlagStatus interrupt_flag = RESET; - uint32_t state; - /* check the interrupt bits */ - switch(int_flag){ - case ADC_INT_FLAG_WDE0: - state = ADC_STAT(adc_periph) & ADC_STAT_WDE0; - if((ADC_CTL0(adc_periph) & ADC_CTL0_WDE0IE) && state){ - interrupt_flag = SET; - } - break; - case ADC_INT_FLAG_EOC: - state = ADC_STAT(adc_periph) & ADC_STAT_EOC; - if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){ - interrupt_flag = SET; - } - break; - case ADC_INT_FLAG_EOIC: - state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; - if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){ - interrupt_flag = SET; - } - break; - case ADC_INT_FLAG_WDE1: - state = ADC_STAT(adc_periph) & ADC_STAT_WDE1; - if((ADC_CTL0(adc_periph) & ADC_CTL0_WDE1IE) && state){ - interrupt_flag = SET; - } - break; - case ADC_INT_FLAG_WDE2: - state = ADC_STAT(adc_periph) & ADC_STAT_WDE2; - if((ADC_CTL0(adc_periph) & ADC_CTL0_WDE2IE) && state){ - interrupt_flag = SET; - } - break; - default: - break; - } - return interrupt_flag; -} - -/*! - \brief clear ADC interrupt flag - \param[in] adc_periph: ADCx, x=0,1,2 - \param[in] int_flag: the ADC interrupt flag - only one parameter can be selected which is shown as below: - \arg ADC_INT_FLAG_WDE0: analog watchdog 0 interrupt flag - \arg ADC_INT_FLAG_EOC: end of group conversion interrupt flag - \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt flag - \arg ADC_INT_FLAG_WDE1: analog watchdog 1 interrupt flag - \arg ADC_INT_FLAG_WDE2: analog watchdog 2 interrupt flag - \param[out] none - \retval none -*/ -void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t int_flag) -{ - ADC_STAT(adc_periph) &= ~((uint32_t)int_flag); -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_can.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_can.c deleted file mode 100644 index ba6eb61..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_can.c +++ /dev/null @@ -1,1615 +0,0 @@ -/*! - \file gd32e50x_can.c - \brief CAN 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. -*/ -#ifndef GD32EPRT -#include "gd32e50x_can.h" -#include - -#define CAN_ERROR_HANDLE(s) do{}while(1) - -/* This table can be used to calculate data length in FD mode */ -const uint8_t g_can_fdlength_table[] = {12, 16, 20, 24, 32, 48, 64}; - -/*! - \brief deinitialize CAN - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_deinit(uint32_t can_periph) -{ -#if defined(GD32E50X_CL) || defined(GD32E508) - switch(can_periph) { - case CAN0: - rcu_periph_reset_enable(RCU_CAN0RST); - rcu_periph_reset_disable(RCU_CAN0RST); - break; - case CAN1: - rcu_periph_reset_enable(RCU_CAN1RST); - rcu_periph_reset_disable(RCU_CAN1RST); - break; - case CAN2: - rcu_periph_reset_enable(RCU_CAN2RST); - rcu_periph_reset_disable(RCU_CAN2RST); - break; - default: - break; - } -#else - switch(can_periph) { - case CAN0: - rcu_periph_reset_enable(RCU_CAN0RST); - rcu_periph_reset_disable(RCU_CAN0RST); - break; - case CAN1: - rcu_periph_reset_enable(RCU_CAN1RST); - rcu_periph_reset_disable(RCU_CAN1RST); - break; - default: - break; - } -#endif -} - -/*! - \brief initialize CAN parameter struct - \param[in] type: the type of CAN parameter struct - only one parameter can be selected which is shown as below: - \arg CAN_INIT_STRUCT: the CAN initial struct - \arg CAN_FILTER_STRUCT: the CAN filter struct - \arg CAN_FD_FRAME_STRUCT: the CAN FD initial struct - \arg CAN_TX_MESSAGE_STRUCT: the CAN TX message struct - \arg CAN_RX_MESSAGE_STRUCT: the CAN RX message struct - \param[in] p_struct: the pointer of the specific struct - \param[out] none - \retval none -*/ -void can_struct_para_init(can_struct_type_enum type, void *p_struct) -{ - uint8_t i; - - if(NULL == p_struct) { - CAN_ERROR_HANDLE("struct parameter can not be NULL \r\n"); - } - /* get type of the struct */ - switch(type) { - /* used for can_init() */ - case CAN_INIT_STRUCT: - ((can_parameter_struct *)p_struct)->auto_bus_off_recovery = DISABLE; - ((can_parameter_struct *)p_struct)->auto_retrans = DISABLE; - ((can_parameter_struct *)p_struct)->auto_wake_up = DISABLE; - ((can_parameter_struct *)p_struct)->prescaler = 0x0400U; - ((can_parameter_struct *)p_struct)->rec_fifo_overwrite = DISABLE; - ((can_parameter_struct *)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ; - ((can_parameter_struct *)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ; - ((can_parameter_struct *)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ; - ((can_parameter_struct *)p_struct)->time_triggered = DISABLE; - ((can_parameter_struct *)p_struct)->trans_fifo_order = DISABLE; - ((can_parameter_struct *)p_struct)->working_mode = CAN_NORMAL_MODE; - break; - /* used for can_filter_init() */ - case CAN_FILTER_STRUCT: - ((can_filter_parameter_struct *)p_struct)->filter_bits = CAN_FILTERBITS_32BIT; - ((can_filter_parameter_struct *)p_struct)->filter_enable = DISABLE; - ((can_filter_parameter_struct *)p_struct)->filter_fifo_number = CAN_FIFO0; - ((can_filter_parameter_struct *)p_struct)->filter_list_high = 0x0000U; - ((can_filter_parameter_struct *)p_struct)->filter_list_low = 0x0000U; - ((can_filter_parameter_struct *)p_struct)->filter_mask_high = 0x0000U; - ((can_filter_parameter_struct *)p_struct)->filter_mask_low = 0x0000U; - ((can_filter_parameter_struct *)p_struct)->filter_mode = CAN_FILTERMODE_MASK; - ((can_filter_parameter_struct *)p_struct)->filter_number = 0U; - break; -#ifdef GD32E508 - /* used for can_fd_init() */ - case CAN_FD_FRAME_STRUCT: - ((can_fdframe_struct *)p_struct)->data_prescaler = 0x0400U; - ((can_fdframe_struct *)p_struct)->data_resync_jump_width = 1U - 1U; - ((can_fdframe_struct *)p_struct)->data_time_segment_1 = 3U - 1U; - ((can_fdframe_struct *)p_struct)->data_time_segment_2 = 2U - 1U; - ((can_fdframe_struct *)p_struct)->delay_compensation = DISABLE; - ((can_fdframe_struct *)p_struct)->esi_mode = CAN_ESIMOD_HARDWARE; - ((can_fdframe_struct *)p_struct)->excp_event_detect = ENABLE; - ((can_fdframe_struct *)p_struct)->fd_frame = DISABLE; - ((can_fdframe_struct *)p_struct)->iso_bosch = CAN_FDMOD_ISO; - ((can_fdframe_struct *)p_struct)->p_delay_compensation = 0U; - break; - /* used for can_message_transmit() */ - case CAN_TX_MESSAGE_STRUCT: - ((can_trasnmit_message_struct *)p_struct)->fd_brs = CAN_BRS_DISABLE; - ((can_trasnmit_message_struct *)p_struct)->fd_esi = CAN_ESI_DOMINANT; - ((can_trasnmit_message_struct *)p_struct)->fd_flag = CAN_FDF_CLASSIC; - - for(i = 0U; i < 64U; i++) { - ((can_trasnmit_message_struct *)p_struct)->tx_data[i] = 0U; - } - - ((can_trasnmit_message_struct *)p_struct)->tx_dlen = 0u; - ((can_trasnmit_message_struct *)p_struct)->tx_efid = 0U; - ((can_trasnmit_message_struct *)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; - ((can_trasnmit_message_struct *)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; - ((can_trasnmit_message_struct *)p_struct)->tx_sfid = 0U; - break; - /* used for can_message_receive() */ - case CAN_RX_MESSAGE_STRUCT: - ((can_receive_message_struct *)p_struct)->fd_brs = CAN_BRS_DISABLE; - ((can_receive_message_struct *)p_struct)->fd_esi = CAN_ESI_DOMINANT; - ((can_receive_message_struct *)p_struct)->fd_flag = CAN_FDF_CLASSIC; - - for(i = 0U; i < 64U; i++) { - ((can_receive_message_struct *)p_struct)->rx_data[i] = 0U; - } - - ((can_receive_message_struct *)p_struct)->rx_dlen = 0U; - ((can_receive_message_struct *)p_struct)->rx_efid = 0U; - ((can_receive_message_struct *)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; - ((can_receive_message_struct *)p_struct)->rx_fi = 0U; - ((can_receive_message_struct *)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; - ((can_receive_message_struct *)p_struct)->rx_sfid = 0U; - break; -#else - /* used for can_message_transmit() */ - case CAN_TX_MESSAGE_STRUCT: - for(i = 0U; i < 8U; i++) { - ((can_trasnmit_message_struct *)p_struct)->tx_data[i] = 0U; - } - - ((can_trasnmit_message_struct *)p_struct)->tx_dlen = 0u; - ((can_trasnmit_message_struct *)p_struct)->tx_efid = 0U; - ((can_trasnmit_message_struct *)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; - ((can_trasnmit_message_struct *)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; - ((can_trasnmit_message_struct *)p_struct)->tx_sfid = 0U; - break; - /* used for can_message_receive() */ - case CAN_RX_MESSAGE_STRUCT: - for(i = 0U; i < 8U; i++) { - ((can_receive_message_struct *)p_struct)->rx_data[i] = 0U; - } - - ((can_receive_message_struct *)p_struct)->rx_dlen = 0U; - ((can_receive_message_struct *)p_struct)->rx_efid = 0U; - ((can_receive_message_struct *)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; - ((can_receive_message_struct *)p_struct)->rx_fi = 0U; - ((can_receive_message_struct *)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; - ((can_receive_message_struct *)p_struct)->rx_sfid = 0U; - break; - -#endif /* GD32E508 */ - default: - CAN_ERROR_HANDLE("parameter is invalid \r\n"); - break; - } -} - -/*! - \brief initialize CAN - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] can_parameter_init: parameters for CAN initializtion - \arg working_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE - \arg resync_jump_width: 0x00 - 0x07 - \arg time_segment_1: 0x00 - 0x7F - \arg time_segment_2: 0x00 - 0x1F - \arg time_triggered: ENABLE or DISABLE - \arg auto_bus_off_recovery: ENABLE or DISABLE - \arg auto_wake_up: ENABLE or DISABLE - \arg auto_retrans: ENABLE or DISABLE - \arg rec_fifo_overwrite: ENABLE or DISABLE - \arg trans_fifo_order: ENABLE or DISABLE - \arg prescaler: 0x0001 - 0x0400 - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus can_init(uint32_t can_periph, can_parameter_struct *can_parameter_init) -{ - uint32_t timeout = CAN_TIMEOUT; - ErrStatus flag = ERROR; -#ifdef GD32E508 - uint32_t fdctl_status; -#endif /* GD32E508 */ - - /* disable sleep mode */ - CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; - /* enable initialize mode */ - CAN_CTL(can_periph) |= CAN_CTL_IWMOD; - /* wait ACK */ - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - /* check initialize working success */ - if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) { - flag = ERROR; - } else { -#ifdef GD32E508 - /* set the bit timing register */ - fdctl_status = CAN_FDCTL(can_periph); - if(CAN_FDCTL_FDEN != (fdctl_status & CAN_FDCTL_FDEN)) { - /* CAN FD disable, should frist enable, then write */ - fdctl_status = fdctl_status | CAN_FDCTL_FDEN; - CAN_FDCTL(can_periph) = fdctl_status; - CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ - BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ - BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ - BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ - BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); - fdctl_status = fdctl_status & (~CAN_FDCTL_FDEN); - CAN_FDCTL(can_periph) = fdctl_status; - } else { - /* CAN FD enable */ - CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ - BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ - BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ - BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ - BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); - } -#else - /* set the bit timing register */ - CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ - BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ - BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ - BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ - BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); - -#endif /* GD32E508 */ - /* time trigger communication mode */ - if(ENABLE == can_parameter_init->time_triggered) { - CAN_CTL(can_periph) |= CAN_CTL_TTC; - } else { - CAN_CTL(can_periph) &= ~CAN_CTL_TTC; - } - /* automatic bus-off managment */ - if(ENABLE == can_parameter_init->auto_bus_off_recovery) { - CAN_CTL(can_periph) |= CAN_CTL_ABOR; - } else { - CAN_CTL(can_periph) &= ~CAN_CTL_ABOR; - } - /* automatic wakeup mode */ - if(ENABLE == can_parameter_init->auto_wake_up) { - CAN_CTL(can_periph) |= CAN_CTL_AWU; - } else { - CAN_CTL(can_periph) &= ~CAN_CTL_AWU; - } - /* automatic retransmission mode */ - if(ENABLE == can_parameter_init->auto_retrans) { - CAN_CTL(can_periph) &= ~CAN_CTL_ARD; - } else { - CAN_CTL(can_periph) |= CAN_CTL_ARD; - } - /* receive fifo overwrite mode */ - if(ENABLE == can_parameter_init->rec_fifo_overwrite) { - CAN_CTL(can_periph) &= ~CAN_CTL_RFOD; - } else { - CAN_CTL(can_periph) |= CAN_CTL_RFOD; - } - /* transmit fifo order */ - if(ENABLE == can_parameter_init->trans_fifo_order) { - CAN_CTL(can_periph) |= CAN_CTL_TFO; - } else { - CAN_CTL(can_periph) &= ~CAN_CTL_TFO; - } - /* disable initialize mode */ - CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; - timeout = CAN_TIMEOUT; - /* wait the ACK */ - while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - /* check exit initialize mode */ - if(0U != timeout) { - flag = SUCCESS; - } - } - return flag; -} - -/*! - \brief initialize CAN filter - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] can_filter_parameter_init: struct for CAN filter initialization - \arg filter_list_high: 0x0000 - 0xFFFF - \arg filter_list_low: 0x0000 - 0xFFFF - \arg filter_mask_high: 0x0000 - 0xFFFF - \arg filter_mask_low: 0x0000 - 0xFFFF - \arg filter_fifo_number: CAN_FIFO0, CAN_FIFO1 - \arg filter_number: In CAN0(0 - 27), In CAN2(0 - 14) - \arg filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST - \arg filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT - \arg filter_enable: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void can_filter_init(uint32_t can_periph, can_filter_parameter_struct *can_filter_parameter_init) -{ - uint32_t val = 0U; - - val = ((uint32_t)1) << (can_filter_parameter_init->filter_number); - if(CAN1 == can_periph) { - can_periph = CAN0; - } - /* filter lock disable */ - CAN_FCTL(can_periph) |= CAN_FCTL_FLD; - /* disable filter */ - CAN_FW(can_periph) &= ~(uint32_t)val; - - /* filter 16 bits */ - if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits) { - /* set filter 16 bits */ - CAN_FSCFG(can_periph) &= ~(uint32_t)val; - /* first 16 bits list and first 16 bits mask or first 16 bits list and second 16 bits list */ - CAN_FDATA0(can_periph, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \ - FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); - /* second 16 bits list and second 16 bits mask or third 16 bits list and fourth 16 bits list */ - CAN_FDATA1(can_periph, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \ - FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS); - } - /* filter 32 bits */ - if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits) { - /* set filter 32 bits */ - CAN_FSCFG(can_periph) |= (uint32_t)val; - /* 32 bits list or first 32 bits list */ - CAN_FDATA0(can_periph, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) | - FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); - /* 32 bits mask or second 32 bits list */ - CAN_FDATA1(can_periph, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | - FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS); - } - - /* filter mode */ - if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode) { - /* mask mode */ - CAN_FMCFG(can_periph) &= ~(uint32_t)val; - } else { - /* list mode */ - CAN_FMCFG(can_periph) |= (uint32_t)val; - } - - /* filter FIFO */ - if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)) { - /* FIFO0 */ - CAN_FAFIFO(can_periph) &= ~(uint32_t)val; - } else { - /* FIFO1 */ - CAN_FAFIFO(can_periph) |= (uint32_t)val; - } - - /* filter working */ - if(ENABLE == can_filter_parameter_init->filter_enable) { - - CAN_FW(can_periph) |= (uint32_t)val; - } - - /* filter lock enable */ - CAN_FCTL(can_periph) &= ~CAN_FCTL_FLD; -} - -/*! - \brief CAN filter mask mode initialization - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] id: extended(11-bits) or standard(29-bits) identifier - \arg 0x00000000 - 0x1FFFFFFF - \param[in] mask: extended(11-bits) or standard(29-bits) identifier mask - \arg 0x00000000 - 0x1FFFFFFF - \param[in] format_fifo: format and fifo states - only one parameter can be selected which is shown as below: - \arg CAN_STANDARD_FIFO0 - \arg CAN_STANDARD_FIFO1 - \arg CAN_EXTENDED_FIFO0 - \arg CAN_EXTENDED_FIFO1 - \param[in] filter_number: filter sequence number - \arg In CAN0:0 - 27 ,In CAN2:0 - 14 - \param[out] none - \retval none -*/ -void can_filter_mask_mode_init(uint32_t can_periph, uint32_t id, uint32_t mask, can_format_fifo_enum format_fifo, uint16_t filter_number) -{ - can_filter_parameter_struct can_filter; - - /* Initialize the filter structure */ - can_struct_para_init(CAN_FILTER_STRUCT, &can_filter); - if(CAN1 == can_periph) { - can_periph = CAN0; - } - /* filter config */ - can_filter.filter_number = filter_number; - can_filter.filter_mode = CAN_FILTERMODE_MASK; - can_filter.filter_bits = CAN_FILTERBITS_32BIT; - can_filter.filter_enable = ENABLE; - - switch(format_fifo) { - /* standard FIFO 0 */ - case CAN_STANDARD_FIFO0: - can_filter.filter_fifo_number = CAN_FIFO0; - /* configure SFID[10:0] */ - can_filter.filter_list_high = (uint16_t)id << 5; - can_filter.filter_list_low = 0x0000U; - /* configure SFID[10:0] mask */ - can_filter.filter_mask_high = (uint16_t)mask << 5; - /* both data and remote frames can be received */ - can_filter.filter_mask_low = (uint16_t)(1U << 2U); - - break; - /* standard FIFO 1 */ - case CAN_STANDARD_FIFO1: - can_filter.filter_fifo_number = CAN_FIFO1; - /* configure SFID[10:0] */ - can_filter.filter_list_high = (uint16_t)id << 5; - can_filter.filter_list_low = 0x0000U; - /* configure SFID[10:0] mask */ - can_filter.filter_mask_high = (uint16_t)mask << 5; - /* both data and remote frames can be received */ - can_filter.filter_mask_low = (uint16_t)(1U << 2U); - - break; - /* extended FIFO 0 */ - case CAN_EXTENDED_FIFO0: - can_filter.filter_fifo_number = CAN_FIFO0; - /* configure EFID[28:13] */ - can_filter.filter_list_high = (uint16_t)(id >> 13); - /* configure EFID[12:0] and frame format bit set */ - can_filter.filter_list_low = ((uint16_t)(id << 3)) | (1U << 2); - /* configure EFID[28:13] mask */ - can_filter.filter_mask_high = (uint16_t)(mask >> 13); - /* configure EFID[12:0] and frame format bit mask */ - /* both data and remote frames can be received */ - can_filter.filter_mask_low = ((uint16_t)(mask << 3)) | (1U << 2); - - break; - /* extended FIFO 1 */ - case CAN_EXTENDED_FIFO1: - can_filter.filter_fifo_number = CAN_FIFO1; - /* configure EFID[28:13] */ - can_filter.filter_list_high = (uint16_t)(id >> 13); - /* configure EFID[12:0] and frame format bit set */ - can_filter.filter_list_low = ((uint16_t)(id << 3)) | (1U << 2); - /* configure EFID[28:13] mask */ - can_filter.filter_mask_high = (uint16_t)(mask >> 13); - /* configure EFID[12:0] and frame format bit mask */ - /* both data and remote frames can be received */ - can_filter.filter_mask_low = ((uint16_t)(mask << 3)) | (1U << 2); - - break; - default: - CAN_ERROR_HANDLE("parameter is invalid \r\n"); - } - - can_filter_init(can_periph, &can_filter); -} - -/*! - \brief CAN communication mode configure - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] mode: communication mode - only one parameter can be selected which is shown as below: - \arg CAN_NORMAL_MODE - \arg CAN_LOOPBACK_MODE - \arg CAN_SILENT_MODE - \arg CAN_SILENT_LOOPBACK_MODE - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus can_monitor_mode_set(uint32_t can_periph, uint8_t mode) -{ - ErrStatus reval = SUCCESS; - uint32_t timeout = CAN_TIMEOUT; - - if(mode == (mode & CAN_SILENT_LOOPBACK_MODE)) { - /* disable sleep mode */ - CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); - /* set initialize mode */ - CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; - /* wait the acknowledge */ - timeout = CAN_TIMEOUT; - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - - if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) { - reval = ERROR; - } else { - CAN_BT(can_periph) &= ~BT_MODE(3); - CAN_BT(can_periph) |= BT_MODE(mode); - - timeout = CAN_TIMEOUT; - /* enter normal mode */ - CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); - /* wait the acknowledge */ - while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)) { - timeout--; - } - if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) { - reval = ERROR; - } - } - } else { - reval = ERROR; - } - - return reval; -} - -#ifdef GD32E508 -/*! - \brief initialize CAN FD function - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] can_fdframe_init: parameters for CAN FD initializtion - \arg fd_frame: ENABLE or DISABLE - \arg excp_event_detect: ENABLE or DISABLE - \arg delay_compensation: ENABLE or DISABLE - \arg p_delay_compensation: the pointer of tdc struct - can_fd_tdc_struct: - tdc_mode: CAN_TDCMOD_CALC_AND_OFFSET or CAN_TDCMOD_OFFSET - tdc_filter: 0x00 - 0x07 - tdc_offset: 0x00 - 0x07 - \arg iso_bosch: CAN_FDMOD_ISO or CAN_FDMOD_BOSCH - \arg esi_mode: CAN_ESIMOD_HARDWARE or CAN_ESIMOD_SOFTWARE - \arg data_resync_jump_width: 0x00 - 0x07 - \arg data_time_segment_1: 0x00 - 0x0F - \arg data_time_segment_2: 0x00 - 0x07 - \arg data_prescaler: 0x0001 - 0x0400 - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus can_fd_init(uint32_t can_periph, can_fdframe_struct *can_fdframe_init) -{ - uint32_t timeout = CAN_TIMEOUT; - uint32_t tempreg = 0U; - - /* check null pointer */ - if(0 == can_fdframe_init) { - return ERROR; - } - /* disable sleep mode */ - CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; - /* enable initialize mode */ - CAN_CTL(can_periph) |= CAN_CTL_IWMOD; - /* wait ACK */ - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - /* check initialize working success */ - if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) { - return ERROR; - } else { - /* set the data bit timing register */ - CAN_DBT(can_periph) = (BT_DSJW((uint32_t)can_fdframe_init->data_resync_jump_width) | \ - BT_DBS1((uint32_t)can_fdframe_init->data_time_segment_1) | \ - BT_DBS2((uint32_t)can_fdframe_init->data_time_segment_2) | \ - BT_BAUDPSC(((uint32_t)can_fdframe_init->data_prescaler) - 1U)); - - tempreg = can_fdframe_init->esi_mode | can_fdframe_init->iso_bosch; - - /* Protocol exception event detection */ - if(ENABLE == can_fdframe_init->excp_event_detect) { - tempreg &= ~CAN_FDCTL_PRED; - } else { - tempreg |= CAN_FDCTL_PRED; - } - - /* Transmitter delay compensation mode */ - if(ENABLE == can_fdframe_init->delay_compensation) { - tempreg |= CAN_FDCTL_TDCEN; - /* p_delay_compensation pointer should be config when TDC mode is enabled */ - if(0 != can_fdframe_init->p_delay_compensation) { - tempreg |= (can_fdframe_init->p_delay_compensation->tdc_mode & CAN_FDCTL_TDCMOD); - CAN_FDTDC(can_periph) = (FDTDC_TDCF(can_fdframe_init->p_delay_compensation->tdc_filter) | FDTDC_TDCO( - can_fdframe_init->p_delay_compensation->tdc_offset)); - } else { - return ERROR; - } - } else { - /* Transmitter delay compensation mode is disabled */ - tempreg &= ~CAN_FDCTL_TDCEN; - } - - /* FD operation mode */ - if(ENABLE == can_fdframe_init->fd_frame) { - tempreg |= CAN_FDCTL_FDEN; - } else { - tempreg &= ~CAN_FDCTL_FDEN; - } - CAN_FDCTL(can_periph) = tempreg; - - /* disable initialize mode */ - CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; - timeout = CAN_TIMEOUT; - /* wait the ACK */ - while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - /* check exit initialize mode */ - if(0U == timeout) { - return ERROR; - } - } - - return SUCCESS; -} - -/*! - \brief CAN FD frame function enable - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_fd_function_enable(uint32_t can_periph) -{ - CAN_FDCTL(can_periph) |= CAN_FDCTL_FDEN; -} - -/*! - \brief CAN FD frame function disable - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL - \param[out] none - \retval none -*/ -void can_fd_function_disable(uint32_t can_periph) -{ - CAN_FDCTL(can_periph) &= ~CAN_FDCTL_FDEN; -} -#endif /* GD32E508 */ - -/*! - \brief set CAN1 fliter start bank number - \param[in] start_bank: CAN1 start bank number - only one parameter can be selected which is shown as below: - \arg (1..27) - \param[out] none - \retval none -*/ -void can1_filter_start_bank(uint8_t start_bank) -{ - /* filter lock disable */ - CAN_FCTL(CAN0) |= CAN_FCTL_FLD; - /* set CAN1 filter start number */ - CAN_FCTL(CAN0) &= ~(uint32_t)CAN_FCTL_HBC1F; - CAN_FCTL(CAN0) |= FCTL_HBC1F(start_bank); - /* filter lock enable */ - CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; -} - -/*! - \brief enable CAN debug freeze - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_debug_freeze_enable(uint32_t can_periph) -{ - /* set DFZ bit */ - CAN_CTL(can_periph) |= CAN_CTL_DFZ; -#ifdef GD32E50X_CL - switch(can_periph) { - case CAN0: - dbg_periph_enable(DBG_CAN0_HOLD); - break; - case CAN1: - dbg_periph_enable(DBG_CAN1_HOLD); - break; - case CAN2: - dbg_periph_enable(DBG_CAN2_HOLD); - break; - default: - break; - } -#else - switch(can_periph) { - case CAN0: - dbg_periph_enable(DBG_CAN0_HOLD); - break; - case CAN1: - dbg_periph_enable(DBG_CAN1_HOLD); - break; - default: - break; - } -#endif -} - -/*! - \brief disable CAN debug freeze - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_debug_freeze_disable(uint32_t can_periph) -{ - /* set DFZ bit */ - CAN_CTL(can_periph) &= ~CAN_CTL_DFZ; -#ifdef GD32E50X_CL - switch(can_periph) { - case CAN0: - dbg_periph_disable(DBG_CAN0_HOLD); - break; - case CAN1: - dbg_periph_disable(DBG_CAN1_HOLD); - break; - case CAN2: - dbg_periph_disable(DBG_CAN2_HOLD); - break; - default: - break; -#else - switch(can_periph) { - case CAN0: - dbg_periph_disable(DBG_CAN0_HOLD); - break; - case CAN1: - dbg_periph_disable(DBG_CAN1_HOLD); - break; - default: - break; -#endif - } -} - -/*! - \brief enable CAN time trigger mode - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_time_trigger_mode_enable(uint32_t can_periph) -{ - uint8_t mailbox_number; - - /* enable the tcc mode */ - CAN_CTL(can_periph) |= CAN_CTL_TTC; - /* enable time stamp */ - for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++) { - CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN; - } -} - -/*! - \brief disable CAN time trigger mode - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_time_trigger_mode_disable(uint32_t can_periph) -{ - uint8_t mailbox_number; - - /* disable the TCC mode */ - CAN_CTL(can_periph) &= ~CAN_CTL_TTC; - /* reset TSEN bits */ - for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++) { - CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN; - } -} - -/*! - \brief transmit CAN message - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] transmit_message: struct for CAN transmit message - \arg tx_sfid: 0x00000000 - 0x000007FF - \arg tx_efid: 0x00000000 - 0x1FFFFFFF - \arg tx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED - \arg tx_ft: CAN_FT_DATA, CAN_FT_REMOTE - \arg tx_dlen: 0 - 8 (FD mode: 0 - 8, or 12, 16, 20, 24, 32, 48, 64) - \arg tx_data[]: 0x00 - 0xFF - \param[out] none - \retval mailbox_number -*/ -uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct *transmit_message) -{ - uint8_t mailbox_number = CAN_MAILBOX0; - volatile uint32_t p_temp; -#ifdef GD32E508 - uint8_t i = 0U; - uint8_t hit = 0U; - uint32_t canfd_en = 0U; - uint32_t reg_temp = 0U; -#endif /* GD32E508 */ - - /* select one empty mailbox */ - if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)) { - mailbox_number = CAN_MAILBOX0; - } else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)) { - mailbox_number = CAN_MAILBOX1; - } else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)) { - mailbox_number = CAN_MAILBOX2; - } else { - mailbox_number = CAN_NOMAILBOX; - } - /* return no mailbox empty */ - if(CAN_NOMAILBOX == mailbox_number) { - return CAN_NOMAILBOX; - } - - CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN; - if(CAN_FF_STANDARD == transmit_message->tx_ff) { - /* set transmit mailbox standard identifier */ - CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \ - transmit_message->tx_ft); - } else { - /* set transmit mailbox extended identifier */ - CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \ - transmit_message->tx_ff | \ - transmit_message->tx_ft); - } - -#ifdef GD32E508 - if(CAN_FDF_CLASSIC == transmit_message->fd_flag) { - /* set the data length */ - CAN_TMP(can_periph, mailbox_number) &= ~(CAN_TMP_DLENC | CAN_TMP_ESI | CAN_TMP_BRS | CAN_TMP_FDF); - /* Classic CAN frame data length does not exceed 8 */ - if (transmit_message->tx_dlen > 8U) { - transmit_message->tx_dlen = 8U; - } - CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen; - /* set the data */ - CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \ - TMDATA0_DB2(transmit_message->tx_data[2]) | \ - TMDATA0_DB1(transmit_message->tx_data[1]) | \ - TMDATA0_DB0(transmit_message->tx_data[0]); - CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \ - TMDATA1_DB6(transmit_message->tx_data[6]) | \ - TMDATA1_DB5(transmit_message->tx_data[5]) | \ - TMDATA1_DB4(transmit_message->tx_data[4]); - } else { - canfd_en = CAN_FDCTL(can_periph) & CAN_FDCTL_FDEN; - /* check FD funciton has been enabled */ - if(canfd_en) { - if(transmit_message->tx_dlen <= 8U) { - /* set the data length */ - reg_temp |= transmit_message->tx_dlen; - } else { - /* data length greater than 8 */ - for(i = 0U; i < 7U; i++) { - if(transmit_message->tx_dlen == g_can_fdlength_table[i]) { - hit = 1U; - break; - } - } - /* data length is valid */ - if(1U == hit) { - reg_temp |= 9U + i; - } else { - CAN_ERROR_HANDLE("dlen is invalid \r\n"); - } - } - reg_temp |= (((uint32_t)transmit_message->fd_brs << 5U) | ((uint32_t)transmit_message->fd_esi << 4U) | ((uint32_t)transmit_message->fd_flag << 7U)); - CAN_TMP(can_periph, mailbox_number) = reg_temp; - - /* set the data */ - i = transmit_message->tx_dlen / 4U; - - /* data length is 5-7 need send 2 word */ - if((1U == i) && (4U != transmit_message->tx_dlen)) { - i++; - } - p_temp = (uint32_t)transmit_message->tx_data; - if((0U == i)) { - CAN_TMDATA0(can_periph, mailbox_number) = *(uint32_t *)p_temp; - } else { - for(; i > 0U; i--) { - CAN_TMDATA0(can_periph, mailbox_number) = *(uint32_t *)p_temp; - p_temp = ((uint32_t)((uint32_t)p_temp + 4U)); - } - } - - } else { - CAN_ERROR_HANDLE("CAN FD function disabled \r\n"); - } - } -#else - /* set the data length */ - CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_DLENC; - CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen; - /* set the data */ - CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \ - TMDATA0_DB2(transmit_message->tx_data[2]) | \ - TMDATA0_DB1(transmit_message->tx_data[1]) | \ - TMDATA0_DB0(transmit_message->tx_data[0]); - CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \ - TMDATA1_DB6(transmit_message->tx_data[6]) | \ - TMDATA1_DB5(transmit_message->tx_data[5]) | \ - TMDATA1_DB4(transmit_message->tx_data[4]); -#endif /* GD32E508 */ - /* enable transmission */ - CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN; - - return mailbox_number; -} - -/*! - \brief get CAN transmit state - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] mailbox_number - only one parameter can be selected which is shown as below: - \arg CAN_MAILBOX(x=0,1,2) - \param[out] none - \retval can_transmit_state_enum -*/ -can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number) -{ - can_transmit_state_enum state = CAN_TRANSMIT_FAILED; - uint32_t val = 0U; - - /* check selected mailbox state */ - switch(mailbox_number) { - /* mailbox0 */ - case CAN_MAILBOX0: - val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0); - break; - /* mailbox1 */ - case CAN_MAILBOX1: - val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1); - break; - /* mailbox2 */ - case CAN_MAILBOX2: - val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2); - break; - default: - val = CAN_TRANSMIT_FAILED; - break; - } - - switch(val) { - /* transmit pending */ - case(CAN_STATE_PENDING): - state = CAN_TRANSMIT_PENDING; - break; - /* mailbox0 transmit succeeded */ - case(CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0): - state = CAN_TRANSMIT_OK; - break; - /* mailbox1 transmit succeeded */ - case(CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1): - state = CAN_TRANSMIT_OK; - break; - /* mailbox2 transmit succeeded */ - case(CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2): - state = CAN_TRANSMIT_OK; - break; - /* transmit failed */ - default: - state = CAN_TRANSMIT_FAILED; - break; - } - return state; -} - -/*! - \brief stop CAN transmission - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] mailbox_number - only one parameter can be selected which is shown as below: - \arg CAN_MAILBOXx(x=0,1,2) - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) -{ - ErrStatus reval = SUCCESS; - /* timeout for CAN_TSTAT_MSTx bits */ - uint32_t timeout = CAN_TIMEOUT; - uint32_t reg_value0 = 0U; - uint32_t reg_value1 = 0U; - - /* get the status of transmit FIFO order */ - reg_value0 = CAN_CTL(can_periph) & CAN_CTL_TFO; - - if(CAN_MAILBOX0 == mailbox_number) { - reg_value1 = CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS0 | CAN_ALL_MAILBOX_EMPTY); - if((CAN_CTL_TFO == reg_value0) && (CAN_TSTAT_TMLS0 == reg_value1)){ - reval = ERROR; - } else { - CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0; - while((CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)) && (0U != timeout)) { - timeout--; - } - if(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){ - reval = ERROR; - } - } - } else if(CAN_MAILBOX1 == mailbox_number) { - reg_value1 = CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS1 | CAN_ALL_MAILBOX_EMPTY); - if((CAN_CTL_TFO == reg_value0) && (CAN_TSTAT_TMLS1 == reg_value1)){ - reval = ERROR; - }else{ - CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1; - while((CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)) && (0U != timeout)) { - timeout--; - } - if(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){ - reval = ERROR; - } - } - - } else if(CAN_MAILBOX2 == mailbox_number) { - reg_value1 = CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS2 | CAN_ALL_MAILBOX_EMPTY); - if((CAN_CTL_TFO == reg_value0) && (CAN_TSTAT_TMLS2 == reg_value1)){ - reval = ERROR; - }else{ - CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2; - while((CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)) && (0U != timeout)) { - timeout--; - } - if(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){ - reval = ERROR; - } - } - } else { - /* illegal parameters */ - } - return reval; -} - -/*! - \brief CAN receive message - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] fifo_number - \arg CAN_FIFOx(x=0,1) - \param[out] receive_message: struct for CAN receive message - \arg rx_sfid: 0x00000000 - 0x000007FF - \arg rx_efid: 0x00000000 - 0x1FFFFFFF - \arg rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED - \arg rx_ft: CAN_FT_DATA, CAN_FT_REMOTE - \arg rx_dlen: 0 - 8 (FD mode: 0 - 8, or 12, 16, 20, 24, 32, 48, 64) - \arg rx_data[]: 0x00 - 0xFF - \arg rx_fi: 0 - 27 - \retval none -*/ -void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct *receive_message) -{ - volatile uint32_t p_temp; -#ifdef GD32E508 - uint32_t canfd_en = 0U; - uint32_t data_temp; - uint8_t canfd_recv_cnt = 0U; - uint8_t i; -#endif /* GD32E508 */ - - /* get the frame format */ - receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number)); - if(CAN_FF_STANDARD == receive_message->rx_ff) { - /* get standard identifier */ - receive_message->rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); - } else { - /* get extended identifier */ - receive_message->rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); - } - - /* get frame type */ - receive_message->rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); - /* filtering index */ - receive_message->rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); - -#ifdef GD32E508 - receive_message->fd_flag = (uint8_t)((CAN_RFIFOMP_FDF & CAN_RFIFOMP(can_periph, fifo_number)) >> 7); - - canfd_en = CAN_FDCTL(can_periph) & CAN_FDCTL_FDEN; - if(!canfd_en) { - if(CAN_FDF_CLASSIC == receive_message->fd_flag) { - /* get recevie data length */ - receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); - /* receive data */ - receive_message->rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message->rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message->rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message->rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message->rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message->rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message->rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message->rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); - } else { - CAN_ERROR_HANDLE("CAN FD function disabled \r\n"); - } - } else { - /* check FD funciton has been enabled */ - /* get recevie data length */ - canfd_recv_cnt = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); - - if(canfd_recv_cnt <= 8U) { - /* set the data length */ - receive_message->rx_dlen = canfd_recv_cnt; - } else { - receive_message->rx_dlen = g_can_fdlength_table[canfd_recv_cnt - 9U]; - } - - receive_message->fd_brs = (uint8_t)((CAN_RFIFOMP(can_periph, fifo_number) & CAN_RFIFOMP_BRS) >> 5); - receive_message->fd_esi = (uint8_t)((CAN_RFIFOMP(can_periph, fifo_number) & CAN_RFIFOMP_ESI) >> 4); - - /* get the data */ - i = receive_message->rx_dlen / 4U; - - /* data length is 5-7 need receive 2 word */ - if((1U == i) && (4U != receive_message->rx_dlen)) { - i++; - } - p_temp = (uint32_t)(uint32_t)receive_message->rx_data; - if(0U == i) { - data_temp = CAN_RFIFOMDATA0(can_periph, fifo_number); - *(uint32_t *)p_temp = data_temp; - } else { - /* get the data by reading from CAN_RFIFOMDATA0 register*/ - for(; i > 0U; i--) { - data_temp = CAN_RFIFOMDATA0(can_periph, fifo_number); - *(uint32_t *)p_temp = data_temp; - p_temp = ((uint32_t)((uint32_t)p_temp + 4U)); - } - } - } -#else - /* get recevie data length */ - receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); - - /* receive data */ - receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message -> rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message -> rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); - -#endif /* GD32E508 */ - /* release FIFO */ - if(CAN_FIFO0 == fifo_number) { - CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; - } else { - CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; - } -} - -/*! - \brief release FIFO0 - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] fifo_number - only one parameter can be selected which is shown as below: - \arg CAN_FIFOx(x=0,1) - \param[out] none - \retval none -*/ -void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) -{ - if(CAN_FIFO0 == fifo_number) { - CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; - } else if(CAN_FIFO1 == fifo_number) { - CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; - } else { - /* illegal parameters */ - CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n"); - } -} - -/*! - \brief CAN receive message length - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] fifo_number - only one parameter can be selected which is shown as below: - \arg CAN_FIFOx(x=0,1) - \param[out] none - \retval message length -*/ -uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number) -{ - uint8_t val = 0U; - - if(CAN_FIFO0 == fifo_number) { - /* FIFO0 */ - val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK); - } else if(CAN_FIFO1 == fifo_number) { - /* FIFO1 */ - val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK); - } else { - /* illegal parameters */ - } - return val; -} - -/*! - \brief set CAN working mode - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] can_working_mode - only one parameter can be selected which is shown as below: - \arg CAN_MODE_INITIALIZE - \arg CAN_MODE_NORMAL - \arg CAN_MODE_SLEEP - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) -{ - ErrStatus flag = ERROR; - /* timeout for IWS or also for SLPWS bits */ - uint32_t timeout = CAN_TIMEOUT; - - if(CAN_MODE_INITIALIZE == working_mode) { - /* disable sleep mode */ - CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); - /* set initialize mode */ - CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; - /* wait the acknowledge */ - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) { - flag = ERROR; - } else { - flag = SUCCESS; - } - } else if(CAN_MODE_NORMAL == working_mode) { - /* enter normal mode */ - CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); - /* wait the acknowledge */ - while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)) { - timeout--; - } - if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) { - flag = ERROR; - } else { - flag = SUCCESS; - } - } else if(CAN_MODE_SLEEP == working_mode) { - /* disable initialize mode */ - CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_IWMOD); - /* set sleep mode */ - CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD; - /* wait the acknowledge */ - while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)) { - timeout--; - } - if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) { - flag = ERROR; - } else { - flag = SUCCESS; - } - } else { - flag = ERROR; - } - return flag; -} - -/*! - \brief wake up CAN - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus can_wakeup(uint32_t can_periph) -{ - ErrStatus flag = ERROR; - uint32_t timeout = CAN_TIMEOUT; - - /* wakeup */ - CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; - - while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)) { - timeout--; - } - /* check state */ - if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) { - flag = ERROR; - } else { - flag = SUCCESS; - } - return flag; -} - -/*! - \brief get CAN error type - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval can_error_enum - \arg CAN_ERROR_NONE: no error - \arg CAN_ERROR_FILL: fill error - \arg CAN_ERROR_FORMATE: format error - \arg CAN_ERROR_ACK: ACK error - \arg CAN_ERROR_BITRECESSIVE: bit recessive - \arg CAN_ERROR_BITDOMINANTER: bit dominant error - \arg CAN_ERROR_CRC: CRC error - \arg CAN_ERROR_SOFTWARECFG: software configure -*/ -can_error_enum can_error_get(uint32_t can_periph) -{ - can_error_enum error; - error = CAN_ERROR_NONE; - - /* get error type */ - error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph))); - return error; -} - -/*! - \brief get CAN receive error number - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL - \param[out] none - \retval error number -*/ -uint8_t can_receive_error_number_get(uint32_t can_periph) -{ - uint8_t val; - - /* get error count */ - val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph))); - return val; -} - -/*! - \brief get CAN transmit error number - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval error number -*/ -uint8_t can_transmit_error_number_get(uint32_t can_periph) -{ - uint8_t val; - - val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph))); - return val; -} - -/*! - \brief enable CAN interrupt - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] interrupt - one or more parameters can be selected which are shown as below: - \arg CAN_INT_TME: transmit mailbox empty interrupt enable - \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable - \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable - \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable - \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable - \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable - \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable - \arg CAN_INT_WERR: warning error interrupt enable - \arg CAN_INT_PERR: passive error interrupt enable - \arg CAN_INT_BO: bus-off interrupt enable - \arg CAN_INT_ERRN: error number interrupt enable - \arg CAN_INT_ERR: error interrupt enable - \arg CAN_INT_WU: wakeup interrupt enable - \arg CAN_INT_SLPW: sleep working interrupt enable - \param[out] none - \retval none -*/ -void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt) -{ - CAN_INTEN(can_periph) |= interrupt; -} - -/*! - \brief disable CAN interrupt - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] interrupt - one or more parameters can be selected which are shown as below: - \arg CAN_INT_TME: transmit mailbox empty interrupt enable - \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable - \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable - \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable - \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable - \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable - \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable - \arg CAN_INT_WERR: warning error interrupt enable - \arg CAN_INT_PERR: passive error interrupt enable - \arg CAN_INT_BO: bus-off interrupt enable - \arg CAN_INT_ERRN: error number interrupt enable - \arg CAN_INT_ERR: error interrupt enable - \arg CAN_INT_WU: wakeup interrupt enable - \arg CAN_INT_SLPW: sleep working interrupt enable - \param[out] none - \retval none -*/ -void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) -{ - CAN_INTEN(can_periph) &= ~interrupt; -} - -/*! - \brief get CAN flag state - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] flag: CAN flags, refer to can_flag_enum - only one parameter can be selected which is shown as below: - \arg CAN_FLAG_RXL: RX level - \arg CAN_FLAG_LASTRX: last sample value of RX pin - \arg CAN_FLAG_RS: receiving state - \arg CAN_FLAG_TS: transmitting state - \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode - \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode - \arg CAN_FLAG_ERRIF: error flag - \arg CAN_FLAG_SLPWS: sleep working state - \arg CAN_FLAG_IWS: initial working state - \arg CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO - \arg CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO - \arg CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO - \arg CAN_FLAG_TME2: transmit mailbox 2 empty - \arg CAN_FLAG_TME1: transmit mailbox 1 empty - \arg CAN_FLAG_TME0: transmit mailbox 0 empty - \arg CAN_FLAG_MTE2: mailbox 2 transmit error - \arg CAN_FLAG_MTE1: mailbox 1 transmit error - \arg CAN_FLAG_MTE0: mailbox 0 transmit error - \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost - \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost - \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost - \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error - \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error - \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error - \arg CAN_FLAG_MTF2: mailbox 2 transmit finished - \arg CAN_FLAG_MTF1: mailbox 1 transmit finished - \arg CAN_FLAG_MTF0: mailbox 0 transmit finished - \arg CAN_FLAG_RFO0: receive FIFO0 overfull - \arg CAN_FLAG_RFF0: receive FIFO0 full - \arg CAN_FLAG_RFO1: receive FIFO1 overfull - \arg CAN_FLAG_RFF1: receive FIFO1 full - \arg CAN_FLAG_BOERR: bus-off error - \arg CAN_FLAG_PERR: passive error - \arg CAN_FLAG_WERR: warning error - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) -{ - /* get flag and interrupt enable state */ - if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))) { - return SET; - } else { - return RESET; - } -} - -/*! - \brief clear CAN flag state - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] flag: CAN flags, refer to can_flag_enum - only one parameter can be selected which is shown as below: - \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode - \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode - \arg CAN_FLAG_ERRIF: error flag - \arg CAN_FLAG_MTE2: mailbox 2 transmit error - \arg CAN_FLAG_MTE1: mailbox 1 transmit error - \arg CAN_FLAG_MTE0: mailbox 0 transmit error - \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost - \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost - \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost - \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error - \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error - \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error - \arg CAN_FLAG_MTF2: mailbox 2 transmit finished - \arg CAN_FLAG_MTF1: mailbox 1 transmit finished - \arg CAN_FLAG_MTF0: mailbox 0 transmit finished - \arg CAN_FLAG_RFO0: receive FIFO0 overfull - \arg CAN_FLAG_RFF0: receive FIFO0 full - \arg CAN_FLAG_RFO1: receive FIFO1 overfull - \arg CAN_FLAG_RFF1: receive FIFO1 full - \param[out] none - \retval none -*/ -void can_flag_clear(uint32_t can_periph, can_flag_enum flag) -{ - CAN_REG_VAL(can_periph, flag) |= BIT(CAN_BIT_POS(flag)); -} - -/*! - \brief get CAN interrupt flag state - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] int_flag: CAN interrupt flags, refer to can_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering - \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode - \arg CAN_INT_FLAG_ERRIF: error interrupt flag - \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag - \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag - \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag - \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag - \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag - \arg CAN_INT_FLAG_RFL0: receive FIFO0 not empty interrupt flag - \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag - \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag - \arg CAN_INT_FLAG_RFL1: receive FIFO1 not empty interrupt flag - \arg CAN_INT_FLAG_ERRN: error number interrupt flag - \arg CAN_INT_FLAG_BOERR: bus-off error interrupt flag - \arg CAN_INT_FLAG_PERR: passive error interrupt flag - \arg CAN_INT_FLAG_WERR: warning error interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum int_flag) -{ - uint32_t ret1 = RESET; - uint32_t ret2 = RESET; - - /* get the staus of interrupt flag */ - if(int_flag == CAN_INT_FLAG_RFL0) { - ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0); - } else if(int_flag == CAN_INT_FLAG_RFL1) { - ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1); - } else if(int_flag == CAN_INT_FLAG_ERRN) { - ret1 = can_error_get(can_periph); - } else { - ret1 = CAN_REG_VALS(can_periph, int_flag) & BIT(CAN_BIT_POS0(int_flag)); - } - /* get the staus of interrupt enale bit */ - ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(int_flag)); - if(ret1 && ret2) { - return SET; - } else { - return RESET; - } -} - -/*! - \brief clear CAN interrupt flag state - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] int_flag: CAN interrupt flags, refer to can_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering - \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode - \arg CAN_INT_FLAG_ERRIF: error interrupt flag - \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag - \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag - \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag - \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag - \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag - \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag - \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag - \param[out] none - \retval none -*/ -void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum int_flag) -{ - CAN_REG_VALS(can_periph, int_flag) |= BIT(CAN_BIT_POS0(int_flag)); -} -#endif /* GD32EPRT */ diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_can.c.base@1.0.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_can.c.base@1.0.0 deleted file mode 100644 index ba6eb61..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_can.c.base@1.0.0 +++ /dev/null @@ -1,1615 +0,0 @@ -/*! - \file gd32e50x_can.c - \brief CAN 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. -*/ -#ifndef GD32EPRT -#include "gd32e50x_can.h" -#include - -#define CAN_ERROR_HANDLE(s) do{}while(1) - -/* This table can be used to calculate data length in FD mode */ -const uint8_t g_can_fdlength_table[] = {12, 16, 20, 24, 32, 48, 64}; - -/*! - \brief deinitialize CAN - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_deinit(uint32_t can_periph) -{ -#if defined(GD32E50X_CL) || defined(GD32E508) - switch(can_periph) { - case CAN0: - rcu_periph_reset_enable(RCU_CAN0RST); - rcu_periph_reset_disable(RCU_CAN0RST); - break; - case CAN1: - rcu_periph_reset_enable(RCU_CAN1RST); - rcu_periph_reset_disable(RCU_CAN1RST); - break; - case CAN2: - rcu_periph_reset_enable(RCU_CAN2RST); - rcu_periph_reset_disable(RCU_CAN2RST); - break; - default: - break; - } -#else - switch(can_periph) { - case CAN0: - rcu_periph_reset_enable(RCU_CAN0RST); - rcu_periph_reset_disable(RCU_CAN0RST); - break; - case CAN1: - rcu_periph_reset_enable(RCU_CAN1RST); - rcu_periph_reset_disable(RCU_CAN1RST); - break; - default: - break; - } -#endif -} - -/*! - \brief initialize CAN parameter struct - \param[in] type: the type of CAN parameter struct - only one parameter can be selected which is shown as below: - \arg CAN_INIT_STRUCT: the CAN initial struct - \arg CAN_FILTER_STRUCT: the CAN filter struct - \arg CAN_FD_FRAME_STRUCT: the CAN FD initial struct - \arg CAN_TX_MESSAGE_STRUCT: the CAN TX message struct - \arg CAN_RX_MESSAGE_STRUCT: the CAN RX message struct - \param[in] p_struct: the pointer of the specific struct - \param[out] none - \retval none -*/ -void can_struct_para_init(can_struct_type_enum type, void *p_struct) -{ - uint8_t i; - - if(NULL == p_struct) { - CAN_ERROR_HANDLE("struct parameter can not be NULL \r\n"); - } - /* get type of the struct */ - switch(type) { - /* used for can_init() */ - case CAN_INIT_STRUCT: - ((can_parameter_struct *)p_struct)->auto_bus_off_recovery = DISABLE; - ((can_parameter_struct *)p_struct)->auto_retrans = DISABLE; - ((can_parameter_struct *)p_struct)->auto_wake_up = DISABLE; - ((can_parameter_struct *)p_struct)->prescaler = 0x0400U; - ((can_parameter_struct *)p_struct)->rec_fifo_overwrite = DISABLE; - ((can_parameter_struct *)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ; - ((can_parameter_struct *)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ; - ((can_parameter_struct *)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ; - ((can_parameter_struct *)p_struct)->time_triggered = DISABLE; - ((can_parameter_struct *)p_struct)->trans_fifo_order = DISABLE; - ((can_parameter_struct *)p_struct)->working_mode = CAN_NORMAL_MODE; - break; - /* used for can_filter_init() */ - case CAN_FILTER_STRUCT: - ((can_filter_parameter_struct *)p_struct)->filter_bits = CAN_FILTERBITS_32BIT; - ((can_filter_parameter_struct *)p_struct)->filter_enable = DISABLE; - ((can_filter_parameter_struct *)p_struct)->filter_fifo_number = CAN_FIFO0; - ((can_filter_parameter_struct *)p_struct)->filter_list_high = 0x0000U; - ((can_filter_parameter_struct *)p_struct)->filter_list_low = 0x0000U; - ((can_filter_parameter_struct *)p_struct)->filter_mask_high = 0x0000U; - ((can_filter_parameter_struct *)p_struct)->filter_mask_low = 0x0000U; - ((can_filter_parameter_struct *)p_struct)->filter_mode = CAN_FILTERMODE_MASK; - ((can_filter_parameter_struct *)p_struct)->filter_number = 0U; - break; -#ifdef GD32E508 - /* used for can_fd_init() */ - case CAN_FD_FRAME_STRUCT: - ((can_fdframe_struct *)p_struct)->data_prescaler = 0x0400U; - ((can_fdframe_struct *)p_struct)->data_resync_jump_width = 1U - 1U; - ((can_fdframe_struct *)p_struct)->data_time_segment_1 = 3U - 1U; - ((can_fdframe_struct *)p_struct)->data_time_segment_2 = 2U - 1U; - ((can_fdframe_struct *)p_struct)->delay_compensation = DISABLE; - ((can_fdframe_struct *)p_struct)->esi_mode = CAN_ESIMOD_HARDWARE; - ((can_fdframe_struct *)p_struct)->excp_event_detect = ENABLE; - ((can_fdframe_struct *)p_struct)->fd_frame = DISABLE; - ((can_fdframe_struct *)p_struct)->iso_bosch = CAN_FDMOD_ISO; - ((can_fdframe_struct *)p_struct)->p_delay_compensation = 0U; - break; - /* used for can_message_transmit() */ - case CAN_TX_MESSAGE_STRUCT: - ((can_trasnmit_message_struct *)p_struct)->fd_brs = CAN_BRS_DISABLE; - ((can_trasnmit_message_struct *)p_struct)->fd_esi = CAN_ESI_DOMINANT; - ((can_trasnmit_message_struct *)p_struct)->fd_flag = CAN_FDF_CLASSIC; - - for(i = 0U; i < 64U; i++) { - ((can_trasnmit_message_struct *)p_struct)->tx_data[i] = 0U; - } - - ((can_trasnmit_message_struct *)p_struct)->tx_dlen = 0u; - ((can_trasnmit_message_struct *)p_struct)->tx_efid = 0U; - ((can_trasnmit_message_struct *)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; - ((can_trasnmit_message_struct *)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; - ((can_trasnmit_message_struct *)p_struct)->tx_sfid = 0U; - break; - /* used for can_message_receive() */ - case CAN_RX_MESSAGE_STRUCT: - ((can_receive_message_struct *)p_struct)->fd_brs = CAN_BRS_DISABLE; - ((can_receive_message_struct *)p_struct)->fd_esi = CAN_ESI_DOMINANT; - ((can_receive_message_struct *)p_struct)->fd_flag = CAN_FDF_CLASSIC; - - for(i = 0U; i < 64U; i++) { - ((can_receive_message_struct *)p_struct)->rx_data[i] = 0U; - } - - ((can_receive_message_struct *)p_struct)->rx_dlen = 0U; - ((can_receive_message_struct *)p_struct)->rx_efid = 0U; - ((can_receive_message_struct *)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; - ((can_receive_message_struct *)p_struct)->rx_fi = 0U; - ((can_receive_message_struct *)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; - ((can_receive_message_struct *)p_struct)->rx_sfid = 0U; - break; -#else - /* used for can_message_transmit() */ - case CAN_TX_MESSAGE_STRUCT: - for(i = 0U; i < 8U; i++) { - ((can_trasnmit_message_struct *)p_struct)->tx_data[i] = 0U; - } - - ((can_trasnmit_message_struct *)p_struct)->tx_dlen = 0u; - ((can_trasnmit_message_struct *)p_struct)->tx_efid = 0U; - ((can_trasnmit_message_struct *)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; - ((can_trasnmit_message_struct *)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; - ((can_trasnmit_message_struct *)p_struct)->tx_sfid = 0U; - break; - /* used for can_message_receive() */ - case CAN_RX_MESSAGE_STRUCT: - for(i = 0U; i < 8U; i++) { - ((can_receive_message_struct *)p_struct)->rx_data[i] = 0U; - } - - ((can_receive_message_struct *)p_struct)->rx_dlen = 0U; - ((can_receive_message_struct *)p_struct)->rx_efid = 0U; - ((can_receive_message_struct *)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; - ((can_receive_message_struct *)p_struct)->rx_fi = 0U; - ((can_receive_message_struct *)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; - ((can_receive_message_struct *)p_struct)->rx_sfid = 0U; - break; - -#endif /* GD32E508 */ - default: - CAN_ERROR_HANDLE("parameter is invalid \r\n"); - break; - } -} - -/*! - \brief initialize CAN - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] can_parameter_init: parameters for CAN initializtion - \arg working_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE - \arg resync_jump_width: 0x00 - 0x07 - \arg time_segment_1: 0x00 - 0x7F - \arg time_segment_2: 0x00 - 0x1F - \arg time_triggered: ENABLE or DISABLE - \arg auto_bus_off_recovery: ENABLE or DISABLE - \arg auto_wake_up: ENABLE or DISABLE - \arg auto_retrans: ENABLE or DISABLE - \arg rec_fifo_overwrite: ENABLE or DISABLE - \arg trans_fifo_order: ENABLE or DISABLE - \arg prescaler: 0x0001 - 0x0400 - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus can_init(uint32_t can_periph, can_parameter_struct *can_parameter_init) -{ - uint32_t timeout = CAN_TIMEOUT; - ErrStatus flag = ERROR; -#ifdef GD32E508 - uint32_t fdctl_status; -#endif /* GD32E508 */ - - /* disable sleep mode */ - CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; - /* enable initialize mode */ - CAN_CTL(can_periph) |= CAN_CTL_IWMOD; - /* wait ACK */ - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - /* check initialize working success */ - if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) { - flag = ERROR; - } else { -#ifdef GD32E508 - /* set the bit timing register */ - fdctl_status = CAN_FDCTL(can_periph); - if(CAN_FDCTL_FDEN != (fdctl_status & CAN_FDCTL_FDEN)) { - /* CAN FD disable, should frist enable, then write */ - fdctl_status = fdctl_status | CAN_FDCTL_FDEN; - CAN_FDCTL(can_periph) = fdctl_status; - CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ - BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ - BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ - BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ - BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); - fdctl_status = fdctl_status & (~CAN_FDCTL_FDEN); - CAN_FDCTL(can_periph) = fdctl_status; - } else { - /* CAN FD enable */ - CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ - BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ - BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ - BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ - BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); - } -#else - /* set the bit timing register */ - CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ - BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ - BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ - BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ - BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); - -#endif /* GD32E508 */ - /* time trigger communication mode */ - if(ENABLE == can_parameter_init->time_triggered) { - CAN_CTL(can_periph) |= CAN_CTL_TTC; - } else { - CAN_CTL(can_periph) &= ~CAN_CTL_TTC; - } - /* automatic bus-off managment */ - if(ENABLE == can_parameter_init->auto_bus_off_recovery) { - CAN_CTL(can_periph) |= CAN_CTL_ABOR; - } else { - CAN_CTL(can_periph) &= ~CAN_CTL_ABOR; - } - /* automatic wakeup mode */ - if(ENABLE == can_parameter_init->auto_wake_up) { - CAN_CTL(can_periph) |= CAN_CTL_AWU; - } else { - CAN_CTL(can_periph) &= ~CAN_CTL_AWU; - } - /* automatic retransmission mode */ - if(ENABLE == can_parameter_init->auto_retrans) { - CAN_CTL(can_periph) &= ~CAN_CTL_ARD; - } else { - CAN_CTL(can_periph) |= CAN_CTL_ARD; - } - /* receive fifo overwrite mode */ - if(ENABLE == can_parameter_init->rec_fifo_overwrite) { - CAN_CTL(can_periph) &= ~CAN_CTL_RFOD; - } else { - CAN_CTL(can_periph) |= CAN_CTL_RFOD; - } - /* transmit fifo order */ - if(ENABLE == can_parameter_init->trans_fifo_order) { - CAN_CTL(can_periph) |= CAN_CTL_TFO; - } else { - CAN_CTL(can_periph) &= ~CAN_CTL_TFO; - } - /* disable initialize mode */ - CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; - timeout = CAN_TIMEOUT; - /* wait the ACK */ - while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - /* check exit initialize mode */ - if(0U != timeout) { - flag = SUCCESS; - } - } - return flag; -} - -/*! - \brief initialize CAN filter - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] can_filter_parameter_init: struct for CAN filter initialization - \arg filter_list_high: 0x0000 - 0xFFFF - \arg filter_list_low: 0x0000 - 0xFFFF - \arg filter_mask_high: 0x0000 - 0xFFFF - \arg filter_mask_low: 0x0000 - 0xFFFF - \arg filter_fifo_number: CAN_FIFO0, CAN_FIFO1 - \arg filter_number: In CAN0(0 - 27), In CAN2(0 - 14) - \arg filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST - \arg filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT - \arg filter_enable: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void can_filter_init(uint32_t can_periph, can_filter_parameter_struct *can_filter_parameter_init) -{ - uint32_t val = 0U; - - val = ((uint32_t)1) << (can_filter_parameter_init->filter_number); - if(CAN1 == can_periph) { - can_periph = CAN0; - } - /* filter lock disable */ - CAN_FCTL(can_periph) |= CAN_FCTL_FLD; - /* disable filter */ - CAN_FW(can_periph) &= ~(uint32_t)val; - - /* filter 16 bits */ - if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits) { - /* set filter 16 bits */ - CAN_FSCFG(can_periph) &= ~(uint32_t)val; - /* first 16 bits list and first 16 bits mask or first 16 bits list and second 16 bits list */ - CAN_FDATA0(can_periph, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \ - FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); - /* second 16 bits list and second 16 bits mask or third 16 bits list and fourth 16 bits list */ - CAN_FDATA1(can_periph, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \ - FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS); - } - /* filter 32 bits */ - if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits) { - /* set filter 32 bits */ - CAN_FSCFG(can_periph) |= (uint32_t)val; - /* 32 bits list or first 32 bits list */ - CAN_FDATA0(can_periph, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) | - FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); - /* 32 bits mask or second 32 bits list */ - CAN_FDATA1(can_periph, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | - FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS); - } - - /* filter mode */ - if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode) { - /* mask mode */ - CAN_FMCFG(can_periph) &= ~(uint32_t)val; - } else { - /* list mode */ - CAN_FMCFG(can_periph) |= (uint32_t)val; - } - - /* filter FIFO */ - if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)) { - /* FIFO0 */ - CAN_FAFIFO(can_periph) &= ~(uint32_t)val; - } else { - /* FIFO1 */ - CAN_FAFIFO(can_periph) |= (uint32_t)val; - } - - /* filter working */ - if(ENABLE == can_filter_parameter_init->filter_enable) { - - CAN_FW(can_periph) |= (uint32_t)val; - } - - /* filter lock enable */ - CAN_FCTL(can_periph) &= ~CAN_FCTL_FLD; -} - -/*! - \brief CAN filter mask mode initialization - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] id: extended(11-bits) or standard(29-bits) identifier - \arg 0x00000000 - 0x1FFFFFFF - \param[in] mask: extended(11-bits) or standard(29-bits) identifier mask - \arg 0x00000000 - 0x1FFFFFFF - \param[in] format_fifo: format and fifo states - only one parameter can be selected which is shown as below: - \arg CAN_STANDARD_FIFO0 - \arg CAN_STANDARD_FIFO1 - \arg CAN_EXTENDED_FIFO0 - \arg CAN_EXTENDED_FIFO1 - \param[in] filter_number: filter sequence number - \arg In CAN0:0 - 27 ,In CAN2:0 - 14 - \param[out] none - \retval none -*/ -void can_filter_mask_mode_init(uint32_t can_periph, uint32_t id, uint32_t mask, can_format_fifo_enum format_fifo, uint16_t filter_number) -{ - can_filter_parameter_struct can_filter; - - /* Initialize the filter structure */ - can_struct_para_init(CAN_FILTER_STRUCT, &can_filter); - if(CAN1 == can_periph) { - can_periph = CAN0; - } - /* filter config */ - can_filter.filter_number = filter_number; - can_filter.filter_mode = CAN_FILTERMODE_MASK; - can_filter.filter_bits = CAN_FILTERBITS_32BIT; - can_filter.filter_enable = ENABLE; - - switch(format_fifo) { - /* standard FIFO 0 */ - case CAN_STANDARD_FIFO0: - can_filter.filter_fifo_number = CAN_FIFO0; - /* configure SFID[10:0] */ - can_filter.filter_list_high = (uint16_t)id << 5; - can_filter.filter_list_low = 0x0000U; - /* configure SFID[10:0] mask */ - can_filter.filter_mask_high = (uint16_t)mask << 5; - /* both data and remote frames can be received */ - can_filter.filter_mask_low = (uint16_t)(1U << 2U); - - break; - /* standard FIFO 1 */ - case CAN_STANDARD_FIFO1: - can_filter.filter_fifo_number = CAN_FIFO1; - /* configure SFID[10:0] */ - can_filter.filter_list_high = (uint16_t)id << 5; - can_filter.filter_list_low = 0x0000U; - /* configure SFID[10:0] mask */ - can_filter.filter_mask_high = (uint16_t)mask << 5; - /* both data and remote frames can be received */ - can_filter.filter_mask_low = (uint16_t)(1U << 2U); - - break; - /* extended FIFO 0 */ - case CAN_EXTENDED_FIFO0: - can_filter.filter_fifo_number = CAN_FIFO0; - /* configure EFID[28:13] */ - can_filter.filter_list_high = (uint16_t)(id >> 13); - /* configure EFID[12:0] and frame format bit set */ - can_filter.filter_list_low = ((uint16_t)(id << 3)) | (1U << 2); - /* configure EFID[28:13] mask */ - can_filter.filter_mask_high = (uint16_t)(mask >> 13); - /* configure EFID[12:0] and frame format bit mask */ - /* both data and remote frames can be received */ - can_filter.filter_mask_low = ((uint16_t)(mask << 3)) | (1U << 2); - - break; - /* extended FIFO 1 */ - case CAN_EXTENDED_FIFO1: - can_filter.filter_fifo_number = CAN_FIFO1; - /* configure EFID[28:13] */ - can_filter.filter_list_high = (uint16_t)(id >> 13); - /* configure EFID[12:0] and frame format bit set */ - can_filter.filter_list_low = ((uint16_t)(id << 3)) | (1U << 2); - /* configure EFID[28:13] mask */ - can_filter.filter_mask_high = (uint16_t)(mask >> 13); - /* configure EFID[12:0] and frame format bit mask */ - /* both data and remote frames can be received */ - can_filter.filter_mask_low = ((uint16_t)(mask << 3)) | (1U << 2); - - break; - default: - CAN_ERROR_HANDLE("parameter is invalid \r\n"); - } - - can_filter_init(can_periph, &can_filter); -} - -/*! - \brief CAN communication mode configure - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] mode: communication mode - only one parameter can be selected which is shown as below: - \arg CAN_NORMAL_MODE - \arg CAN_LOOPBACK_MODE - \arg CAN_SILENT_MODE - \arg CAN_SILENT_LOOPBACK_MODE - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus can_monitor_mode_set(uint32_t can_periph, uint8_t mode) -{ - ErrStatus reval = SUCCESS; - uint32_t timeout = CAN_TIMEOUT; - - if(mode == (mode & CAN_SILENT_LOOPBACK_MODE)) { - /* disable sleep mode */ - CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); - /* set initialize mode */ - CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; - /* wait the acknowledge */ - timeout = CAN_TIMEOUT; - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - - if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) { - reval = ERROR; - } else { - CAN_BT(can_periph) &= ~BT_MODE(3); - CAN_BT(can_periph) |= BT_MODE(mode); - - timeout = CAN_TIMEOUT; - /* enter normal mode */ - CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); - /* wait the acknowledge */ - while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)) { - timeout--; - } - if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) { - reval = ERROR; - } - } - } else { - reval = ERROR; - } - - return reval; -} - -#ifdef GD32E508 -/*! - \brief initialize CAN FD function - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] can_fdframe_init: parameters for CAN FD initializtion - \arg fd_frame: ENABLE or DISABLE - \arg excp_event_detect: ENABLE or DISABLE - \arg delay_compensation: ENABLE or DISABLE - \arg p_delay_compensation: the pointer of tdc struct - can_fd_tdc_struct: - tdc_mode: CAN_TDCMOD_CALC_AND_OFFSET or CAN_TDCMOD_OFFSET - tdc_filter: 0x00 - 0x07 - tdc_offset: 0x00 - 0x07 - \arg iso_bosch: CAN_FDMOD_ISO or CAN_FDMOD_BOSCH - \arg esi_mode: CAN_ESIMOD_HARDWARE or CAN_ESIMOD_SOFTWARE - \arg data_resync_jump_width: 0x00 - 0x07 - \arg data_time_segment_1: 0x00 - 0x0F - \arg data_time_segment_2: 0x00 - 0x07 - \arg data_prescaler: 0x0001 - 0x0400 - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus can_fd_init(uint32_t can_periph, can_fdframe_struct *can_fdframe_init) -{ - uint32_t timeout = CAN_TIMEOUT; - uint32_t tempreg = 0U; - - /* check null pointer */ - if(0 == can_fdframe_init) { - return ERROR; - } - /* disable sleep mode */ - CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; - /* enable initialize mode */ - CAN_CTL(can_periph) |= CAN_CTL_IWMOD; - /* wait ACK */ - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - /* check initialize working success */ - if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) { - return ERROR; - } else { - /* set the data bit timing register */ - CAN_DBT(can_periph) = (BT_DSJW((uint32_t)can_fdframe_init->data_resync_jump_width) | \ - BT_DBS1((uint32_t)can_fdframe_init->data_time_segment_1) | \ - BT_DBS2((uint32_t)can_fdframe_init->data_time_segment_2) | \ - BT_BAUDPSC(((uint32_t)can_fdframe_init->data_prescaler) - 1U)); - - tempreg = can_fdframe_init->esi_mode | can_fdframe_init->iso_bosch; - - /* Protocol exception event detection */ - if(ENABLE == can_fdframe_init->excp_event_detect) { - tempreg &= ~CAN_FDCTL_PRED; - } else { - tempreg |= CAN_FDCTL_PRED; - } - - /* Transmitter delay compensation mode */ - if(ENABLE == can_fdframe_init->delay_compensation) { - tempreg |= CAN_FDCTL_TDCEN; - /* p_delay_compensation pointer should be config when TDC mode is enabled */ - if(0 != can_fdframe_init->p_delay_compensation) { - tempreg |= (can_fdframe_init->p_delay_compensation->tdc_mode & CAN_FDCTL_TDCMOD); - CAN_FDTDC(can_periph) = (FDTDC_TDCF(can_fdframe_init->p_delay_compensation->tdc_filter) | FDTDC_TDCO( - can_fdframe_init->p_delay_compensation->tdc_offset)); - } else { - return ERROR; - } - } else { - /* Transmitter delay compensation mode is disabled */ - tempreg &= ~CAN_FDCTL_TDCEN; - } - - /* FD operation mode */ - if(ENABLE == can_fdframe_init->fd_frame) { - tempreg |= CAN_FDCTL_FDEN; - } else { - tempreg &= ~CAN_FDCTL_FDEN; - } - CAN_FDCTL(can_periph) = tempreg; - - /* disable initialize mode */ - CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; - timeout = CAN_TIMEOUT; - /* wait the ACK */ - while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - /* check exit initialize mode */ - if(0U == timeout) { - return ERROR; - } - } - - return SUCCESS; -} - -/*! - \brief CAN FD frame function enable - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_fd_function_enable(uint32_t can_periph) -{ - CAN_FDCTL(can_periph) |= CAN_FDCTL_FDEN; -} - -/*! - \brief CAN FD frame function disable - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL - \param[out] none - \retval none -*/ -void can_fd_function_disable(uint32_t can_periph) -{ - CAN_FDCTL(can_periph) &= ~CAN_FDCTL_FDEN; -} -#endif /* GD32E508 */ - -/*! - \brief set CAN1 fliter start bank number - \param[in] start_bank: CAN1 start bank number - only one parameter can be selected which is shown as below: - \arg (1..27) - \param[out] none - \retval none -*/ -void can1_filter_start_bank(uint8_t start_bank) -{ - /* filter lock disable */ - CAN_FCTL(CAN0) |= CAN_FCTL_FLD; - /* set CAN1 filter start number */ - CAN_FCTL(CAN0) &= ~(uint32_t)CAN_FCTL_HBC1F; - CAN_FCTL(CAN0) |= FCTL_HBC1F(start_bank); - /* filter lock enable */ - CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; -} - -/*! - \brief enable CAN debug freeze - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_debug_freeze_enable(uint32_t can_periph) -{ - /* set DFZ bit */ - CAN_CTL(can_periph) |= CAN_CTL_DFZ; -#ifdef GD32E50X_CL - switch(can_periph) { - case CAN0: - dbg_periph_enable(DBG_CAN0_HOLD); - break; - case CAN1: - dbg_periph_enable(DBG_CAN1_HOLD); - break; - case CAN2: - dbg_periph_enable(DBG_CAN2_HOLD); - break; - default: - break; - } -#else - switch(can_periph) { - case CAN0: - dbg_periph_enable(DBG_CAN0_HOLD); - break; - case CAN1: - dbg_periph_enable(DBG_CAN1_HOLD); - break; - default: - break; - } -#endif -} - -/*! - \brief disable CAN debug freeze - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_debug_freeze_disable(uint32_t can_periph) -{ - /* set DFZ bit */ - CAN_CTL(can_periph) &= ~CAN_CTL_DFZ; -#ifdef GD32E50X_CL - switch(can_periph) { - case CAN0: - dbg_periph_disable(DBG_CAN0_HOLD); - break; - case CAN1: - dbg_periph_disable(DBG_CAN1_HOLD); - break; - case CAN2: - dbg_periph_disable(DBG_CAN2_HOLD); - break; - default: - break; -#else - switch(can_periph) { - case CAN0: - dbg_periph_disable(DBG_CAN0_HOLD); - break; - case CAN1: - dbg_periph_disable(DBG_CAN1_HOLD); - break; - default: - break; -#endif - } -} - -/*! - \brief enable CAN time trigger mode - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_time_trigger_mode_enable(uint32_t can_periph) -{ - uint8_t mailbox_number; - - /* enable the tcc mode */ - CAN_CTL(can_periph) |= CAN_CTL_TTC; - /* enable time stamp */ - for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++) { - CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN; - } -} - -/*! - \brief disable CAN time trigger mode - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval none -*/ -void can_time_trigger_mode_disable(uint32_t can_periph) -{ - uint8_t mailbox_number; - - /* disable the TCC mode */ - CAN_CTL(can_periph) &= ~CAN_CTL_TTC; - /* reset TSEN bits */ - for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++) { - CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN; - } -} - -/*! - \brief transmit CAN message - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] transmit_message: struct for CAN transmit message - \arg tx_sfid: 0x00000000 - 0x000007FF - \arg tx_efid: 0x00000000 - 0x1FFFFFFF - \arg tx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED - \arg tx_ft: CAN_FT_DATA, CAN_FT_REMOTE - \arg tx_dlen: 0 - 8 (FD mode: 0 - 8, or 12, 16, 20, 24, 32, 48, 64) - \arg tx_data[]: 0x00 - 0xFF - \param[out] none - \retval mailbox_number -*/ -uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct *transmit_message) -{ - uint8_t mailbox_number = CAN_MAILBOX0; - volatile uint32_t p_temp; -#ifdef GD32E508 - uint8_t i = 0U; - uint8_t hit = 0U; - uint32_t canfd_en = 0U; - uint32_t reg_temp = 0U; -#endif /* GD32E508 */ - - /* select one empty mailbox */ - if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)) { - mailbox_number = CAN_MAILBOX0; - } else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)) { - mailbox_number = CAN_MAILBOX1; - } else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)) { - mailbox_number = CAN_MAILBOX2; - } else { - mailbox_number = CAN_NOMAILBOX; - } - /* return no mailbox empty */ - if(CAN_NOMAILBOX == mailbox_number) { - return CAN_NOMAILBOX; - } - - CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN; - if(CAN_FF_STANDARD == transmit_message->tx_ff) { - /* set transmit mailbox standard identifier */ - CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \ - transmit_message->tx_ft); - } else { - /* set transmit mailbox extended identifier */ - CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \ - transmit_message->tx_ff | \ - transmit_message->tx_ft); - } - -#ifdef GD32E508 - if(CAN_FDF_CLASSIC == transmit_message->fd_flag) { - /* set the data length */ - CAN_TMP(can_periph, mailbox_number) &= ~(CAN_TMP_DLENC | CAN_TMP_ESI | CAN_TMP_BRS | CAN_TMP_FDF); - /* Classic CAN frame data length does not exceed 8 */ - if (transmit_message->tx_dlen > 8U) { - transmit_message->tx_dlen = 8U; - } - CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen; - /* set the data */ - CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \ - TMDATA0_DB2(transmit_message->tx_data[2]) | \ - TMDATA0_DB1(transmit_message->tx_data[1]) | \ - TMDATA0_DB0(transmit_message->tx_data[0]); - CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \ - TMDATA1_DB6(transmit_message->tx_data[6]) | \ - TMDATA1_DB5(transmit_message->tx_data[5]) | \ - TMDATA1_DB4(transmit_message->tx_data[4]); - } else { - canfd_en = CAN_FDCTL(can_periph) & CAN_FDCTL_FDEN; - /* check FD funciton has been enabled */ - if(canfd_en) { - if(transmit_message->tx_dlen <= 8U) { - /* set the data length */ - reg_temp |= transmit_message->tx_dlen; - } else { - /* data length greater than 8 */ - for(i = 0U; i < 7U; i++) { - if(transmit_message->tx_dlen == g_can_fdlength_table[i]) { - hit = 1U; - break; - } - } - /* data length is valid */ - if(1U == hit) { - reg_temp |= 9U + i; - } else { - CAN_ERROR_HANDLE("dlen is invalid \r\n"); - } - } - reg_temp |= (((uint32_t)transmit_message->fd_brs << 5U) | ((uint32_t)transmit_message->fd_esi << 4U) | ((uint32_t)transmit_message->fd_flag << 7U)); - CAN_TMP(can_periph, mailbox_number) = reg_temp; - - /* set the data */ - i = transmit_message->tx_dlen / 4U; - - /* data length is 5-7 need send 2 word */ - if((1U == i) && (4U != transmit_message->tx_dlen)) { - i++; - } - p_temp = (uint32_t)transmit_message->tx_data; - if((0U == i)) { - CAN_TMDATA0(can_periph, mailbox_number) = *(uint32_t *)p_temp; - } else { - for(; i > 0U; i--) { - CAN_TMDATA0(can_periph, mailbox_number) = *(uint32_t *)p_temp; - p_temp = ((uint32_t)((uint32_t)p_temp + 4U)); - } - } - - } else { - CAN_ERROR_HANDLE("CAN FD function disabled \r\n"); - } - } -#else - /* set the data length */ - CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_DLENC; - CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen; - /* set the data */ - CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \ - TMDATA0_DB2(transmit_message->tx_data[2]) | \ - TMDATA0_DB1(transmit_message->tx_data[1]) | \ - TMDATA0_DB0(transmit_message->tx_data[0]); - CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \ - TMDATA1_DB6(transmit_message->tx_data[6]) | \ - TMDATA1_DB5(transmit_message->tx_data[5]) | \ - TMDATA1_DB4(transmit_message->tx_data[4]); -#endif /* GD32E508 */ - /* enable transmission */ - CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN; - - return mailbox_number; -} - -/*! - \brief get CAN transmit state - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] mailbox_number - only one parameter can be selected which is shown as below: - \arg CAN_MAILBOX(x=0,1,2) - \param[out] none - \retval can_transmit_state_enum -*/ -can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number) -{ - can_transmit_state_enum state = CAN_TRANSMIT_FAILED; - uint32_t val = 0U; - - /* check selected mailbox state */ - switch(mailbox_number) { - /* mailbox0 */ - case CAN_MAILBOX0: - val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0); - break; - /* mailbox1 */ - case CAN_MAILBOX1: - val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1); - break; - /* mailbox2 */ - case CAN_MAILBOX2: - val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2); - break; - default: - val = CAN_TRANSMIT_FAILED; - break; - } - - switch(val) { - /* transmit pending */ - case(CAN_STATE_PENDING): - state = CAN_TRANSMIT_PENDING; - break; - /* mailbox0 transmit succeeded */ - case(CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0): - state = CAN_TRANSMIT_OK; - break; - /* mailbox1 transmit succeeded */ - case(CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1): - state = CAN_TRANSMIT_OK; - break; - /* mailbox2 transmit succeeded */ - case(CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2): - state = CAN_TRANSMIT_OK; - break; - /* transmit failed */ - default: - state = CAN_TRANSMIT_FAILED; - break; - } - return state; -} - -/*! - \brief stop CAN transmission - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] mailbox_number - only one parameter can be selected which is shown as below: - \arg CAN_MAILBOXx(x=0,1,2) - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) -{ - ErrStatus reval = SUCCESS; - /* timeout for CAN_TSTAT_MSTx bits */ - uint32_t timeout = CAN_TIMEOUT; - uint32_t reg_value0 = 0U; - uint32_t reg_value1 = 0U; - - /* get the status of transmit FIFO order */ - reg_value0 = CAN_CTL(can_periph) & CAN_CTL_TFO; - - if(CAN_MAILBOX0 == mailbox_number) { - reg_value1 = CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS0 | CAN_ALL_MAILBOX_EMPTY); - if((CAN_CTL_TFO == reg_value0) && (CAN_TSTAT_TMLS0 == reg_value1)){ - reval = ERROR; - } else { - CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0; - while((CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)) && (0U != timeout)) { - timeout--; - } - if(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){ - reval = ERROR; - } - } - } else if(CAN_MAILBOX1 == mailbox_number) { - reg_value1 = CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS1 | CAN_ALL_MAILBOX_EMPTY); - if((CAN_CTL_TFO == reg_value0) && (CAN_TSTAT_TMLS1 == reg_value1)){ - reval = ERROR; - }else{ - CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1; - while((CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)) && (0U != timeout)) { - timeout--; - } - if(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){ - reval = ERROR; - } - } - - } else if(CAN_MAILBOX2 == mailbox_number) { - reg_value1 = CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS2 | CAN_ALL_MAILBOX_EMPTY); - if((CAN_CTL_TFO == reg_value0) && (CAN_TSTAT_TMLS2 == reg_value1)){ - reval = ERROR; - }else{ - CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2; - while((CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)) && (0U != timeout)) { - timeout--; - } - if(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){ - reval = ERROR; - } - } - } else { - /* illegal parameters */ - } - return reval; -} - -/*! - \brief CAN receive message - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] fifo_number - \arg CAN_FIFOx(x=0,1) - \param[out] receive_message: struct for CAN receive message - \arg rx_sfid: 0x00000000 - 0x000007FF - \arg rx_efid: 0x00000000 - 0x1FFFFFFF - \arg rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED - \arg rx_ft: CAN_FT_DATA, CAN_FT_REMOTE - \arg rx_dlen: 0 - 8 (FD mode: 0 - 8, or 12, 16, 20, 24, 32, 48, 64) - \arg rx_data[]: 0x00 - 0xFF - \arg rx_fi: 0 - 27 - \retval none -*/ -void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct *receive_message) -{ - volatile uint32_t p_temp; -#ifdef GD32E508 - uint32_t canfd_en = 0U; - uint32_t data_temp; - uint8_t canfd_recv_cnt = 0U; - uint8_t i; -#endif /* GD32E508 */ - - /* get the frame format */ - receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number)); - if(CAN_FF_STANDARD == receive_message->rx_ff) { - /* get standard identifier */ - receive_message->rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); - } else { - /* get extended identifier */ - receive_message->rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); - } - - /* get frame type */ - receive_message->rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); - /* filtering index */ - receive_message->rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); - -#ifdef GD32E508 - receive_message->fd_flag = (uint8_t)((CAN_RFIFOMP_FDF & CAN_RFIFOMP(can_periph, fifo_number)) >> 7); - - canfd_en = CAN_FDCTL(can_periph) & CAN_FDCTL_FDEN; - if(!canfd_en) { - if(CAN_FDF_CLASSIC == receive_message->fd_flag) { - /* get recevie data length */ - receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); - /* receive data */ - receive_message->rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message->rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message->rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message->rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message->rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message->rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message->rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message->rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); - } else { - CAN_ERROR_HANDLE("CAN FD function disabled \r\n"); - } - } else { - /* check FD funciton has been enabled */ - /* get recevie data length */ - canfd_recv_cnt = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); - - if(canfd_recv_cnt <= 8U) { - /* set the data length */ - receive_message->rx_dlen = canfd_recv_cnt; - } else { - receive_message->rx_dlen = g_can_fdlength_table[canfd_recv_cnt - 9U]; - } - - receive_message->fd_brs = (uint8_t)((CAN_RFIFOMP(can_periph, fifo_number) & CAN_RFIFOMP_BRS) >> 5); - receive_message->fd_esi = (uint8_t)((CAN_RFIFOMP(can_periph, fifo_number) & CAN_RFIFOMP_ESI) >> 4); - - /* get the data */ - i = receive_message->rx_dlen / 4U; - - /* data length is 5-7 need receive 2 word */ - if((1U == i) && (4U != receive_message->rx_dlen)) { - i++; - } - p_temp = (uint32_t)(uint32_t)receive_message->rx_data; - if(0U == i) { - data_temp = CAN_RFIFOMDATA0(can_periph, fifo_number); - *(uint32_t *)p_temp = data_temp; - } else { - /* get the data by reading from CAN_RFIFOMDATA0 register*/ - for(; i > 0U; i--) { - data_temp = CAN_RFIFOMDATA0(can_periph, fifo_number); - *(uint32_t *)p_temp = data_temp; - p_temp = ((uint32_t)((uint32_t)p_temp + 4U)); - } - } - } -#else - /* get recevie data length */ - receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); - - /* receive data */ - receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); - receive_message -> rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message -> rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message -> rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); - receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); - -#endif /* GD32E508 */ - /* release FIFO */ - if(CAN_FIFO0 == fifo_number) { - CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; - } else { - CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; - } -} - -/*! - \brief release FIFO0 - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] fifo_number - only one parameter can be selected which is shown as below: - \arg CAN_FIFOx(x=0,1) - \param[out] none - \retval none -*/ -void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) -{ - if(CAN_FIFO0 == fifo_number) { - CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; - } else if(CAN_FIFO1 == fifo_number) { - CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; - } else { - /* illegal parameters */ - CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n"); - } -} - -/*! - \brief CAN receive message length - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] fifo_number - only one parameter can be selected which is shown as below: - \arg CAN_FIFOx(x=0,1) - \param[out] none - \retval message length -*/ -uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number) -{ - uint8_t val = 0U; - - if(CAN_FIFO0 == fifo_number) { - /* FIFO0 */ - val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK); - } else if(CAN_FIFO1 == fifo_number) { - /* FIFO1 */ - val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK); - } else { - /* illegal parameters */ - } - return val; -} - -/*! - \brief set CAN working mode - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] can_working_mode - only one parameter can be selected which is shown as below: - \arg CAN_MODE_INITIALIZE - \arg CAN_MODE_NORMAL - \arg CAN_MODE_SLEEP - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) -{ - ErrStatus flag = ERROR; - /* timeout for IWS or also for SLPWS bits */ - uint32_t timeout = CAN_TIMEOUT; - - if(CAN_MODE_INITIALIZE == working_mode) { - /* disable sleep mode */ - CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); - /* set initialize mode */ - CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; - /* wait the acknowledge */ - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { - timeout--; - } - if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) { - flag = ERROR; - } else { - flag = SUCCESS; - } - } else if(CAN_MODE_NORMAL == working_mode) { - /* enter normal mode */ - CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); - /* wait the acknowledge */ - while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)) { - timeout--; - } - if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) { - flag = ERROR; - } else { - flag = SUCCESS; - } - } else if(CAN_MODE_SLEEP == working_mode) { - /* disable initialize mode */ - CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_IWMOD); - /* set sleep mode */ - CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD; - /* wait the acknowledge */ - while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)) { - timeout--; - } - if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) { - flag = ERROR; - } else { - flag = SUCCESS; - } - } else { - flag = ERROR; - } - return flag; -} - -/*! - \brief wake up CAN - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus can_wakeup(uint32_t can_periph) -{ - ErrStatus flag = ERROR; - uint32_t timeout = CAN_TIMEOUT; - - /* wakeup */ - CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; - - while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)) { - timeout--; - } - /* check state */ - if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) { - flag = ERROR; - } else { - flag = SUCCESS; - } - return flag; -} - -/*! - \brief get CAN error type - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval can_error_enum - \arg CAN_ERROR_NONE: no error - \arg CAN_ERROR_FILL: fill error - \arg CAN_ERROR_FORMATE: format error - \arg CAN_ERROR_ACK: ACK error - \arg CAN_ERROR_BITRECESSIVE: bit recessive - \arg CAN_ERROR_BITDOMINANTER: bit dominant error - \arg CAN_ERROR_CRC: CRC error - \arg CAN_ERROR_SOFTWARECFG: software configure -*/ -can_error_enum can_error_get(uint32_t can_periph) -{ - can_error_enum error; - error = CAN_ERROR_NONE; - - /* get error type */ - error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph))); - return error; -} - -/*! - \brief get CAN receive error number - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL - \param[out] none - \retval error number -*/ -uint8_t can_receive_error_number_get(uint32_t can_periph) -{ - uint8_t val; - - /* get error count */ - val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph))); - return val; -} - -/*! - \brief get CAN transmit error number - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[out] none - \retval error number -*/ -uint8_t can_transmit_error_number_get(uint32_t can_periph) -{ - uint8_t val; - - val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph))); - return val; -} - -/*! - \brief enable CAN interrupt - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] interrupt - one or more parameters can be selected which are shown as below: - \arg CAN_INT_TME: transmit mailbox empty interrupt enable - \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable - \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable - \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable - \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable - \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable - \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable - \arg CAN_INT_WERR: warning error interrupt enable - \arg CAN_INT_PERR: passive error interrupt enable - \arg CAN_INT_BO: bus-off interrupt enable - \arg CAN_INT_ERRN: error number interrupt enable - \arg CAN_INT_ERR: error interrupt enable - \arg CAN_INT_WU: wakeup interrupt enable - \arg CAN_INT_SLPW: sleep working interrupt enable - \param[out] none - \retval none -*/ -void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt) -{ - CAN_INTEN(can_periph) |= interrupt; -} - -/*! - \brief disable CAN interrupt - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] interrupt - one or more parameters can be selected which are shown as below: - \arg CAN_INT_TME: transmit mailbox empty interrupt enable - \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable - \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable - \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable - \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable - \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable - \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable - \arg CAN_INT_WERR: warning error interrupt enable - \arg CAN_INT_PERR: passive error interrupt enable - \arg CAN_INT_BO: bus-off interrupt enable - \arg CAN_INT_ERRN: error number interrupt enable - \arg CAN_INT_ERR: error interrupt enable - \arg CAN_INT_WU: wakeup interrupt enable - \arg CAN_INT_SLPW: sleep working interrupt enable - \param[out] none - \retval none -*/ -void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) -{ - CAN_INTEN(can_periph) &= ~interrupt; -} - -/*! - \brief get CAN flag state - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] flag: CAN flags, refer to can_flag_enum - only one parameter can be selected which is shown as below: - \arg CAN_FLAG_RXL: RX level - \arg CAN_FLAG_LASTRX: last sample value of RX pin - \arg CAN_FLAG_RS: receiving state - \arg CAN_FLAG_TS: transmitting state - \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode - \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode - \arg CAN_FLAG_ERRIF: error flag - \arg CAN_FLAG_SLPWS: sleep working state - \arg CAN_FLAG_IWS: initial working state - \arg CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO - \arg CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO - \arg CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO - \arg CAN_FLAG_TME2: transmit mailbox 2 empty - \arg CAN_FLAG_TME1: transmit mailbox 1 empty - \arg CAN_FLAG_TME0: transmit mailbox 0 empty - \arg CAN_FLAG_MTE2: mailbox 2 transmit error - \arg CAN_FLAG_MTE1: mailbox 1 transmit error - \arg CAN_FLAG_MTE0: mailbox 0 transmit error - \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost - \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost - \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost - \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error - \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error - \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error - \arg CAN_FLAG_MTF2: mailbox 2 transmit finished - \arg CAN_FLAG_MTF1: mailbox 1 transmit finished - \arg CAN_FLAG_MTF0: mailbox 0 transmit finished - \arg CAN_FLAG_RFO0: receive FIFO0 overfull - \arg CAN_FLAG_RFF0: receive FIFO0 full - \arg CAN_FLAG_RFO1: receive FIFO1 overfull - \arg CAN_FLAG_RFF1: receive FIFO1 full - \arg CAN_FLAG_BOERR: bus-off error - \arg CAN_FLAG_PERR: passive error - \arg CAN_FLAG_WERR: warning error - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) -{ - /* get flag and interrupt enable state */ - if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))) { - return SET; - } else { - return RESET; - } -} - -/*! - \brief clear CAN flag state - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] flag: CAN flags, refer to can_flag_enum - only one parameter can be selected which is shown as below: - \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode - \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode - \arg CAN_FLAG_ERRIF: error flag - \arg CAN_FLAG_MTE2: mailbox 2 transmit error - \arg CAN_FLAG_MTE1: mailbox 1 transmit error - \arg CAN_FLAG_MTE0: mailbox 0 transmit error - \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost - \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost - \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost - \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error - \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error - \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error - \arg CAN_FLAG_MTF2: mailbox 2 transmit finished - \arg CAN_FLAG_MTF1: mailbox 1 transmit finished - \arg CAN_FLAG_MTF0: mailbox 0 transmit finished - \arg CAN_FLAG_RFO0: receive FIFO0 overfull - \arg CAN_FLAG_RFF0: receive FIFO0 full - \arg CAN_FLAG_RFO1: receive FIFO1 overfull - \arg CAN_FLAG_RFF1: receive FIFO1 full - \param[out] none - \retval none -*/ -void can_flag_clear(uint32_t can_periph, can_flag_enum flag) -{ - CAN_REG_VAL(can_periph, flag) |= BIT(CAN_BIT_POS(flag)); -} - -/*! - \brief get CAN interrupt flag state - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] int_flag: CAN interrupt flags, refer to can_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering - \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode - \arg CAN_INT_FLAG_ERRIF: error interrupt flag - \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag - \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag - \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag - \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag - \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag - \arg CAN_INT_FLAG_RFL0: receive FIFO0 not empty interrupt flag - \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag - \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag - \arg CAN_INT_FLAG_RFL1: receive FIFO1 not empty interrupt flag - \arg CAN_INT_FLAG_ERRN: error number interrupt flag - \arg CAN_INT_FLAG_BOERR: bus-off error interrupt flag - \arg CAN_INT_FLAG_PERR: passive error interrupt flag - \arg CAN_INT_FLAG_WERR: warning error interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum int_flag) -{ - uint32_t ret1 = RESET; - uint32_t ret2 = RESET; - - /* get the staus of interrupt flag */ - if(int_flag == CAN_INT_FLAG_RFL0) { - ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0); - } else if(int_flag == CAN_INT_FLAG_RFL1) { - ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1); - } else if(int_flag == CAN_INT_FLAG_ERRN) { - ret1 = can_error_get(can_periph); - } else { - ret1 = CAN_REG_VALS(can_periph, int_flag) & BIT(CAN_BIT_POS0(int_flag)); - } - /* get the staus of interrupt enale bit */ - ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(int_flag)); - if(ret1 && ret2) { - return SET; - } else { - return RESET; - } -} - -/*! - \brief clear CAN interrupt flag state - \param[in] can_periph - \arg CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508 - \param[in] int_flag: CAN interrupt flags, refer to can_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering - \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode - \arg CAN_INT_FLAG_ERRIF: error interrupt flag - \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag - \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag - \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag - \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag - \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag - \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag - \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag - \param[out] none - \retval none -*/ -void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum int_flag) -{ - CAN_REG_VALS(can_periph, int_flag) |= BIT(CAN_BIT_POS0(int_flag)); -} -#endif /* GD32EPRT */ diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_crc.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_crc.c deleted file mode 100644 index ea8a401..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_crc.c +++ /dev/null @@ -1,239 +0,0 @@ -/*! - \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); -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_crc.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_crc.c.base@1.5.0 deleted file mode 100644 index ea8a401..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_crc.c.base@1.5.0 +++ /dev/null @@ -1,239 +0,0 @@ -/*! - \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); -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_ctc.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_ctc.c deleted file mode 100644 index 7816261..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_ctc.c +++ /dev/null @@ -1,388 +0,0 @@ -/*! - \file gd32e50x_ctc.c - \brief CTC 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_ctc.h" - -#define CTC_FLAG_MASK ((uint32_t)0x00000700U) - -/* CTC register bit offset */ -#define CTC_TRIMVALUE_OFFSET ((uint32_t)8U) -#define CTC_TRIM_VALUE_OFFSET ((uint32_t)8U) -#define CTC_REFCAP_OFFSET ((uint32_t)16U) -#define CTC_LIMIT_VALUE_OFFSET ((uint32_t)16U) - -/*! - \brief reset CTC clock trim controller - \param[in] none - \param[out] none - \retval none -*/ -void ctc_deinit(void) -{ - /* reset CTC */ - rcu_periph_reset_enable(RCU_CTCRST); - rcu_periph_reset_disable(RCU_CTCRST); -} - -/*! - \brief enable CTC trim counter - \param[in] none - \param[out] none - \retval none -*/ -void ctc_counter_enable(void) -{ - CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN; -} - -/*! - \brief disable CTC trim counter - \param[in] none - \param[out] none - \retval none -*/ -void ctc_counter_disable(void) -{ - CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN); -} - -/*! - \brief configure the IRC48M trim value - \param[in] trim_value: 6-bit IRC48M trim value - \arg 0x00 - 0x3F - \param[out] none - \retval none -*/ -void ctc_irc48m_trim_value_config(uint8_t trim_value) -{ - /* clear TRIMVALUE bits */ - CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE); - /* set TRIMVALUE bits */ - CTC_CTL0 |= ((uint32_t)trim_value << CTC_TRIM_VALUE_OFFSET); -} - -/*! - \brief generate software reference source sync pulse - \param[in] none - \param[out] none - \retval none -*/ -void ctc_software_refsource_pulse_generate(void) -{ - CTC_CTL0 |= (uint32_t)CTC_CTL0_SWREFPUL; -} - -/*! - \brief configure hardware automatically trim mode - \param[in] hardmode: - only one parameter can be selected which is shown as below: - \arg CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable - \arg CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable - \param[out] none - \retval none -*/ -void ctc_hardware_trim_mode_config(uint32_t hardmode) -{ - CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM); - CTC_CTL0 |= (uint32_t)hardmode; -} -/*! - \brief configure reference signal source polarity - \param[in] polarity: - only one parameter can be selected which is shown as below: - \arg CTC_REFSOURCE_POLARITY_FALLING: reference signal source polarity is falling edge - \arg CTC_REFSOURCE_POLARITY_RISING: reference signal source polarity is rising edge - \param[out] none - \retval none -*/ -void ctc_refsource_polarity_config(uint32_t polarity) -{ - CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL); - CTC_CTL1 |= (uint32_t)polarity; -} - -/*! - \brief select reference signal source - \param[in] refs: - only one parameter can be selected which is shown as below: - \arg CTC_REFSOURCE_GPIO: GPIO is selected - \arg CTC_REFSOURCE_LXTAL: LXTAL is selected - \param[out] none - \retval none -*/ -void ctc_refsource_signal_select(uint32_t refs) -{ - CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL); - CTC_CTL1 |= (uint32_t)refs; -} - -/*! - \brief configure reference signal source prescaler - \param[in] prescaler: - only one parameter can be selected which is shown as below: - \arg CTC_REFSOURCE_PSC_OFF: reference signal not divided - \arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2 - \arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4 - \arg CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8 - \arg CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16 - \arg CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32 - \arg CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64 - \arg CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128 - \param[out] none - \retval none -*/ -void ctc_refsource_prescaler_config(uint32_t prescaler) -{ - CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC); - CTC_CTL1 |= (uint32_t)prescaler; -} - -/*! - \brief configure clock trim base limit value - \param[in] limit_value: 8-bit clock trim base limit value - \arg 0x00 - 0xFF - \param[out] none - \retval none -*/ -void ctc_clock_limit_value_config(uint8_t limit_value) -{ - CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM); - CTC_CTL1 |= (uint32_t)((uint32_t)limit_value << CTC_LIMIT_VALUE_OFFSET); -} - -/*! - \brief configure CTC counter reload value - \param[in] reload_value: 16-bit CTC counter reload value - \arg 0x0000 - 0xFFFF - \param[out] none - \retval none -*/ -void ctc_counter_reload_value_config(uint16_t reload_value) -{ - CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE); - CTC_CTL1 |= (uint32_t)reload_value; -} - -/*! - \brief read CTC counter capture value when reference sync pulse occurred - \param[in] none - \param[out] none - \retval the 16-bit CTC counter capture value -*/ -uint16_t ctc_counter_capture_value_read(void) -{ - uint16_t capture_value = 0U; - capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> CTC_REFCAP_OFFSET); - return (capture_value); -} - -/*! - \brief read CTC trim counter direction when reference sync pulse occurred - \param[in] none - \param[out] none - \retval FlagStatus: SET or RESET - \arg SET: CTC trim counter direction is down-counting - \arg RESET: CTC trim counter direction is up-counting -*/ -FlagStatus ctc_counter_direction_read(void) -{ - if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief read CTC counter reload value - \param[in] none - \param[out] none - \retval the 16-bit CTC counter reload value -*/ -uint16_t ctc_counter_reload_value_read(void) -{ - uint16_t reload_value = 0U; - reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE); - return (reload_value); -} - -/*! - \brief read the IRC48M trim value - \param[in] none - \param[out] none - \retval the 6-bit IRC48M trim value -*/ -uint8_t ctc_irc48m_trim_value_read(void) -{ - uint8_t trim_value = 0U; - trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> CTC_TRIMVALUE_OFFSET); - return (trim_value); -} - -/*! - \brief get CTC flag - \param[in] flag: the CTC flag - only one parameter can be selected which is shown as below: - \arg CTC_FLAG_CKOK: clock trim OK flag - \arg CTC_FLAG_CKWARN: clock trim warning flag - \arg CTC_FLAG_ERR: error flag - \arg CTC_FLAG_EREF: expect reference flag - \arg CTC_FLAG_CKERR: clock trim error bit - \arg CTC_FLAG_REFMISS: reference sync pulse miss - \arg CTC_FLAG_TRIMERR: trim value error bit - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus ctc_flag_get(uint32_t flag) -{ - if(RESET != (CTC_STAT & flag)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear CTC flag - \param[in] flag: the CTC flag - only one parameter can be selected which is shown as below: - \arg CTC_FLAG_CKOK: clock trim OK flag - \arg CTC_FLAG_CKWARN: clock trim warning flag - \arg CTC_FLAG_ERR: error flag - \arg CTC_FLAG_EREF: expect reference flag - \arg CTC_FLAG_CKERR: clock trim error bit - \arg CTC_FLAG_REFMISS: reference sync pulse miss - \arg CTC_FLAG_TRIMERR: trim value error bit - \param[out] none - \retval none -*/ -void ctc_flag_clear(uint32_t flag) -{ - if(RESET != (flag & CTC_FLAG_MASK)){ - CTC_INTC |= CTC_INTC_ERRIC; - }else{ - CTC_INTC |= flag; - } -} - -/*! - \brief enable the CTC interrupt - \param[in] interrupt: CTC interrupt enable - one or more parameters can be selected which are shown as below: - \arg CTC_INT_CKOK: clock trim OK interrupt enable - \arg CTC_INT_CKWARN: clock trim warning interrupt enable - \arg CTC_INT_ERR: error interrupt enable - \arg CTC_INT_EREF: expect reference interrupt enable - \param[out] none - \retval none -*/ -void ctc_interrupt_enable(uint32_t interrupt) -{ - CTC_CTL0 |= (uint32_t)interrupt; -} - -/*! - \brief disable the CTC interrupt - \param[in] interrupt: CTC interrupt enable source - one or more parameters can be selected which are shown as below: - \arg CTC_INT_CKOK: clock trim OK interrupt enable - \arg CTC_INT_CKWARN: clock trim warning interrupt enable - \arg CTC_INT_ERR: error interrupt enable - \arg CTC_INT_EREF: expect reference interrupt enable - \param[out] none - \retval none -*/ -void ctc_interrupt_disable(uint32_t interrupt) -{ - CTC_CTL0 &= (uint32_t)(~interrupt); -} - -/*! - \brief get CTC interrupt flag - \param[in] int_flag: the CTC interrupt flag - only one parameter can be selected which is shown as below: - \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt - \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt - \arg CTC_INT_FLAG_ERR: error interrupt - \arg CTC_INT_FLAG_EREF: expect reference interrupt - \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt - \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt - \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus ctc_interrupt_flag_get(uint32_t int_flag) -{ - uint32_t interrupt_flag = 0U, intenable = 0U; - - /* check whether the interrupt is enabled */ - if(RESET != (int_flag & CTC_FLAG_MASK)){ - intenable = CTC_CTL0 & CTC_CTL0_ERRIE; - }else{ - intenable = CTC_CTL0 & int_flag; - } - - /* get interrupt flag status */ - interrupt_flag = CTC_STAT & int_flag; - - if(interrupt_flag && intenable){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear CTC interrupt flag - \param[in] int_flag: the CTC interrupt flag - only one parameter can be selected which is shown as below: - \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt - \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt - \arg CTC_INT_FLAG_ERR: error interrupt - \arg CTC_INT_FLAG_EREF: expect reference interrupt - \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt - \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt - \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt - \param[out] none - \retval none -*/ -void ctc_interrupt_flag_clear(uint32_t int_flag) -{ - if(RESET != (int_flag & CTC_FLAG_MASK)){ - CTC_INTC |= CTC_INTC_ERRIC; - }else{ - CTC_INTC |= int_flag; - } -} - diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_ctc.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_ctc.c.base@1.5.0 deleted file mode 100644 index 7816261..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_ctc.c.base@1.5.0 +++ /dev/null @@ -1,388 +0,0 @@ -/*! - \file gd32e50x_ctc.c - \brief CTC 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_ctc.h" - -#define CTC_FLAG_MASK ((uint32_t)0x00000700U) - -/* CTC register bit offset */ -#define CTC_TRIMVALUE_OFFSET ((uint32_t)8U) -#define CTC_TRIM_VALUE_OFFSET ((uint32_t)8U) -#define CTC_REFCAP_OFFSET ((uint32_t)16U) -#define CTC_LIMIT_VALUE_OFFSET ((uint32_t)16U) - -/*! - \brief reset CTC clock trim controller - \param[in] none - \param[out] none - \retval none -*/ -void ctc_deinit(void) -{ - /* reset CTC */ - rcu_periph_reset_enable(RCU_CTCRST); - rcu_periph_reset_disable(RCU_CTCRST); -} - -/*! - \brief enable CTC trim counter - \param[in] none - \param[out] none - \retval none -*/ -void ctc_counter_enable(void) -{ - CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN; -} - -/*! - \brief disable CTC trim counter - \param[in] none - \param[out] none - \retval none -*/ -void ctc_counter_disable(void) -{ - CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN); -} - -/*! - \brief configure the IRC48M trim value - \param[in] trim_value: 6-bit IRC48M trim value - \arg 0x00 - 0x3F - \param[out] none - \retval none -*/ -void ctc_irc48m_trim_value_config(uint8_t trim_value) -{ - /* clear TRIMVALUE bits */ - CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE); - /* set TRIMVALUE bits */ - CTC_CTL0 |= ((uint32_t)trim_value << CTC_TRIM_VALUE_OFFSET); -} - -/*! - \brief generate software reference source sync pulse - \param[in] none - \param[out] none - \retval none -*/ -void ctc_software_refsource_pulse_generate(void) -{ - CTC_CTL0 |= (uint32_t)CTC_CTL0_SWREFPUL; -} - -/*! - \brief configure hardware automatically trim mode - \param[in] hardmode: - only one parameter can be selected which is shown as below: - \arg CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable - \arg CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable - \param[out] none - \retval none -*/ -void ctc_hardware_trim_mode_config(uint32_t hardmode) -{ - CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM); - CTC_CTL0 |= (uint32_t)hardmode; -} -/*! - \brief configure reference signal source polarity - \param[in] polarity: - only one parameter can be selected which is shown as below: - \arg CTC_REFSOURCE_POLARITY_FALLING: reference signal source polarity is falling edge - \arg CTC_REFSOURCE_POLARITY_RISING: reference signal source polarity is rising edge - \param[out] none - \retval none -*/ -void ctc_refsource_polarity_config(uint32_t polarity) -{ - CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL); - CTC_CTL1 |= (uint32_t)polarity; -} - -/*! - \brief select reference signal source - \param[in] refs: - only one parameter can be selected which is shown as below: - \arg CTC_REFSOURCE_GPIO: GPIO is selected - \arg CTC_REFSOURCE_LXTAL: LXTAL is selected - \param[out] none - \retval none -*/ -void ctc_refsource_signal_select(uint32_t refs) -{ - CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL); - CTC_CTL1 |= (uint32_t)refs; -} - -/*! - \brief configure reference signal source prescaler - \param[in] prescaler: - only one parameter can be selected which is shown as below: - \arg CTC_REFSOURCE_PSC_OFF: reference signal not divided - \arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2 - \arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4 - \arg CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8 - \arg CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16 - \arg CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32 - \arg CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64 - \arg CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128 - \param[out] none - \retval none -*/ -void ctc_refsource_prescaler_config(uint32_t prescaler) -{ - CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC); - CTC_CTL1 |= (uint32_t)prescaler; -} - -/*! - \brief configure clock trim base limit value - \param[in] limit_value: 8-bit clock trim base limit value - \arg 0x00 - 0xFF - \param[out] none - \retval none -*/ -void ctc_clock_limit_value_config(uint8_t limit_value) -{ - CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM); - CTC_CTL1 |= (uint32_t)((uint32_t)limit_value << CTC_LIMIT_VALUE_OFFSET); -} - -/*! - \brief configure CTC counter reload value - \param[in] reload_value: 16-bit CTC counter reload value - \arg 0x0000 - 0xFFFF - \param[out] none - \retval none -*/ -void ctc_counter_reload_value_config(uint16_t reload_value) -{ - CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE); - CTC_CTL1 |= (uint32_t)reload_value; -} - -/*! - \brief read CTC counter capture value when reference sync pulse occurred - \param[in] none - \param[out] none - \retval the 16-bit CTC counter capture value -*/ -uint16_t ctc_counter_capture_value_read(void) -{ - uint16_t capture_value = 0U; - capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> CTC_REFCAP_OFFSET); - return (capture_value); -} - -/*! - \brief read CTC trim counter direction when reference sync pulse occurred - \param[in] none - \param[out] none - \retval FlagStatus: SET or RESET - \arg SET: CTC trim counter direction is down-counting - \arg RESET: CTC trim counter direction is up-counting -*/ -FlagStatus ctc_counter_direction_read(void) -{ - if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief read CTC counter reload value - \param[in] none - \param[out] none - \retval the 16-bit CTC counter reload value -*/ -uint16_t ctc_counter_reload_value_read(void) -{ - uint16_t reload_value = 0U; - reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE); - return (reload_value); -} - -/*! - \brief read the IRC48M trim value - \param[in] none - \param[out] none - \retval the 6-bit IRC48M trim value -*/ -uint8_t ctc_irc48m_trim_value_read(void) -{ - uint8_t trim_value = 0U; - trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> CTC_TRIMVALUE_OFFSET); - return (trim_value); -} - -/*! - \brief get CTC flag - \param[in] flag: the CTC flag - only one parameter can be selected which is shown as below: - \arg CTC_FLAG_CKOK: clock trim OK flag - \arg CTC_FLAG_CKWARN: clock trim warning flag - \arg CTC_FLAG_ERR: error flag - \arg CTC_FLAG_EREF: expect reference flag - \arg CTC_FLAG_CKERR: clock trim error bit - \arg CTC_FLAG_REFMISS: reference sync pulse miss - \arg CTC_FLAG_TRIMERR: trim value error bit - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus ctc_flag_get(uint32_t flag) -{ - if(RESET != (CTC_STAT & flag)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear CTC flag - \param[in] flag: the CTC flag - only one parameter can be selected which is shown as below: - \arg CTC_FLAG_CKOK: clock trim OK flag - \arg CTC_FLAG_CKWARN: clock trim warning flag - \arg CTC_FLAG_ERR: error flag - \arg CTC_FLAG_EREF: expect reference flag - \arg CTC_FLAG_CKERR: clock trim error bit - \arg CTC_FLAG_REFMISS: reference sync pulse miss - \arg CTC_FLAG_TRIMERR: trim value error bit - \param[out] none - \retval none -*/ -void ctc_flag_clear(uint32_t flag) -{ - if(RESET != (flag & CTC_FLAG_MASK)){ - CTC_INTC |= CTC_INTC_ERRIC; - }else{ - CTC_INTC |= flag; - } -} - -/*! - \brief enable the CTC interrupt - \param[in] interrupt: CTC interrupt enable - one or more parameters can be selected which are shown as below: - \arg CTC_INT_CKOK: clock trim OK interrupt enable - \arg CTC_INT_CKWARN: clock trim warning interrupt enable - \arg CTC_INT_ERR: error interrupt enable - \arg CTC_INT_EREF: expect reference interrupt enable - \param[out] none - \retval none -*/ -void ctc_interrupt_enable(uint32_t interrupt) -{ - CTC_CTL0 |= (uint32_t)interrupt; -} - -/*! - \brief disable the CTC interrupt - \param[in] interrupt: CTC interrupt enable source - one or more parameters can be selected which are shown as below: - \arg CTC_INT_CKOK: clock trim OK interrupt enable - \arg CTC_INT_CKWARN: clock trim warning interrupt enable - \arg CTC_INT_ERR: error interrupt enable - \arg CTC_INT_EREF: expect reference interrupt enable - \param[out] none - \retval none -*/ -void ctc_interrupt_disable(uint32_t interrupt) -{ - CTC_CTL0 &= (uint32_t)(~interrupt); -} - -/*! - \brief get CTC interrupt flag - \param[in] int_flag: the CTC interrupt flag - only one parameter can be selected which is shown as below: - \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt - \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt - \arg CTC_INT_FLAG_ERR: error interrupt - \arg CTC_INT_FLAG_EREF: expect reference interrupt - \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt - \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt - \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus ctc_interrupt_flag_get(uint32_t int_flag) -{ - uint32_t interrupt_flag = 0U, intenable = 0U; - - /* check whether the interrupt is enabled */ - if(RESET != (int_flag & CTC_FLAG_MASK)){ - intenable = CTC_CTL0 & CTC_CTL0_ERRIE; - }else{ - intenable = CTC_CTL0 & int_flag; - } - - /* get interrupt flag status */ - interrupt_flag = CTC_STAT & int_flag; - - if(interrupt_flag && intenable){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear CTC interrupt flag - \param[in] int_flag: the CTC interrupt flag - only one parameter can be selected which is shown as below: - \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt - \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt - \arg CTC_INT_FLAG_ERR: error interrupt - \arg CTC_INT_FLAG_EREF: expect reference interrupt - \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt - \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt - \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt - \param[out] none - \retval none -*/ -void ctc_interrupt_flag_clear(uint32_t int_flag) -{ - if(RESET != (int_flag & CTC_FLAG_MASK)){ - CTC_INTC |= CTC_INTC_ERRIC; - }else{ - CTC_INTC |= int_flag; - } -} - diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dbg.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dbg.c deleted file mode 100644 index 629de2e..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dbg.c +++ /dev/null @@ -1,148 +0,0 @@ -/*! - \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; -} - diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dbg.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dbg.c.base@1.5.0 deleted file mode 100644 index 629de2e..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dbg.c.base@1.5.0 +++ /dev/null @@ -1,148 +0,0 @@ -/*! - \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; -} - diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dma.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dma.c deleted file mode 100644 index 9b4b501..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dma.c +++ /dev/null @@ -1,752 +0,0 @@ -/*! - \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 - -#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; -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dma.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dma.c.base@1.5.0 deleted file mode 100644 index 9b4b501..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_dma.c.base@1.5.0 +++ /dev/null @@ -1,752 +0,0 @@ -/*! - \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 - -#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; -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_exti.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_exti.c deleted file mode 100644 index 99cfa62..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_exti.c +++ /dev/null @@ -1,249 +0,0 @@ -/*! - \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; -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_exti.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_exti.c.base@1.5.0 deleted file mode 100644 index 99cfa62..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_exti.c.base@1.5.0 +++ /dev/null @@ -1,249 +0,0 @@ -/*! - \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; -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fmc.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fmc.c deleted file mode 100644 index a220f53..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fmc.c +++ /dev/null @@ -1,875 +0,0 @@ -/*! - \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; -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fmc.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fmc.c.base@1.5.0 deleted file mode 100644 index a220f53..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fmc.c.base@1.5.0 +++ /dev/null @@ -1,875 +0,0 @@ -/*! - \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; -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c deleted file mode 100644 index 0e18853..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c +++ /dev/null @@ -1,227 +0,0 @@ -/*! - \file gd32e50x_fwdgt.c - \brief FWDGT 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_fwdgt.h" - -/*! - \brief enable write access to FWDGT_PSC and FWDGT_RLD - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_write_enable(void) -{ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; -} - -/*! - \brief disable write access to FWDGT_PSC and FWDGT_RLD - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_write_disable(void) -{ - FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; -} - -/*! - \brief start the free watchdog timer counter - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_enable(void) -{ - FWDGT_CTL = FWDGT_KEY_ENABLE; -} - -/*! - \brief configure the free watchdog timer counter prescaler value - \param[in] prescaler_value: specify prescaler value - only one parameter can be selected which is shown as below: - \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 - \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 - \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 - \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 - \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 - \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 - \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value) -{ - uint32_t timeout = FWDGT_PSC_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* enable write access to FWDGT_PSC */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT */ - FWDGT_PSC = (uint32_t)prescaler_value; - - /* wait until the PUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_PUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - return status; -} - -/*! - \brief configure the free watchdog timer counter reload value - \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_reload_value_config(uint16_t reload_value) -{ - uint32_t timeout = FWDGT_RLD_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* enable write access to FWDGT_RLD */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT_RLD */ - FWDGT_RLD = RLD_RLD(reload_value); - - /* wait until the RUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_RUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - return status; -} - -/*! - \brief reload the counter of FWDGT - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_counter_reload(void) -{ - FWDGT_CTL = FWDGT_KEY_RELOAD; -} - -/*! - \brief configure counter reload value, and prescaler divider value - \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) - \param[in] prescaler_value: FWDGT prescaler value - only one parameter can be selected which is shown as below: - \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 - \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 - \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 - \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 - \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 - \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 - \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_value) -{ - uint32_t timeout = FWDGT_PSC_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* start the free watchdog timer counter */ - FWDGT_CTL = FWDGT_KEY_ENABLE; - - /* enable write access to FWDGT_PSC,and FWDGT_RLD */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT PSC */ - FWDGT_PSC = (uint32_t)prescaler_value; - - /* wait until the PUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_PUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - if(SUCCESS == status) { - /* configure FWDGT_RLD */ - FWDGT_RLD = RLD_RLD(reload_value); - - /* wait until the RUD flag to be reset */ - timeout = FWDGT_RLD_TIMEOUT; - do { - flag_status = FWDGT_STAT & FWDGT_STAT_RUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - } - - if(SUCCESS == status) { - /* reload the counter */ - FWDGT_CTL = FWDGT_KEY_RELOAD; - } - - return status; -} - -/*! - \brief get flag state of FWDGT - \param[in] flag: flag to get - only one parameter can be selected which is shown as below: - \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going - \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus fwdgt_flag_get(uint16_t flag) -{ - FlagStatus flag_status = RESET; - if(FWDGT_STAT & flag) { - flag_status = SET; - } - return flag_status; -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c.base@1.5.0 deleted file mode 100644 index 0e18853..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c.base@1.5.0 +++ /dev/null @@ -1,227 +0,0 @@ -/*! - \file gd32e50x_fwdgt.c - \brief FWDGT 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_fwdgt.h" - -/*! - \brief enable write access to FWDGT_PSC and FWDGT_RLD - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_write_enable(void) -{ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; -} - -/*! - \brief disable write access to FWDGT_PSC and FWDGT_RLD - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_write_disable(void) -{ - FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; -} - -/*! - \brief start the free watchdog timer counter - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_enable(void) -{ - FWDGT_CTL = FWDGT_KEY_ENABLE; -} - -/*! - \brief configure the free watchdog timer counter prescaler value - \param[in] prescaler_value: specify prescaler value - only one parameter can be selected which is shown as below: - \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 - \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 - \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 - \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 - \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 - \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 - \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value) -{ - uint32_t timeout = FWDGT_PSC_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* enable write access to FWDGT_PSC */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT */ - FWDGT_PSC = (uint32_t)prescaler_value; - - /* wait until the PUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_PUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - return status; -} - -/*! - \brief configure the free watchdog timer counter reload value - \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_reload_value_config(uint16_t reload_value) -{ - uint32_t timeout = FWDGT_RLD_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* enable write access to FWDGT_RLD */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT_RLD */ - FWDGT_RLD = RLD_RLD(reload_value); - - /* wait until the RUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_RUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - return status; -} - -/*! - \brief reload the counter of FWDGT - \param[in] none - \param[out] none - \retval none -*/ -void fwdgt_counter_reload(void) -{ - FWDGT_CTL = FWDGT_KEY_RELOAD; -} - -/*! - \brief configure counter reload value, and prescaler divider value - \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) - \param[in] prescaler_value: FWDGT prescaler value - only one parameter can be selected which is shown as below: - \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 - \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 - \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 - \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 - \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 - \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 - \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 - \param[out] none - \retval ErrStatus: ERROR or SUCCESS -*/ -ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_value) -{ - uint32_t timeout = FWDGT_PSC_TIMEOUT; - uint32_t flag_status = RESET; - ErrStatus status = SUCCESS; - - /* start the free watchdog timer counter */ - FWDGT_CTL = FWDGT_KEY_ENABLE; - - /* enable write access to FWDGT_PSC,and FWDGT_RLD */ - FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - - /* configure FWDGT PSC */ - FWDGT_PSC = (uint32_t)prescaler_value; - - /* wait until the PUD flag to be reset */ - do { - flag_status = FWDGT_STAT & FWDGT_STAT_PUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - - if(SUCCESS == status) { - /* configure FWDGT_RLD */ - FWDGT_RLD = RLD_RLD(reload_value); - - /* wait until the RUD flag to be reset */ - timeout = FWDGT_RLD_TIMEOUT; - do { - flag_status = FWDGT_STAT & FWDGT_STAT_RUD; - } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if((uint32_t)RESET != flag_status) { - status = ERROR; - } - } - - if(SUCCESS == status) { - /* reload the counter */ - FWDGT_CTL = FWDGT_KEY_RELOAD; - } - - return status; -} - -/*! - \brief get flag state of FWDGT - \param[in] flag: flag to get - only one parameter can be selected which is shown as below: - \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going - \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus fwdgt_flag_get(uint16_t flag) -{ - FlagStatus flag_status = RESET; - if(FWDGT_STAT & flag) { - flag_status = SET; - } - return flag_status; -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_gpio.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_gpio.c deleted file mode 100644 index fcff5ba..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_gpio.c +++ /dev/null @@ -1,699 +0,0 @@ -/*! - \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; - } -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_gpio.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_gpio.c.base@1.5.0 deleted file mode 100644 index fcff5ba..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_gpio.c.base@1.5.0 +++ /dev/null @@ -1,699 +0,0 @@ -/*! - \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; - } -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_misc.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_misc.c deleted file mode 100644 index 8d58fb7..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_misc.c +++ /dev/null @@ -1,180 +0,0 @@ -/*! - \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; - } -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_misc.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_misc.c.base@1.5.0 deleted file mode 100644 index 8d58fb7..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_misc.c.base@1.5.0 +++ /dev/null @@ -1,180 +0,0 @@ -/*! - \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; - } -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_pmu.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_pmu.c deleted file mode 100644 index 853f0d6..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_pmu.c +++ /dev/null @@ -1,522 +0,0 @@ -/*! - \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; - } -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_pmu.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_pmu.c.base@1.5.0 deleted file mode 100644 index 853f0d6..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_pmu.c.base@1.5.0 +++ /dev/null @@ -1,522 +0,0 @@ -/*! - \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; - } -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_rcu.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_rcu.c deleted file mode 100644 index 41a5251..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_rcu.c +++ /dev/null @@ -1,1621 +0,0 @@ -/*! - \file gd32e50x_rcu.c - \brief RCU driver - - \version 2026-02-09, V1.7.0, firmware for GD32E50x -*/ - -/* - Copyright (c) 2025, GigaDevice Semiconductor Inc. - - All rights reserved. - - 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_rcu.h" - -/* define clock source */ -#define SEL_IRC8M ((uint16_t)0U) /* IRC8M is selected as CK_SYS */ -#define SEL_HXTAL ((uint16_t)1U) /* HXTAL is selected as CK_SYS */ -#define SEL_PLL ((uint16_t)2U) /* PLL is selected as CK_SYS */ - -/* define startup timeout count */ -#define OSC_STARTUP_TIMEOUT ((uint32_t)0x000FFFFFU) -#define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x03FFFFFFU) - -/* ADC clock prescaler offset */ -#define RCU_ADC_PSC_OFFSET ((uint32_t)14U) - -/* RCU IRC8M adjust value mask and offset*/ -#define RCU_IRC8M_ADJUST_MASK ((uint8_t)0x1FU) -#define RCU_IRC8M_ADJUST_OFFSET ((uint32_t)3U) - -/* RCU PLL1 clock multiplication factor offset */ -#define RCU_CFG1_PLL1MF_OFFSET ((uint32_t)8U) -/* RCU PREDV1 division factor offset*/ -#define RCU_CFG1_PREDV1_OFFSET ((uint32_t)4U) - -/*! - \brief deinitialize the RCU - \param[in] none - \param[out] none - \retval none -*/ -void rcu_deinit(void) -{ - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - while(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - } - RCU_CFG0 &= ~RCU_CFG0_SCS; - /* reset CTL register */ - RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); - RCU_CTL &= ~RCU_CTL_HXTALBPS; -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); -#endif /* GD32E50X_CL and GD32EPRT and GD32E508 */ - /* reset CFG0 register */ -#if defined(GD32E50X_HD) - RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | - RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF | - RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_PLLMF_4 | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBDPSC_2); -#elif defined(GD32E50X_CL) || defined(GD32E508) - RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | - RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | - RCU_CFG0_USBHSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBHSPSC_2); -#elif defined(GD32EPRT) - RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | - RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | - RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBDPSC_2); -#endif /* GD32E50X_HD */ - - /* reset INT and CFG1 register */ -#if defined(GD32E50X_HD) - RCU_INT = 0x009f0000U; - RCU_CFG1 &= ~(RCU_CFG1_ADCPSC_3 | RCU_CFG1_PLLPRESEL); - RCU_CFG2 &= ~(RCU_CFG2_USART5SEL | RCU_CFG2_I2C2SEL); -#elif defined(GD32E50X_CL) || defined(GD32E508) - RCU_INT = 0x00ff0000U; - RCU_ADDINT = 0x00C00000U; - RCU_ADDCTL &= ~(RCU_ADDCTL_CK48MSEL | RCU_ADDCTL_USBHSSEL | RCU_ADDCTL_USBHSDV | RCU_ADDCTL_USBSWEN | RCU_ADDCTL_PLLUSBEN | RCU_ADDCTL_IRC48MEN); - RCU_ADDCFG &= ~(RCU_ADDCFG_PLLUSBPREDV | RCU_ADDCFG_PLLUSBPRESEL | RCU_ADDCFG_PLLUSBPREDVSEL | RCU_ADDCFG_PLLUSBMF); - - RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF | - RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL | RCU_CFG1_SHRTIMERSEL | RCU_CFG1_PLL2MF_5 | RCU_CFG1_ADCPSC_3 | - RCU_CFG1_PLLPRESEL | RCU_CFG1_PLL2MF_4); - RCU_CFG2 &= ~(RCU_CFG2_USART5SEL | RCU_CFG2_I2C2SEL); -#elif defined(GD32EPRT) - RCU_INT = 0x00ff0000U; - RCU_ADDINT &= ~ (RCU_ADDINT_IRC48MSTBIC); - RCU_ADDCTL &= ~(RCU_ADDCTL_CK48MSEL | RCU_ADDCTL_IRC48MEN); - - RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF | - RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL | RCU_CFG1_PLL2MF_5 | RCU_CFG1_ADCPSC_3 | - RCU_CFG1_PLLPRESEL | RCU_CFG1_PLL2MF_4); - RCU_CFG2 &= ~(RCU_CFG2_USART5SEL | RCU_CFG2_I2C2SEL); - -#endif /* GD32E50X_HD */ -} - -/*! - \brief enable the peripherals clock - \param[in] periph: RCU peripherals, refer to rcu_periph_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOx (x = A,B,C,D,E,F,G): GPIO ports clock - \arg RCU_AF : alternate function clock - \arg RCU_CRC: CRC clock - \arg RCU_DMAx (x = 0,1): DMA clock - \arg RCU_ENET: ENET clock(EPRT and CL series available) - \arg RCU_ENETTX: ENETTX clock(EPRT and CL series available) - \arg RCU_ENETRX: ENETRX clock(EPRT and CL series available) - \arg RCU_USBD: USBD clock(HD and EPRT series available) - \arg RCU_USBHS: USBHS clock(CL series available) - \arg RCU_TMU: TMU clock - \arg RCU_SQPI: SQPI clock - \arg RCU_EXMC: EXMC clock - \arg RCU_TIMERx (x = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): TIMER clock - \arg RCU_WWDGT: WWDGT clock - \arg RCU_SPIx (x = 0,1,2): SPI clock - \arg RCU_USARTx (x = 0,1,2,5): USART clock - \arg RCU_UARTx (x = 3,4): UART clock - \arg RCU_I2Cx (x = 0,1,2): I2C clock - \arg RCU_CANx (x = 0,1,2,CAN2 is only available for CL series,CANx is not avaliable for GD32EPRT): CAN clock - \arg RCU_PMU: PMU clock - \arg RCU_DAC: DAC clock - \arg RCU_RTC: RTC clock - \arg RCU_ADCx (x = 0,1,2, ADC2 is not available for CL series): ADC clock - \arg RCU_SDIO: SDIO clock(not available for CL and EPRT series) - \arg RCU_CTC: CTC clock - \arg RCU_BKPI: BKP interface clock - \arg RCU_SHRTIMER: (not available for EPRT series):SHRTIMER clock - \arg RCU_CMP(CMP is only available for CL series):CMP clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_enable(rcu_periph_enum periph) -{ - RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief disable the peripherals clock - \param[in] periph: RCU peripherals, refer to rcu_periph_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOx (x = A,B,C,D,E,F,G): GPIO ports clock - \arg RCU_AF : alternate function clock - \arg RCU_CRC: CRC clock - \arg RCU_DMAx (x =0,1): DMA clock - \arg RCU_ENET: ENET clock(EPRT and CL series available) - \arg RCU_ENETTX: ENETTX clock(EPRT and CL series available) - \arg RCU_ENETRX: ENETRX clock(EPRT and CL series available) - \arg RCU_USBD: USBD clock(HD and EPRT series available) - \arg RCU_USBHS: USBHS clock(CL series available) - \arg RCU_TMU: TMU clock - \arg RCU_SQPI: SQPI clock - \arg RCU_EXMC: EXMC clock - \arg RCU_TIMERx (x = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): TIMER clock - \arg RCU_WWDGT: WWDGT clock - \arg RCU_SPIx (x = 0,1,2): SPI clock - \arg RCU_USARTx (x = 0,1,2,5): USART clock - \arg RCU_UARTx (x = 3,4): UART clock - \arg RCU_I2Cx (x = 0,1,2): I2C clock - \arg RCU_CANx (x = 0,1,2,CAN2 is only available for CL series,CANx is not avaliable for GD32EPRT): CAN clock - \arg RCU_PMU: PMU clock - \arg RCU_DAC: DAC clock - \arg RCU_RTC: RTC clock - \arg RCU_ADCx (x = 0,1,2,ADC2 is not available for CL series): ADC clock - \arg RCU_SDIO: SDIO clock(not available for CL and EPRT series) - \arg RCU_CTC: CTC clock - \arg RCU_BKPI: BKP interface clock - \arg RCU_SHRTIMER: (not available for EPRT series): SHRTIMER clock - \arg RCU_CMP(CMP is only available for CL series):CMP clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_disable(rcu_periph_enum periph) -{ - RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief enable the peripherals clock when sleep mode - \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum - only one parameter can be selected which is shown as below: - \arg RCU_FMC_SLP: FMC clock - \arg RCU_SRAM_SLP: SRAM clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph) -{ - RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief disable the peripherals clock when sleep mode - \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum - only one parameter can be selected which is shown as below: - \arg RCU_SRAM_SLP: SRAM clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) -{ - RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief reset the peripherals - \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOxRST (x = A,B,C,D,E,F,G): reset GPIO ports - \arg RCU_AFRST : reset alternate function clock - \arg RCU_ENETRST: reset ENET(EPRT and CL series available) - \arg RCU_USBDRST: reset USBD(HD and EPRT series available) - \arg RCU_USBHSRST: reset USBHS(CL series available) - \arg RCU_TMURST: reset TMU - \arg RCU_SQPIRST: reset SQPI - \arg RCU_TIMERxRST (x = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): reset TIMER - \arg RCU_WWDGTRST: reset WWDGT - \arg RCU_SPIxRST (x = 0,1,2): reset SPI - \arg RCU_USARTxRST (x = 0,1,2,5): reset USART - \arg RCU_UARTxRST (x = 3,4): reset UART - \arg RCU_I2CxRST (x = 0,1): reset I2C - \arg RCU_PMURST: reset PMU - \arg RCU_DACRST: reset DAC - \arg RCU_ADCRST (x = 0,1,2,ADC2 is not available for CL series): reset ADC - \arg RCU_CTCRST: reset CTC - \arg RCU_BKPIRST: reset BKPI - \arg RCU_SHRTIMERRST: (not available for EPRT series):reset SHRTIMERRST - \arg RCU_CMPRST(CMP is only available for CL series): reset CMP - \param[out] none - \retval none -*/ -void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) -{ - RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset)); -} - -/*! - \brief disable reset the peripheral - \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOxRST (x = A,B,C,D,E,F,G): reset GPIO ports - \arg RCU_AFRST : reset alternate function clock - \arg RCU_ENETRST: reset ENET(CL series available) - \arg RCU_USBDRST: reset USBD(HD and EPRT series available) - \arg RCU_USBHSRST: reset USBHS(CL series available) - \arg RCU_TMURST: reset TMU - \arg RCU_SQPIRST: reset SQPI - \arg RCU_TIMERxRST (x = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): reset TIMER - \arg RCU_WWDGTRST: reset WWDGT - \arg RCU_SPIxRST (x = 0,1,2): reset SPI - \arg RCU_USARTxRST (x = 0,1,2,5): reset USART - \arg RCU_UARTxRST (x = 3,4): reset UART - \arg RCU_I2CxRST (x = 0,1): reset I2C - \arg RCU_PMURST: reset PMU - \arg RCU_DACRST: reset DAC - \arg RCU_ADCRST (x = 0,1,2,ADC2 is not available for CL series): reset ADC - \arg RCU_CTCRST: reset CTC - \arg RCU_BKPIRST: reset BKPI - \arg RCU_SHRTIMERRST: (not available for EPRT series):reset SHRTIMERRST - \arg RCU_CMPRST(CMP is only available for CL series): reset CMP - \param[out] none - \retval none -*/ -void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset) -{ - RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset)); -} - -/*! - \brief reset the BKP domain - \param[in] none - \param[out] none - \retval none -*/ -void rcu_bkp_reset_enable(void) -{ - RCU_BDCTL |= RCU_BDCTL_BKPRST; -} - -/*! - \brief disable the BKP domain reset - \param[in] none - \param[out] none - \retval none -*/ -void rcu_bkp_reset_disable(void) -{ - RCU_BDCTL &= ~RCU_BDCTL_BKPRST; -} - -/*! - \brief configure the system clock source - \param[in] ck_sys: system clock source select - only one parameter can be selected which is shown as below: - \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source - \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source - \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source - \param[out] none - \retval none -*/ -void rcu_system_clock_source_config(uint32_t ck_sys) -{ - uint32_t reg; - - reg = RCU_CFG0; - /* reset the SCS bits and set according to ck_sys */ - reg &= ~RCU_CFG0_SCS; - RCU_CFG0 = (reg | ck_sys); -} - -/*! - \brief get the system clock source - \param[in] none - \param[out] none - \retval which clock is selected as CK_SYS source - \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source - \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source - \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source -*/ -uint32_t rcu_system_clock_source_get(void) -{ - return (RCU_CFG0 & RCU_CFG0_SCSS); -} - -/*! - \brief configure the AHB clock prescaler selection - \param[in] ck_ahb: AHB clock prescaler selection - only one parameter can be selected which is shown as below: - \arg RCU_AHB_CKSYS_DIVx (x = 1, 2, 4, 8, 16, 64, 128, 256, 512): select CK_SYS / x as CK_AHB - \param[out] none - \retval none -*/ -void rcu_ahb_clock_config(uint32_t ck_ahb) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the AHBPSC bits and set according to ck_ahb */ - reg &= ~RCU_CFG0_AHBPSC; - RCU_CFG0 = (reg | ck_ahb); -} - -/*! - \brief configure the APB1 clock prescaler selection - \param[in] ck_apb1: APB1 clock prescaler selection - only one parameter can be selected which is shown as below: - \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1 - \arg RCU_APB1_CKAHB_DIV2: select CK_AHB / 2 as CK_APB1 - \arg RCU_APB1_CKAHB_DIV4: select CK_AHB / 4 as CK_APB1 - \arg RCU_APB1_CKAHB_DIV8: select CK_AHB / 8 as CK_APB1 - \arg RCU_APB1_CKAHB_DIV16: select CK_AHB / 16 as CK_APB1 - \param[out] none - \retval none -*/ -void rcu_apb1_clock_config(uint32_t ck_apb1) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the APB1PSC and set according to ck_apb1 */ - reg &= ~RCU_CFG0_APB1PSC; - RCU_CFG0 = (reg | ck_apb1); -} - -/*! - \brief configure the APB2 clock prescaler selection - \param[in] ck_apb2: APB2 clock prescaler selection - only one parameter can be selected which is shown as below: - \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2 - \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2 - \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2 - \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2 - \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2 - \param[out] none - \retval none -*/ -void rcu_apb2_clock_config(uint32_t ck_apb2) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the APB2PSC and set according to ck_apb2 */ - reg &= ~RCU_CFG0_APB2PSC; - RCU_CFG0 = (reg | ck_apb2); -} - -/*! - \brief configure the CK_OUT0 clock source - \param[in] ckout0_src: CK_OUT0 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_CKOUT0SRC_NONE: no clock selected - \arg RCU_CKOUT0SRC_CKSYS: system clock selected - \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected - \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected - \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected - \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_EXT1: EXT1 selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_CKPLL2: CK_PLL2 clock selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_CKIRC48M: CK_IRC48M clock selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_CKIRC48M_DIV8: CK_IRC48M/8 clock selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_CKPLLUSB_DIV32: CK_PLLUSB/32 clock selected (available for CL and E508 series) - \param[out] none - \retval none -*/ -void rcu_ckout0_config(uint32_t ckout0_src) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the CKOUT0SRC, set according to ckout0_src */ - reg &= ~RCU_CFG0_CKOUT0SEL; - RCU_CFG0 = (reg | ckout0_src); -} - -/*! - \brief configure the main PLL clock - \param[in] pll_src: PLL clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL - \arg RCU_PLLSRC_HXTAL_IRC48M: HXTAL or IRC48M selected as source clock of PLL - \param[in] pll_mul: PLL clock multiplication factor - only one parameter can be selected which is shown as below: - \arg RCU_PLL_MULx (HD series x = 2..63, CL series x = 2..14, 16..64, 6.5): PLL clock * x - \param[out] none - \retval none -*/ -void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul) -{ - uint32_t reg = 0U; - - reg = RCU_CFG0; - - /* PLL clock source and multiplication factor configuration */ - reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - reg |= (pll_src | pll_mul); - - RCU_CFG0 = reg; -} - -/*! - \brief configure the PLL clock source preselection - \param[in] pll_presel: PLL clock source preselection - only one parameter can be selected which is shown as below: - \arg RCU_PLLPRESRC_HXTAL: HXTAL selected as PREDV0 input source clock - \arg RCU_PLLPRESRC_IRC48M: CK_PLL selected as PREDV0 input source clock - \param[out] none - \retval none -*/ -void rcu_pllpresel_config(uint32_t pll_presel) -{ - uint32_t reg = 0U; - - reg = RCU_CFG1; - - /* PLL clock source preselection */ - reg &= ~RCU_CFG1_PLLPRESEL; - reg |= pll_presel; - - RCU_CFG1 = reg; -} - -#if defined(GD32E50X_HD) -/*! - \brief configure the PREDV0 division factor - \param[in] predv0_div: PREDV0 division factor - \arg RCU_PREDV0_DIVx (x = 1, 2): PREDV0 input source clock is divided x - \param[out] none - \retval none -*/ -void rcu_predv0_config(uint32_t predv0_div) -{ - uint32_t reg = 0U; - - reg = RCU_CFG0; - /* reset PREDV0 bit */ - reg &= ~RCU_CFG0_PREDV0; - if(RCU_PREDV0_DIV2 == predv0_div){ - /* set the PREDV0 bit */ - reg |= RCU_CFG0_PREDV0; - } - - RCU_CFG0 = reg; -} -#elif defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) -/*! - \brief configure the PREDV0 division factor and clock source - \param[in] predv0_source: PREDV0 input clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_PREDV0SRC_HXTAL_IRC48M: HXTAL or IRC48M selected as PREDV0 input source clock - \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock - \param[in] predv0_div: PREDV0 division factor - only one parameter can be selected which is shown as below: - \arg RCU_PREDV0_DIVx (x = 1..16): PREDV0 input source clock is divided x - \param[out] none - \retval none -*/ -void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) -{ - uint32_t reg = 0U; - - reg = RCU_CFG1; - /* reset PREDV0SEL and PREDV0 bits */ - reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0); - /* set the PREDV0SEL and PREDV0 division factor */ - reg |= (predv0_source | predv0_div); - - RCU_CFG1 = reg; -} - -/*! - \brief configure the PREDV1 division factor - \param[in] predv1_div: PREDV1 division factor - only one parameter can be selected which is shown as below: - \arg RCU_PREDV1_DIVx (x = 1..16): PREDV1 input source clock is divided x - \param[out] none - \retval none -*/ -void rcu_predv1_config(uint32_t predv1_div) -{ - uint32_t reg = 0U; - - reg = RCU_CFG1; - /* reset the PREDV1 bits */ - reg &= ~RCU_CFG1_PREDV1; - /* set the PREDV1 division factor */ - reg |= predv1_div; - - RCU_CFG1 = reg; -} - -/*! - \brief configure the PLL1 clock - \param[in] pll_mul: PLL clock multiplication factor - only one parameter can be selected which is shown as below: - \arg RCU_PLL1_MULx (x = 8..14,16,20): PLL1 clock * x - \param[out] none - \retval none -*/ -void rcu_pll1_config(uint32_t pll_mul) -{ - RCU_CFG1 &= ~RCU_CFG1_PLL1MF; - RCU_CFG1 |= pll_mul; -} - -/*! - \brief configure the PLL2 clock - \param[in] pll_mul: PLL clock multiplication factor - only one parameter can be selected which is shown as below: - \arg RCU_PLL2_MULx (x = 8..14,16,20,18..32,40,34..64,80): PLL2 clock * x - \param[out] none - \retval none -*/ -void rcu_pll2_config(uint32_t pll_mul) -{ - RCU_CFG1 &= ~RCU_CFG1_PLL2MF; - RCU_CFG1 |= pll_mul; -} -#endif /* GD32E50X_HD */ - -#if defined(GD32E50X_CL) || defined(GD32E508) -/*! - \brief configure the PLLUSB clock source preselection - \param[in] pllusb_presel: PLLUSB clock source preselection - only one parameter can be selected which is shown as below: - \arg RCU_PLLUSBPRESRC_HXTAL: HXTAL selected as PLLUSB source clock - \arg RCU_PLLUSBPRESRC_IRC48M: IRC48M clock selected as PLLUSB source clock - \param[out] none - \retval none -*/ -void rcu_pllusbpresel_config(uint32_t pllusb_presel) -{ - uint32_t reg = 0U; - - reg = RCU_ADDCFG; - - /* PLLUSB clock source preselection */ - reg &= ~RCU_ADDCFG_PLLUSBPRESEL; - reg |= pllusb_presel; - - RCU_ADDCFG = reg; -} - -/*! - \brief configure the PLLUSBPREDV division factor and clock source - \param[in] pllusbpredv_source: PLLUSBPREDV input clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_PLLUSBPREDVSRC_HXTAL_IRC48M: HXTAL or IRC48M selected as PLLUSBPREDV input source clock - \arg RCU_PLLUSBPREDVSRC_CKPLL1: CK_PLL1 selected as PLLUSBPREDV input source clock - \param[in] pllusbpredv_div: PLLUSBPREDV division factor - only one parameter can be selected which is shown as below: - \arg RCU_PLLUSBPREDV_DIVx (x = 1..15): PLLUSBPREDV input source clock divided by x - \param[out] none - \retval none -*/ -void rcu_pllusbpredv_config(uint32_t pllusbpredv_source, uint32_t pllusbpredv_div) -{ - uint32_t reg = 0U; - - reg = RCU_ADDCFG; - /* reset PLLUSBPRESEL and PLLUSBPREDV bits */ - reg &= ~(RCU_ADDCFG_PLLUSBPREDVSEL | RCU_ADDCFG_PLLUSBPREDV); - /* set the PLLUSBPRESEL and PLLUSBPREDV division factor */ - reg |= (pllusbpredv_source | pllusbpredv_div); - - RCU_ADDCFG = reg; -} - -/*! - \brief configure the PLLUSB clock - \param[in] pllusb_mul: PLLUSB clock multiplication factor - only one parameter can be selected which is shown as below: - \arg RCU_PLLUSB_MULx (x = 16,17..127): PLLUSB source clock multiply by x - \param[out] none - \retval none -*/ -void rcu_pllusb_config(uint32_t pllusb_mul) -{ - RCU_ADDCFG &= ~RCU_ADDCFG_PLLUSBMF; - RCU_ADDCFG |= pllusb_mul; -} - -#endif /* GD32E50X_CL and GD32E508 */ - -/*! - \brief configure the ADC prescaler factor - \param[in] adc_psc: ADC prescaler factor - only one parameter can be selected which is shown as below: - \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2 / 2 - \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2 / 4 - \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2 / 6 - \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2 / 8 - \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2 / 12 - \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2 / 16 - \arg RCU_CKADC_CKAHB_DIV5: ADC prescaler select CK_AHB / 5 - \arg RCU_CKADC_CKAHB_DIV6: ADC prescaler select CK_AHB / 6 - \arg RCU_CKADC_CKAHB_DIV10: ADC prescaler select CK_AHB / 10 - \arg RCU_CKADC_CKAHB_DIV20: ADC prescaler select CK_AHB / 20 - \param[out] none - \retval none -*/ -void rcu_adc_clock_config(uint32_t adc_psc) -{ - uint32_t reg0,reg1; - - /* reset the ADCPSC bits */ - reg0 = RCU_CFG0; - reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC); - reg1 = RCU_CFG1; - reg1 &= ~RCU_CFG1_ADCPSC_3; - - /* set the ADC prescaler factor */ - switch(adc_psc){ - case RCU_CKADC_CKAPB2_DIV2: - case RCU_CKADC_CKAPB2_DIV4: - case RCU_CKADC_CKAPB2_DIV6: - case RCU_CKADC_CKAPB2_DIV8: - reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET); - break; - - case RCU_CKADC_CKAPB2_DIV12: - case RCU_CKADC_CKAPB2_DIV16: - adc_psc &= ~BIT(2); - reg0 |= ((adc_psc << RCU_ADC_PSC_OFFSET) | RCU_CFG0_ADCPSC_2); - break; - - case RCU_CKADC_CKAHB_DIV5: - case RCU_CKADC_CKAHB_DIV6: - case RCU_CKADC_CKAHB_DIV10: - case RCU_CKADC_CKAHB_DIV20: - adc_psc &= ~BITS(2,3); - reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET); - reg1 |= RCU_CFG1_ADCPSC_3; - break; - - default: - break; - } - - /* set the register */ - RCU_CFG0 = reg0; - RCU_CFG1 = reg1; -} - -/*! - \brief configure the USBD/USBHS prescaler factor - \param[in] usb_psc: USB prescaler factor - only one parameter can be selected which is shown as below: - \arg RCU_CKUSB_CKPLL_DIV1_5: USBD / USBHS prescaler select CK_PLL / 1.5 - \arg RCU_CKUSB_CKPLL_DIV1: USBD / USBHS prescaler select CK_PLL / 1 - \arg RCU_CKUSB_CKPLL_DIV2_5: USBD / USBHS prescaler select CK_PLL / 2.5 - \arg RCU_CKUSB_CKPLL_DIV2: USBD / USBHS prescaler select CK_PLL / 2 - \arg RCU_CKUSB_CKPLL_DIV3: USBD / USBHS prescaler select CK_PLL / 3 - \arg RCU_CKUSB_CKPLL_DIV3_5: USBD / USBHS prescaler select CK_PLL / 3.5 - \arg RCU_CKUSB_CKPLL_DIV4: USBD / USBHS prescaler select CK_PLL / 4 - \param[out] none - \retval none -*/ -void rcu_usb_clock_config(uint32_t usb_psc) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* configure the USBD/USBHS prescaler factor */ -#if (defined(GD32E50X_HD) || defined(GD32EPRT)) - reg &= ~RCU_CFG0_USBDPSC; -#elif defined(GD32E50X_CL) || defined(GD32E508) - reg &= ~RCU_CFG0_USBHSPSC; -#endif /* GD32E50X_HD and GD32EPRT */ - - RCU_CFG0 = (reg | usb_psc); -} - -/*! - \brief configure the RTC clock source selection - \param[in] rtc_clock_source: RTC clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_RTCSRC_NONE: no clock selected - \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock - \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock - \arg RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock - \param[out] none - \retval none -*/ -void rcu_rtc_clock_config(uint32_t rtc_clock_source) -{ - uint32_t reg; - - reg = RCU_BDCTL; - /* reset the RTCSRC bits and set according to rtc_clock_source */ - reg &= ~RCU_BDCTL_RTCSRC; - RCU_BDCTL = (reg | rtc_clock_source); -} - -#ifndef GD32EPRT -/*! - \brief configure the SHRTIMER clock source selection - \param[in] shrtimer_clock_source: SHRTIMER clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_SHRTIMERSRC_CKAPB2: APB2 clock selected as SHRTIMER source clock - \arg RCU_SHRTIMERSRC_CKSYS: system clock selected as SHRTIMER source clock - \param[out] none - \retval none -*/ -void rcu_shrtimer_clock_config(uint32_t shrtimer_clock_source) -{ - uint32_t reg; - - reg = RCU_CFG1; - /* reset the I2S1SEL bit and set according to shrtimer_clock_source */ - reg &= ~RCU_CFG1_SHRTIMERSEL; - RCU_CFG1 = (reg | shrtimer_clock_source); -} -#endif /* GD32EPRT */ - -/*! - \brief configure the USART5 clock source selection - \param[in] usart5_clock_source: USART5 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_USART5SRC_CKAPB2: APB2 clock selected as USART5 source clock - \arg RCU_USART5SRC_CKSYS: system clock selected as USART5 source clock - \arg RCU_USART5SRC_LXTAL: LXTAL clock selected as USART5 source clock - \arg RCU_USART5SRC_IRC8M: IRC8M clock selected as USART5 source clock - \param[out] none - \retval none -*/ -void rcu_usart5_clock_config(uint32_t usart5_clock_source) -{ - uint32_t reg; - reg = RCU_CFG2; - /* reset the I2S1SEL bit and set according to usart5_clock_source */ - reg &= ~RCU_CFG2_USART5SEL; - RCU_CFG2 = (reg | usart5_clock_source); -} - -/*! - \brief configure the I2C2 clock source selection - \param[in] i2c2_clock_source: I2C2 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_I2C2SRC_CKAPB1: APB1 clock selected as I2C2 source clock - \arg RCU_I2C2SRC_CKSYS: System clock selected as I2C2 source clock - \arg RCU_I2C2SRCSRC_CKIRC8M: CK_IRC8M clock selected as I2C2 source clock - \param[out] none - \retval none -*/ -void rcu_i2c2_clock_config(uint32_t i2c2_clock_source) -{ - uint32_t reg; - - reg = RCU_CFG2; - /* reset the I2S1SEL bit and set according to i2c2_clock_source */ - reg &= ~RCU_CFG2_I2C2SEL; - RCU_CFG2 = (reg | i2c2_clock_source); -} - -/*! - \brief configure the CK48M clock source selection - \param[in] ck48m_clock_source: CK48M clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_CK48MSRC_CKPLL: CK_PLL selected as CK48M source clock - \arg RCU_CK48MSRC_IRC48M: CK_IRC48M selected as CK48M source clock - \arg RCU_CK48MSRC_CKPLLUSB: (not available for EPRT series): CKPLLUSB selected as CK48M source clock - \arg RCU_CK48MSRC_CKPLL2: CKPLL2 selected as CK48M source clock - \param[out] none - \retval none -*/ -void rcu_ck48m_clock_config(uint32_t ck48m_clock_source) -{ - uint32_t reg; - - reg = RCU_ADDCTL; - /* reset the CK48MSEL bit and set according to ck48m_clock_source */ - reg &= ~RCU_ADDCTL_CK48MSEL; - RCU_ADDCTL = (reg | ck48m_clock_source); -} - -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) -/*! - \brief configure the I2S1 clock source selection - \param[in] i2s_clock_source: I2S1 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_I2S1SRC_CKSYS: system clock selected as I2S1 source clock - \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2 * 2 selected as I2S1 source clock - \param[out] none - \retval none -*/ -void rcu_i2s1_clock_config(uint32_t i2s_clock_source) -{ - uint32_t reg; - - reg = RCU_CFG1; - /* reset the I2S1SEL bit and set according to i2s_clock_source */ - reg &= ~RCU_CFG1_I2S1SEL; - RCU_CFG1 = (reg | i2s_clock_source); -} - -/*! - \brief configure the I2S2 clock source selection - \param[in] i2s_clock_source: I2S2 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock - \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2 * 2 selected as I2S2 source clock - \param[out] none - \retval none -*/ -void rcu_i2s2_clock_config(uint32_t i2s_clock_source) -{ - uint32_t reg; - - reg = RCU_CFG1; - /* reset the I2S2SEL bit and set according to i2s_clock_source */ - reg &= ~RCU_CFG1_I2S2SEL; - RCU_CFG1 = (reg | i2s_clock_source); -} -#endif /* GD32E50X_CL and GD32E50X_EPRT and GD32E508 */ - -#if defined(GD32E50X_CL) || defined(GD32E508) -/*! - \brief configure the USBHSSEL source clock selection - \param[in] usbhssel_clock_source: USBHSSEL clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_USBHSSRC_48M: 48M clock selected as USBHS source clock - \arg RCU_CK48MSRC_60M: 60M clock selected as USBHS source clock - \param[out] none - \retval none -*/ -void rcu_usbhssel_config(uint32_t usbhssel_clock_source) -{ - uint32_t reg = 0U; - - reg = RCU_ADDCTL; - - /* USBHS clock source selection */ - reg &= ~RCU_ADDCTL_USBHSSEL; - reg |= usbhssel_clock_source; - - RCU_ADDCTL = reg; -} - -/*! - \brief configure the USBHSDV division factor - \param[in] usbhs_dv: USBHSDV division factor - only one parameter can be selected which is shown as below: - \arg RCU_USBHSDV_DIV2: USBHSDV input source clock divided by 2 - \arg RCU_USBHSDV_DIV4: USBHSDV input source clock divided by 4 - \arg RCU_USBHSDV_DIV6: USBHSDV input source clock divided by 6 - \arg RCU_USBHSDV_DIV8: USBHSDV input source clock divided by 8 - \arg RCU_USBHSDV_DIV10: USBHSDV input source clock divided by 10 - \arg RCU_USBHSDV_DIV12: USBHSDV input source clock divided by 12 - \arg RCU_USBHSDV_DIV14: USBHSDV input source clock divided by 14 - \arg RCU_USBHSDV_DIV16: USBHSDV input source clock divided by 16 - \param[out] none - \retval none -*/ -void rcu_usbdv_config(uint32_t usbhs_dv) -{ - uint32_t reg = 0U; - - reg = RCU_ADDCTL; - - /* usbhs input clock source division factor */ - reg &= ~RCU_ADDCTL_USBHSDV; - reg |= usbhs_dv; - - RCU_ADDCTL = reg; -} -#endif /* GD32E50X_CL and GD32E508 */ - -/*! - \brief configure the LXTAL drive capability - \param[in] lxtal_dricap: drive capability of LXTAL - only one parameter can be selected which is shown as below: - \arg RCU_LXTAL_LOWDRI: lower driving capability - \arg RCU_LXTAL_MED_LOWDRI: medium low driving capability - \arg RCU_LXTAL_MED_HIGHDRI: medium high driving capability - \arg RCU_LXTAL_HIGHDRI: higher driving capability - \param[out] none - \retval none -*/ -void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap) -{ - uint32_t reg; - - reg = RCU_BDCTL; - - /* reset the LXTALDRI bits and set according to lxtal_dricap */ - reg &= ~RCU_BDCTL_LXTALDRI; - RCU_BDCTL = (reg | lxtal_dricap); -} - -/*! - \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) - \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) - \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) - \arg RCU_PLL_CK: phase locked loop(PLL) - \arg RCU_PLL1_CK: phase locked loop 1(CL, EPRT and E508 series available) - \arg RCU_PLL2_CK: phase locked loop 2(CL, EPRT and E508 series available) - \arg RCU_PLLUSB_CK: phase locked loop USB(CL and E508 series available) - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) -{ - uint32_t stb_cnt = 0U; - ErrStatus reval = ERROR; - FlagStatus osci_stat = RESET; - - switch(osci){ - /* wait HXTAL stable */ - case RCU_HXTAL: - while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){ - reval = SUCCESS; - } - break; - - /* wait LXTAL stable */ - case RCU_LXTAL: - while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){ - reval = SUCCESS; - } - break; - - /* wait IRC8M stable */ - case RCU_IRC8M: - while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){ - reval = SUCCESS; - } - break; - - /* wait IRC48M stable */ - case RCU_IRC48M: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if (RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)){ - reval = SUCCESS; - } - break; - - /* wait IRC40K stable */ - case RCU_IRC40K: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){ - reval = SUCCESS; - } - break; - - /* wait PLL stable */ - case RCU_PLL_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){ - reval = SUCCESS; - } - break; - -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - /* wait PLL1 stable */ - case RCU_PLL1_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){ - reval = SUCCESS; - } - break; - /* wait PLL2 stable */ - case RCU_PLL2_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){ - reval = SUCCESS; - } - break; -#endif /* GD32E50X_CL and GD32E50X_EPRT and GD32E508 */ -#if defined(GD32E50X_CL) || defined(GD32E508) - case RCU_PLLUSB_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_PLLUSBSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLLUSBSTB)){ - reval = SUCCESS; - } - break; -#endif /* GD32E50X_CL and GD32E508 */ - - default: - break; - } - - /* return value */ - return reval; -} - -/*! - \brief turn on the oscillator - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) - \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) - \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) - \arg RCU_PLL_CK: phase locked loop(PLL) - \arg RCU_PLL1_CK: phase locked loop 1(CL, EPRT and E508 series available) - \arg RCU_PLL2_CK: phase locked loop 2(CL, EPRT and E508 series available) - \arg RCU_PLLUSB_CK: phase locked loop USB(CL and E508 series available) - \param[out] none - \retval none -*/ -void rcu_osci_on(rcu_osci_type_enum osci) -{ - RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci)); -} - -/*! - \brief turn off the oscillator - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) - \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) - \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) - \arg RCU_PLL_CK: phase locked loop(PLL) - \arg RCU_PLL1_CK: phase locked loop 1(CL, EPRT and E508 series available) - \arg RCU_PLL2_CK: phase locked loop 2(CL, EPRT and E508 series available) - \arg RCU_PLLUSB_CK: phase locked loop USB(CL and E508 series available) - \param[out] none - \retval none -*/ -void rcu_osci_off(rcu_osci_type_enum osci) -{ - RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci)); -} - -/*! - \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \param[out] none - \retval none -*/ -void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) -{ - uint32_t reg; - - switch(osci){ - /* enable HXTAL to bypass mode */ - case RCU_HXTAL: - reg = RCU_CTL; - RCU_CTL &= ~RCU_CTL_HXTALEN; - RCU_CTL = (reg | RCU_CTL_HXTALBPS); - break; - /* enable LXTAL to bypass mode */ - case RCU_LXTAL: - reg = RCU_BDCTL; - RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; - RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS); - break; - case RCU_IRC8M: - case RCU_IRC48M: - case RCU_IRC40K: - case RCU_PLL_CK: -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - case RCU_PLL1_CK: - case RCU_PLL2_CK: -#endif /* GD32E50X_CL and GD32EPRT and GD32E508 */ - break; - default: - break; - } -} - -/*! - \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \param[out] none - \retval none -*/ -void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) -{ - uint32_t reg; - - switch(osci){ - /* disable HXTAL to bypass mode */ - case RCU_HXTAL: - reg = RCU_CTL; - RCU_CTL &= ~RCU_CTL_HXTALEN; - RCU_CTL = (reg & ~RCU_CTL_HXTALBPS); - break; - /* disable LXTAL to bypass mode */ - case RCU_LXTAL: - reg = RCU_BDCTL; - RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; - RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS); - break; - case RCU_IRC8M: - case RCU_IRC48M: - case RCU_IRC40K: - case RCU_PLL_CK: -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - case RCU_PLL1_CK: - case RCU_PLL2_CK: -#endif /* GD32E50X_CL and GD32EPRT and GD32E508 */ - break; - default: - break; - } -} - -/*! - \brief set the IRC8M adjust value - \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F - \arg 0x00 - 0x1F - \param[out] none - \retval none -*/ -void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval) -{ - uint32_t reg; - - reg = RCU_CTL; - /* reset the IRC8MADJ bits and set according to irc8m_adjval */ - reg &= ~RCU_CTL_IRC8MADJ; - RCU_CTL = (reg | ((irc8m_adjval & RCU_IRC8M_ADJUST_MASK) << RCU_IRC8M_ADJUST_OFFSET)); -} - -/*! - \brief configure the spread spectrum modulation for the main PLL clock - \param[in] spread_spectrum_type: PLL spread spectrum modulation type select - \arg RCU_SS_TYPE_CENTER: center spread type is selected - \arg RCU_SS_TYPE_DOWN: down spread type is selected - \param[in] modstep: configure PLL spread spectrum modulation profile amplitude and frequency - \arg This parameter should be selected between 0 and 7FFF.The following criteria must be met: MODSTEP*MODCNT <=2^15-1 - \param[in] modcnt: configure PLL spread spectrum modulation profile amplitude and frequency - \arg This parameter should be selected between 0 and 1FFF.The following criteria must be met: MODSTEP*MODCNT <=2^15-1 - \param[out] none - \retval none -*/ -void rcu_spread_spectrum_config(uint32_t spread_spectrum_type, uint32_t modstep, uint32_t modcnt) -{ - uint32_t reg; - - reg = RCU_PLLSSCTL; - /* reset the RCU_PLLSSCTL register bits */ - reg &= ~(RCU_PLLSSCTL_MODCNT | RCU_PLLSSCTL_MODSTEP | RCU_PLLSSCTL_SS_TYPE); - RCU_PLLSSCTL = (reg | spread_spectrum_type | modstep << 13 | modcnt); -} - -/*! - \brief enable the PLL spread spectrum modulation - \param[in] none - \param[out] none - \retval none -*/ -void rcu_spread_spectrum_enable(void) -{ - RCU_PLLSSCTL |= RCU_PLLSSCTL_SSCGON; -} - -/*! - \brief disable the PLL spread spectrum modulation - \param[in] none - \param[out] none - \retval none -*/ -void rcu_spread_spectrum_disable(void) -{ - RCU_PLLSSCTL &= ~RCU_PLLSSCTL_SSCGON; -} - -/*! - \brief enable the HXTAL clock monitor - \param[in] none - \param[out] none - \retval none -*/ - -void rcu_hxtal_clock_monitor_enable(void) -{ - RCU_CTL |= RCU_CTL_CKMEN; -} - -/*! - \brief disable the HXTAL clock monitor - \param[in] none - \param[out] none - \retval none -*/ -void rcu_hxtal_clock_monitor_disable(void) -{ - RCU_CTL &= ~RCU_CTL_CKMEN; -} - - -/*! - \brief deep-sleep mode voltage select - \param[in] dsvol: deep sleep mode voltage - only one parameter can be selected which is shown as below: - \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V - \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V - \arg RCU_DEEPSLEEP_V_0_8: the core voltage is 0.8V - \arg RCU_DEEPSLEEP_V_0_7: the core voltage is 0.7V - \param[out] none - \retval none -*/ -void rcu_deepsleep_voltage_set(uint32_t dsvol) -{ - dsvol &= RCU_DSV_DSLPVS; - RCU_DSV = dsvol; -} - -/*! - \brief get the system clock, bus and peripheral clock frequency - \param[in] clock: the clock frequency which to get - only one parameter can be selected which is shown as below: - \arg CK_SYS: system clock frequency - \arg CK_AHB: AHB clock frequency - \arg CK_APB1: APB1 clock frequency - \arg CK_APB2: APB2 clock frequency - \arg CK_USART: USART5 clock frequency - \param[out] none - \retval clock frequency of system, AHB, APB1, APB2 -*/ -uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) -{ - uint32_t sws, ck_freq = 0U; - uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; - uint32_t usart_freq = 0U; - uint32_t pllsel, pllpresel, predv0sel, pllmf,ck_src, idx, clk_exp; -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - uint32_t predv0, predv1, pll1mf; -#endif /* GD32E50X_CL and GD32EPRT and GD32E508*/ - - /* exponent of AHB, APB1 and APB2 clock divider */ - uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; - uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; - uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; - - sws = GET_BITS(RCU_CFG0, 2, 3); - switch(sws){ - /* IRC8M is selected as CK_SYS */ - case SEL_IRC8M: - cksys_freq = IRC8M_VALUE; - break; - /* HXTAL is selected as CK_SYS */ - case SEL_HXTAL: - cksys_freq = HXTAL_VALUE; - break; - /* PLL is selected as CK_SYS */ - case SEL_PLL: - /* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */ - pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); - - if(RCU_PLLSRC_HXTAL_IRC48M == pllsel) { - /* PLL clock source is HXTAL or IRC48M */ - pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL); - - if(RCU_PLLPRESRC_HXTAL == pllpresel){ - /* PLL clock source is HXTAL */ - ck_src = HXTAL_VALUE; - }else{ - /* PLL clock source is IRC48 */ - ck_src = IRC48M_VALUE; - } - -#if defined(GD32E50X_HD) - predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); - /* PREDV0 input source clock divided by 2 */ - if(RCU_CFG0_PREDV0 == predv0sel){ - ck_src = HXTAL_VALUE/2U; - } -#elif defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); - /* source clock use PLL1 */ - if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ - predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> RCU_CFG1_PREDV1_OFFSET) + 1U; - pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> RCU_CFG1_PLL1MF_OFFSET) + 2U; - if(17U == pll1mf){ - pll1mf = 20U; - } - ck_src = (ck_src/predv1)*pll1mf; - } - predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; - ck_src /= predv0; -#endif /* GD32E50X_HD */ - }else{ - /* PLL clock source is IRC8M/2 */ - ck_src = IRC8M_VALUE/2U; - } - - /* PLL multiplication factor */ - pllmf = GET_BITS(RCU_CFG0, 18, 21); - if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ - pllmf |= 0x10U; - } - if((RCU_CFG0 & RCU_CFG0_PLLMF_5)){ - pllmf |= 0x20U; - } - if(pllmf < 15U){ - pllmf += 2U; - }else if((pllmf >= 15U) && (pllmf <= 64U)){ - pllmf += 1U; - }else{ - } - cksys_freq = ck_src*pllmf; -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - if(15U == pllmf){ - cksys_freq = ck_src*6U + ck_src/2U; - } -#endif /* GD32E50X_CL and GD32EPRT and GD32E508 */ - - break; - /* IRC8M is selected as CK_SYS */ - default: - cksys_freq = IRC8M_VALUE; - break; - } - - /* calculate AHB clock frequency */ - idx = GET_BITS(RCU_CFG0, 4, 7); - clk_exp = ahb_exp[idx]; - ahb_freq = cksys_freq >> clk_exp; - - /* calculate APB1 clock frequency */ - idx = GET_BITS(RCU_CFG0, 8, 10); - clk_exp = apb1_exp[idx]; - apb1_freq = ahb_freq >> clk_exp; - - /* calculate APB2 clock frequency */ - idx = GET_BITS(RCU_CFG0, 11, 13); - clk_exp = apb2_exp[idx]; - apb2_freq = ahb_freq >> clk_exp; - - /* return the clocks frequency */ - switch(clock){ - case CK_SYS: - ck_freq = cksys_freq; - break; - case CK_AHB: - ck_freq = ahb_freq; - break; - case CK_APB1: - ck_freq = apb1_freq; - break; - case CK_APB2: - ck_freq = apb2_freq; - break; - case CK_USART: - /* calculate USART5 clock frequency */ - if(RCU_USART5SRC_CKAPB2 == (RCU_CFG2 & RCU_CFG2_USART5SEL)){ - usart_freq = apb2_freq; - }else if(RCU_USART5SRC_CKSYS == (RCU_CFG2 & RCU_CFG2_USART5SEL)){ - usart_freq = cksys_freq; - }else if(RCU_USART5SRC_LXTAL == (RCU_CFG2 & RCU_CFG2_USART5SEL)){ - usart_freq = LXTAL_VALUE; - }else if(RCU_USART5SRC_IRC8M == (RCU_CFG2 & RCU_CFG2_USART5SEL)){ - usart_freq = IRC8M_VALUE; - }else{ - } - ck_freq = usart_freq; - break; - default: - break; - } - return ck_freq; -} - -/*! - \brief get the clock stabilization and periphral reset flags - \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum - only one parameter can be selected which is shown as below: - \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag - \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag - \arg RCU_FLAG_PLLSTB: PLL stabilization flag - \arg RCU_FLAG_PLLUSBSTB: PLLUSB stabilization flag(CL and E508 series available) - \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag(CL, EPRT and E508 series available) - \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag(CL, EPRT and E508 series available) - \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag - \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag - \arg RCU_FLAG_IRC48MSTB: IRC48M stabilization flag - \arg RCU_FLAG_EPRST: external PIN reset flag - \arg RCU_FLAG_PORRST: power reset flag - \arg RCU_FLAG_SWRST: software reset flag - \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag - \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag - \arg RCU_FLAG_LPRST: low-power reset flag - \param[out] none - \retval none -*/ -FlagStatus rcu_flag_get(rcu_flag_enum flag) -{ - /* get the rcu flag */ - if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear all the reset flag - \param[in] none - \param[out] none - \retval none -*/ -void rcu_all_reset_flag_clear(void) -{ - RCU_RSTSCK |= RCU_RSTSCK_RSTFC; -} - -/*! - \brief get the clock stabilization interrupt and ckm flags - \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag - \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag - \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag - \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag - \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag - \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag(CL, EPRT and E508 series available) - \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag(CL, EPRT and E508 series available) - \arg RCU_INT_FLAG_PLLUSBSTB: PLLUSB stabilization interrupt flag(CL and E508 series available) - \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag - \arg RCU_INT_FLAG_IRC48MSTB: IRC48M stabilization interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) -{ - /* get the rcu interrupt flag */ - if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear the interrupt flags - \param[in] int_flag: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear - \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear - \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear - \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear - \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear - \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear(CL, EPRT and E508 series available) - \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear(CL, EPRT and E508 series available) - \arg RCU_INT_FLAG_PLLUSBSTB_CLR: PLLUS stabilization interrupt flag clear(CL and E508 series available) - \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear - \arg RCU_INT_FLAG_IRC48MSTB_CLR: IRC48M stabilization interrupt flag clear - \param[out] none - \retval none -*/ -void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag) -{ - RCU_REG_VAL(int_flag) |= BIT(RCU_BIT_POS(int_flag)); -} - -/*! - \brief enable the stabilization interrupt - \param[in] interrupt clock stabilization interrupt, refer to rcu_int_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable - \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable - \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable - \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable - \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable - \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL, EPRT and E508 series available) - \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL, EPRT and E508 series available) - \arg RCU_INT_PLLUSBSTB: PLLUSB stabilization interrupt enable(CL and E508 series available) - \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable - \param[out] none - \retval none -*/ -void rcu_interrupt_enable(rcu_int_enum interrupt) -{ - RCU_REG_VAL(interrupt) |= BIT(RCU_BIT_POS(interrupt)); -} - -/*! - \brief disable the stabilization interrupt - \param[in] interrupt clock stabilization interrupt, refer to rcu_int_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable - \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable - \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable - \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable - \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable - \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL, EPRT and E508 series available) - \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL, EPRT and E508 series available) - \arg RCU_INT_PLLUSBSTB: PLLUSB stabilization interrupt enable(CL and E508 series available) - \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable - \param[out] none - \retval none -*/ -void rcu_interrupt_disable(rcu_int_enum interrupt) -{ - RCU_REG_VAL(interrupt) &= ~BIT(RCU_BIT_POS(interrupt)); -} \ No newline at end of file diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_rcu.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_rcu.c.base@1.5.0 deleted file mode 100644 index 41a5251..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_rcu.c.base@1.5.0 +++ /dev/null @@ -1,1621 +0,0 @@ -/*! - \file gd32e50x_rcu.c - \brief RCU driver - - \version 2026-02-09, V1.7.0, firmware for GD32E50x -*/ - -/* - Copyright (c) 2025, GigaDevice Semiconductor Inc. - - All rights reserved. - - 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_rcu.h" - -/* define clock source */ -#define SEL_IRC8M ((uint16_t)0U) /* IRC8M is selected as CK_SYS */ -#define SEL_HXTAL ((uint16_t)1U) /* HXTAL is selected as CK_SYS */ -#define SEL_PLL ((uint16_t)2U) /* PLL is selected as CK_SYS */ - -/* define startup timeout count */ -#define OSC_STARTUP_TIMEOUT ((uint32_t)0x000FFFFFU) -#define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x03FFFFFFU) - -/* ADC clock prescaler offset */ -#define RCU_ADC_PSC_OFFSET ((uint32_t)14U) - -/* RCU IRC8M adjust value mask and offset*/ -#define RCU_IRC8M_ADJUST_MASK ((uint8_t)0x1FU) -#define RCU_IRC8M_ADJUST_OFFSET ((uint32_t)3U) - -/* RCU PLL1 clock multiplication factor offset */ -#define RCU_CFG1_PLL1MF_OFFSET ((uint32_t)8U) -/* RCU PREDV1 division factor offset*/ -#define RCU_CFG1_PREDV1_OFFSET ((uint32_t)4U) - -/*! - \brief deinitialize the RCU - \param[in] none - \param[out] none - \retval none -*/ -void rcu_deinit(void) -{ - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - while(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - } - RCU_CFG0 &= ~RCU_CFG0_SCS; - /* reset CTL register */ - RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); - RCU_CTL &= ~RCU_CTL_HXTALBPS; -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); -#endif /* GD32E50X_CL and GD32EPRT and GD32E508 */ - /* reset CFG0 register */ -#if defined(GD32E50X_HD) - RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | - RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF | - RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_PLLMF_4 | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBDPSC_2); -#elif defined(GD32E50X_CL) || defined(GD32E508) - RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | - RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | - RCU_CFG0_USBHSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBHSPSC_2); -#elif defined(GD32EPRT) - RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | - RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | - RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBDPSC_2); -#endif /* GD32E50X_HD */ - - /* reset INT and CFG1 register */ -#if defined(GD32E50X_HD) - RCU_INT = 0x009f0000U; - RCU_CFG1 &= ~(RCU_CFG1_ADCPSC_3 | RCU_CFG1_PLLPRESEL); - RCU_CFG2 &= ~(RCU_CFG2_USART5SEL | RCU_CFG2_I2C2SEL); -#elif defined(GD32E50X_CL) || defined(GD32E508) - RCU_INT = 0x00ff0000U; - RCU_ADDINT = 0x00C00000U; - RCU_ADDCTL &= ~(RCU_ADDCTL_CK48MSEL | RCU_ADDCTL_USBHSSEL | RCU_ADDCTL_USBHSDV | RCU_ADDCTL_USBSWEN | RCU_ADDCTL_PLLUSBEN | RCU_ADDCTL_IRC48MEN); - RCU_ADDCFG &= ~(RCU_ADDCFG_PLLUSBPREDV | RCU_ADDCFG_PLLUSBPRESEL | RCU_ADDCFG_PLLUSBPREDVSEL | RCU_ADDCFG_PLLUSBMF); - - RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF | - RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL | RCU_CFG1_SHRTIMERSEL | RCU_CFG1_PLL2MF_5 | RCU_CFG1_ADCPSC_3 | - RCU_CFG1_PLLPRESEL | RCU_CFG1_PLL2MF_4); - RCU_CFG2 &= ~(RCU_CFG2_USART5SEL | RCU_CFG2_I2C2SEL); -#elif defined(GD32EPRT) - RCU_INT = 0x00ff0000U; - RCU_ADDINT &= ~ (RCU_ADDINT_IRC48MSTBIC); - RCU_ADDCTL &= ~(RCU_ADDCTL_CK48MSEL | RCU_ADDCTL_IRC48MEN); - - RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF | - RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL | RCU_CFG1_PLL2MF_5 | RCU_CFG1_ADCPSC_3 | - RCU_CFG1_PLLPRESEL | RCU_CFG1_PLL2MF_4); - RCU_CFG2 &= ~(RCU_CFG2_USART5SEL | RCU_CFG2_I2C2SEL); - -#endif /* GD32E50X_HD */ -} - -/*! - \brief enable the peripherals clock - \param[in] periph: RCU peripherals, refer to rcu_periph_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOx (x = A,B,C,D,E,F,G): GPIO ports clock - \arg RCU_AF : alternate function clock - \arg RCU_CRC: CRC clock - \arg RCU_DMAx (x = 0,1): DMA clock - \arg RCU_ENET: ENET clock(EPRT and CL series available) - \arg RCU_ENETTX: ENETTX clock(EPRT and CL series available) - \arg RCU_ENETRX: ENETRX clock(EPRT and CL series available) - \arg RCU_USBD: USBD clock(HD and EPRT series available) - \arg RCU_USBHS: USBHS clock(CL series available) - \arg RCU_TMU: TMU clock - \arg RCU_SQPI: SQPI clock - \arg RCU_EXMC: EXMC clock - \arg RCU_TIMERx (x = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): TIMER clock - \arg RCU_WWDGT: WWDGT clock - \arg RCU_SPIx (x = 0,1,2): SPI clock - \arg RCU_USARTx (x = 0,1,2,5): USART clock - \arg RCU_UARTx (x = 3,4): UART clock - \arg RCU_I2Cx (x = 0,1,2): I2C clock - \arg RCU_CANx (x = 0,1,2,CAN2 is only available for CL series,CANx is not avaliable for GD32EPRT): CAN clock - \arg RCU_PMU: PMU clock - \arg RCU_DAC: DAC clock - \arg RCU_RTC: RTC clock - \arg RCU_ADCx (x = 0,1,2, ADC2 is not available for CL series): ADC clock - \arg RCU_SDIO: SDIO clock(not available for CL and EPRT series) - \arg RCU_CTC: CTC clock - \arg RCU_BKPI: BKP interface clock - \arg RCU_SHRTIMER: (not available for EPRT series):SHRTIMER clock - \arg RCU_CMP(CMP is only available for CL series):CMP clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_enable(rcu_periph_enum periph) -{ - RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief disable the peripherals clock - \param[in] periph: RCU peripherals, refer to rcu_periph_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOx (x = A,B,C,D,E,F,G): GPIO ports clock - \arg RCU_AF : alternate function clock - \arg RCU_CRC: CRC clock - \arg RCU_DMAx (x =0,1): DMA clock - \arg RCU_ENET: ENET clock(EPRT and CL series available) - \arg RCU_ENETTX: ENETTX clock(EPRT and CL series available) - \arg RCU_ENETRX: ENETRX clock(EPRT and CL series available) - \arg RCU_USBD: USBD clock(HD and EPRT series available) - \arg RCU_USBHS: USBHS clock(CL series available) - \arg RCU_TMU: TMU clock - \arg RCU_SQPI: SQPI clock - \arg RCU_EXMC: EXMC clock - \arg RCU_TIMERx (x = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): TIMER clock - \arg RCU_WWDGT: WWDGT clock - \arg RCU_SPIx (x = 0,1,2): SPI clock - \arg RCU_USARTx (x = 0,1,2,5): USART clock - \arg RCU_UARTx (x = 3,4): UART clock - \arg RCU_I2Cx (x = 0,1,2): I2C clock - \arg RCU_CANx (x = 0,1,2,CAN2 is only available for CL series,CANx is not avaliable for GD32EPRT): CAN clock - \arg RCU_PMU: PMU clock - \arg RCU_DAC: DAC clock - \arg RCU_RTC: RTC clock - \arg RCU_ADCx (x = 0,1,2,ADC2 is not available for CL series): ADC clock - \arg RCU_SDIO: SDIO clock(not available for CL and EPRT series) - \arg RCU_CTC: CTC clock - \arg RCU_BKPI: BKP interface clock - \arg RCU_SHRTIMER: (not available for EPRT series): SHRTIMER clock - \arg RCU_CMP(CMP is only available for CL series):CMP clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_disable(rcu_periph_enum periph) -{ - RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief enable the peripherals clock when sleep mode - \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum - only one parameter can be selected which is shown as below: - \arg RCU_FMC_SLP: FMC clock - \arg RCU_SRAM_SLP: SRAM clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph) -{ - RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief disable the peripherals clock when sleep mode - \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum - only one parameter can be selected which is shown as below: - \arg RCU_SRAM_SLP: SRAM clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) -{ - RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief reset the peripherals - \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOxRST (x = A,B,C,D,E,F,G): reset GPIO ports - \arg RCU_AFRST : reset alternate function clock - \arg RCU_ENETRST: reset ENET(EPRT and CL series available) - \arg RCU_USBDRST: reset USBD(HD and EPRT series available) - \arg RCU_USBHSRST: reset USBHS(CL series available) - \arg RCU_TMURST: reset TMU - \arg RCU_SQPIRST: reset SQPI - \arg RCU_TIMERxRST (x = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): reset TIMER - \arg RCU_WWDGTRST: reset WWDGT - \arg RCU_SPIxRST (x = 0,1,2): reset SPI - \arg RCU_USARTxRST (x = 0,1,2,5): reset USART - \arg RCU_UARTxRST (x = 3,4): reset UART - \arg RCU_I2CxRST (x = 0,1): reset I2C - \arg RCU_PMURST: reset PMU - \arg RCU_DACRST: reset DAC - \arg RCU_ADCRST (x = 0,1,2,ADC2 is not available for CL series): reset ADC - \arg RCU_CTCRST: reset CTC - \arg RCU_BKPIRST: reset BKPI - \arg RCU_SHRTIMERRST: (not available for EPRT series):reset SHRTIMERRST - \arg RCU_CMPRST(CMP is only available for CL series): reset CMP - \param[out] none - \retval none -*/ -void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) -{ - RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset)); -} - -/*! - \brief disable reset the peripheral - \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOxRST (x = A,B,C,D,E,F,G): reset GPIO ports - \arg RCU_AFRST : reset alternate function clock - \arg RCU_ENETRST: reset ENET(CL series available) - \arg RCU_USBDRST: reset USBD(HD and EPRT series available) - \arg RCU_USBHSRST: reset USBHS(CL series available) - \arg RCU_TMURST: reset TMU - \arg RCU_SQPIRST: reset SQPI - \arg RCU_TIMERxRST (x = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): reset TIMER - \arg RCU_WWDGTRST: reset WWDGT - \arg RCU_SPIxRST (x = 0,1,2): reset SPI - \arg RCU_USARTxRST (x = 0,1,2,5): reset USART - \arg RCU_UARTxRST (x = 3,4): reset UART - \arg RCU_I2CxRST (x = 0,1): reset I2C - \arg RCU_PMURST: reset PMU - \arg RCU_DACRST: reset DAC - \arg RCU_ADCRST (x = 0,1,2,ADC2 is not available for CL series): reset ADC - \arg RCU_CTCRST: reset CTC - \arg RCU_BKPIRST: reset BKPI - \arg RCU_SHRTIMERRST: (not available for EPRT series):reset SHRTIMERRST - \arg RCU_CMPRST(CMP is only available for CL series): reset CMP - \param[out] none - \retval none -*/ -void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset) -{ - RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset)); -} - -/*! - \brief reset the BKP domain - \param[in] none - \param[out] none - \retval none -*/ -void rcu_bkp_reset_enable(void) -{ - RCU_BDCTL |= RCU_BDCTL_BKPRST; -} - -/*! - \brief disable the BKP domain reset - \param[in] none - \param[out] none - \retval none -*/ -void rcu_bkp_reset_disable(void) -{ - RCU_BDCTL &= ~RCU_BDCTL_BKPRST; -} - -/*! - \brief configure the system clock source - \param[in] ck_sys: system clock source select - only one parameter can be selected which is shown as below: - \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source - \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source - \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source - \param[out] none - \retval none -*/ -void rcu_system_clock_source_config(uint32_t ck_sys) -{ - uint32_t reg; - - reg = RCU_CFG0; - /* reset the SCS bits and set according to ck_sys */ - reg &= ~RCU_CFG0_SCS; - RCU_CFG0 = (reg | ck_sys); -} - -/*! - \brief get the system clock source - \param[in] none - \param[out] none - \retval which clock is selected as CK_SYS source - \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source - \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source - \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source -*/ -uint32_t rcu_system_clock_source_get(void) -{ - return (RCU_CFG0 & RCU_CFG0_SCSS); -} - -/*! - \brief configure the AHB clock prescaler selection - \param[in] ck_ahb: AHB clock prescaler selection - only one parameter can be selected which is shown as below: - \arg RCU_AHB_CKSYS_DIVx (x = 1, 2, 4, 8, 16, 64, 128, 256, 512): select CK_SYS / x as CK_AHB - \param[out] none - \retval none -*/ -void rcu_ahb_clock_config(uint32_t ck_ahb) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the AHBPSC bits and set according to ck_ahb */ - reg &= ~RCU_CFG0_AHBPSC; - RCU_CFG0 = (reg | ck_ahb); -} - -/*! - \brief configure the APB1 clock prescaler selection - \param[in] ck_apb1: APB1 clock prescaler selection - only one parameter can be selected which is shown as below: - \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1 - \arg RCU_APB1_CKAHB_DIV2: select CK_AHB / 2 as CK_APB1 - \arg RCU_APB1_CKAHB_DIV4: select CK_AHB / 4 as CK_APB1 - \arg RCU_APB1_CKAHB_DIV8: select CK_AHB / 8 as CK_APB1 - \arg RCU_APB1_CKAHB_DIV16: select CK_AHB / 16 as CK_APB1 - \param[out] none - \retval none -*/ -void rcu_apb1_clock_config(uint32_t ck_apb1) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the APB1PSC and set according to ck_apb1 */ - reg &= ~RCU_CFG0_APB1PSC; - RCU_CFG0 = (reg | ck_apb1); -} - -/*! - \brief configure the APB2 clock prescaler selection - \param[in] ck_apb2: APB2 clock prescaler selection - only one parameter can be selected which is shown as below: - \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2 - \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2 - \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2 - \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2 - \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2 - \param[out] none - \retval none -*/ -void rcu_apb2_clock_config(uint32_t ck_apb2) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the APB2PSC and set according to ck_apb2 */ - reg &= ~RCU_CFG0_APB2PSC; - RCU_CFG0 = (reg | ck_apb2); -} - -/*! - \brief configure the CK_OUT0 clock source - \param[in] ckout0_src: CK_OUT0 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_CKOUT0SRC_NONE: no clock selected - \arg RCU_CKOUT0SRC_CKSYS: system clock selected - \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected - \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected - \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected - \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_EXT1: EXT1 selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_CKPLL2: CK_PLL2 clock selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_CKIRC48M: CK_IRC48M clock selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_CKIRC48M_DIV8: CK_IRC48M/8 clock selected (available for CL、EPRT and E508 series) - \arg RCU_CKOUT0SRC_CKPLLUSB_DIV32: CK_PLLUSB/32 clock selected (available for CL and E508 series) - \param[out] none - \retval none -*/ -void rcu_ckout0_config(uint32_t ckout0_src) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the CKOUT0SRC, set according to ckout0_src */ - reg &= ~RCU_CFG0_CKOUT0SEL; - RCU_CFG0 = (reg | ckout0_src); -} - -/*! - \brief configure the main PLL clock - \param[in] pll_src: PLL clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL - \arg RCU_PLLSRC_HXTAL_IRC48M: HXTAL or IRC48M selected as source clock of PLL - \param[in] pll_mul: PLL clock multiplication factor - only one parameter can be selected which is shown as below: - \arg RCU_PLL_MULx (HD series x = 2..63, CL series x = 2..14, 16..64, 6.5): PLL clock * x - \param[out] none - \retval none -*/ -void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul) -{ - uint32_t reg = 0U; - - reg = RCU_CFG0; - - /* PLL clock source and multiplication factor configuration */ - reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - reg |= (pll_src | pll_mul); - - RCU_CFG0 = reg; -} - -/*! - \brief configure the PLL clock source preselection - \param[in] pll_presel: PLL clock source preselection - only one parameter can be selected which is shown as below: - \arg RCU_PLLPRESRC_HXTAL: HXTAL selected as PREDV0 input source clock - \arg RCU_PLLPRESRC_IRC48M: CK_PLL selected as PREDV0 input source clock - \param[out] none - \retval none -*/ -void rcu_pllpresel_config(uint32_t pll_presel) -{ - uint32_t reg = 0U; - - reg = RCU_CFG1; - - /* PLL clock source preselection */ - reg &= ~RCU_CFG1_PLLPRESEL; - reg |= pll_presel; - - RCU_CFG1 = reg; -} - -#if defined(GD32E50X_HD) -/*! - \brief configure the PREDV0 division factor - \param[in] predv0_div: PREDV0 division factor - \arg RCU_PREDV0_DIVx (x = 1, 2): PREDV0 input source clock is divided x - \param[out] none - \retval none -*/ -void rcu_predv0_config(uint32_t predv0_div) -{ - uint32_t reg = 0U; - - reg = RCU_CFG0; - /* reset PREDV0 bit */ - reg &= ~RCU_CFG0_PREDV0; - if(RCU_PREDV0_DIV2 == predv0_div){ - /* set the PREDV0 bit */ - reg |= RCU_CFG0_PREDV0; - } - - RCU_CFG0 = reg; -} -#elif defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) -/*! - \brief configure the PREDV0 division factor and clock source - \param[in] predv0_source: PREDV0 input clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_PREDV0SRC_HXTAL_IRC48M: HXTAL or IRC48M selected as PREDV0 input source clock - \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock - \param[in] predv0_div: PREDV0 division factor - only one parameter can be selected which is shown as below: - \arg RCU_PREDV0_DIVx (x = 1..16): PREDV0 input source clock is divided x - \param[out] none - \retval none -*/ -void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) -{ - uint32_t reg = 0U; - - reg = RCU_CFG1; - /* reset PREDV0SEL and PREDV0 bits */ - reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0); - /* set the PREDV0SEL and PREDV0 division factor */ - reg |= (predv0_source | predv0_div); - - RCU_CFG1 = reg; -} - -/*! - \brief configure the PREDV1 division factor - \param[in] predv1_div: PREDV1 division factor - only one parameter can be selected which is shown as below: - \arg RCU_PREDV1_DIVx (x = 1..16): PREDV1 input source clock is divided x - \param[out] none - \retval none -*/ -void rcu_predv1_config(uint32_t predv1_div) -{ - uint32_t reg = 0U; - - reg = RCU_CFG1; - /* reset the PREDV1 bits */ - reg &= ~RCU_CFG1_PREDV1; - /* set the PREDV1 division factor */ - reg |= predv1_div; - - RCU_CFG1 = reg; -} - -/*! - \brief configure the PLL1 clock - \param[in] pll_mul: PLL clock multiplication factor - only one parameter can be selected which is shown as below: - \arg RCU_PLL1_MULx (x = 8..14,16,20): PLL1 clock * x - \param[out] none - \retval none -*/ -void rcu_pll1_config(uint32_t pll_mul) -{ - RCU_CFG1 &= ~RCU_CFG1_PLL1MF; - RCU_CFG1 |= pll_mul; -} - -/*! - \brief configure the PLL2 clock - \param[in] pll_mul: PLL clock multiplication factor - only one parameter can be selected which is shown as below: - \arg RCU_PLL2_MULx (x = 8..14,16,20,18..32,40,34..64,80): PLL2 clock * x - \param[out] none - \retval none -*/ -void rcu_pll2_config(uint32_t pll_mul) -{ - RCU_CFG1 &= ~RCU_CFG1_PLL2MF; - RCU_CFG1 |= pll_mul; -} -#endif /* GD32E50X_HD */ - -#if defined(GD32E50X_CL) || defined(GD32E508) -/*! - \brief configure the PLLUSB clock source preselection - \param[in] pllusb_presel: PLLUSB clock source preselection - only one parameter can be selected which is shown as below: - \arg RCU_PLLUSBPRESRC_HXTAL: HXTAL selected as PLLUSB source clock - \arg RCU_PLLUSBPRESRC_IRC48M: IRC48M clock selected as PLLUSB source clock - \param[out] none - \retval none -*/ -void rcu_pllusbpresel_config(uint32_t pllusb_presel) -{ - uint32_t reg = 0U; - - reg = RCU_ADDCFG; - - /* PLLUSB clock source preselection */ - reg &= ~RCU_ADDCFG_PLLUSBPRESEL; - reg |= pllusb_presel; - - RCU_ADDCFG = reg; -} - -/*! - \brief configure the PLLUSBPREDV division factor and clock source - \param[in] pllusbpredv_source: PLLUSBPREDV input clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_PLLUSBPREDVSRC_HXTAL_IRC48M: HXTAL or IRC48M selected as PLLUSBPREDV input source clock - \arg RCU_PLLUSBPREDVSRC_CKPLL1: CK_PLL1 selected as PLLUSBPREDV input source clock - \param[in] pllusbpredv_div: PLLUSBPREDV division factor - only one parameter can be selected which is shown as below: - \arg RCU_PLLUSBPREDV_DIVx (x = 1..15): PLLUSBPREDV input source clock divided by x - \param[out] none - \retval none -*/ -void rcu_pllusbpredv_config(uint32_t pllusbpredv_source, uint32_t pllusbpredv_div) -{ - uint32_t reg = 0U; - - reg = RCU_ADDCFG; - /* reset PLLUSBPRESEL and PLLUSBPREDV bits */ - reg &= ~(RCU_ADDCFG_PLLUSBPREDVSEL | RCU_ADDCFG_PLLUSBPREDV); - /* set the PLLUSBPRESEL and PLLUSBPREDV division factor */ - reg |= (pllusbpredv_source | pllusbpredv_div); - - RCU_ADDCFG = reg; -} - -/*! - \brief configure the PLLUSB clock - \param[in] pllusb_mul: PLLUSB clock multiplication factor - only one parameter can be selected which is shown as below: - \arg RCU_PLLUSB_MULx (x = 16,17..127): PLLUSB source clock multiply by x - \param[out] none - \retval none -*/ -void rcu_pllusb_config(uint32_t pllusb_mul) -{ - RCU_ADDCFG &= ~RCU_ADDCFG_PLLUSBMF; - RCU_ADDCFG |= pllusb_mul; -} - -#endif /* GD32E50X_CL and GD32E508 */ - -/*! - \brief configure the ADC prescaler factor - \param[in] adc_psc: ADC prescaler factor - only one parameter can be selected which is shown as below: - \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2 / 2 - \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2 / 4 - \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2 / 6 - \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2 / 8 - \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2 / 12 - \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2 / 16 - \arg RCU_CKADC_CKAHB_DIV5: ADC prescaler select CK_AHB / 5 - \arg RCU_CKADC_CKAHB_DIV6: ADC prescaler select CK_AHB / 6 - \arg RCU_CKADC_CKAHB_DIV10: ADC prescaler select CK_AHB / 10 - \arg RCU_CKADC_CKAHB_DIV20: ADC prescaler select CK_AHB / 20 - \param[out] none - \retval none -*/ -void rcu_adc_clock_config(uint32_t adc_psc) -{ - uint32_t reg0,reg1; - - /* reset the ADCPSC bits */ - reg0 = RCU_CFG0; - reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC); - reg1 = RCU_CFG1; - reg1 &= ~RCU_CFG1_ADCPSC_3; - - /* set the ADC prescaler factor */ - switch(adc_psc){ - case RCU_CKADC_CKAPB2_DIV2: - case RCU_CKADC_CKAPB2_DIV4: - case RCU_CKADC_CKAPB2_DIV6: - case RCU_CKADC_CKAPB2_DIV8: - reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET); - break; - - case RCU_CKADC_CKAPB2_DIV12: - case RCU_CKADC_CKAPB2_DIV16: - adc_psc &= ~BIT(2); - reg0 |= ((adc_psc << RCU_ADC_PSC_OFFSET) | RCU_CFG0_ADCPSC_2); - break; - - case RCU_CKADC_CKAHB_DIV5: - case RCU_CKADC_CKAHB_DIV6: - case RCU_CKADC_CKAHB_DIV10: - case RCU_CKADC_CKAHB_DIV20: - adc_psc &= ~BITS(2,3); - reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET); - reg1 |= RCU_CFG1_ADCPSC_3; - break; - - default: - break; - } - - /* set the register */ - RCU_CFG0 = reg0; - RCU_CFG1 = reg1; -} - -/*! - \brief configure the USBD/USBHS prescaler factor - \param[in] usb_psc: USB prescaler factor - only one parameter can be selected which is shown as below: - \arg RCU_CKUSB_CKPLL_DIV1_5: USBD / USBHS prescaler select CK_PLL / 1.5 - \arg RCU_CKUSB_CKPLL_DIV1: USBD / USBHS prescaler select CK_PLL / 1 - \arg RCU_CKUSB_CKPLL_DIV2_5: USBD / USBHS prescaler select CK_PLL / 2.5 - \arg RCU_CKUSB_CKPLL_DIV2: USBD / USBHS prescaler select CK_PLL / 2 - \arg RCU_CKUSB_CKPLL_DIV3: USBD / USBHS prescaler select CK_PLL / 3 - \arg RCU_CKUSB_CKPLL_DIV3_5: USBD / USBHS prescaler select CK_PLL / 3.5 - \arg RCU_CKUSB_CKPLL_DIV4: USBD / USBHS prescaler select CK_PLL / 4 - \param[out] none - \retval none -*/ -void rcu_usb_clock_config(uint32_t usb_psc) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* configure the USBD/USBHS prescaler factor */ -#if (defined(GD32E50X_HD) || defined(GD32EPRT)) - reg &= ~RCU_CFG0_USBDPSC; -#elif defined(GD32E50X_CL) || defined(GD32E508) - reg &= ~RCU_CFG0_USBHSPSC; -#endif /* GD32E50X_HD and GD32EPRT */ - - RCU_CFG0 = (reg | usb_psc); -} - -/*! - \brief configure the RTC clock source selection - \param[in] rtc_clock_source: RTC clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_RTCSRC_NONE: no clock selected - \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock - \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock - \arg RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock - \param[out] none - \retval none -*/ -void rcu_rtc_clock_config(uint32_t rtc_clock_source) -{ - uint32_t reg; - - reg = RCU_BDCTL; - /* reset the RTCSRC bits and set according to rtc_clock_source */ - reg &= ~RCU_BDCTL_RTCSRC; - RCU_BDCTL = (reg | rtc_clock_source); -} - -#ifndef GD32EPRT -/*! - \brief configure the SHRTIMER clock source selection - \param[in] shrtimer_clock_source: SHRTIMER clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_SHRTIMERSRC_CKAPB2: APB2 clock selected as SHRTIMER source clock - \arg RCU_SHRTIMERSRC_CKSYS: system clock selected as SHRTIMER source clock - \param[out] none - \retval none -*/ -void rcu_shrtimer_clock_config(uint32_t shrtimer_clock_source) -{ - uint32_t reg; - - reg = RCU_CFG1; - /* reset the I2S1SEL bit and set according to shrtimer_clock_source */ - reg &= ~RCU_CFG1_SHRTIMERSEL; - RCU_CFG1 = (reg | shrtimer_clock_source); -} -#endif /* GD32EPRT */ - -/*! - \brief configure the USART5 clock source selection - \param[in] usart5_clock_source: USART5 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_USART5SRC_CKAPB2: APB2 clock selected as USART5 source clock - \arg RCU_USART5SRC_CKSYS: system clock selected as USART5 source clock - \arg RCU_USART5SRC_LXTAL: LXTAL clock selected as USART5 source clock - \arg RCU_USART5SRC_IRC8M: IRC8M clock selected as USART5 source clock - \param[out] none - \retval none -*/ -void rcu_usart5_clock_config(uint32_t usart5_clock_source) -{ - uint32_t reg; - reg = RCU_CFG2; - /* reset the I2S1SEL bit and set according to usart5_clock_source */ - reg &= ~RCU_CFG2_USART5SEL; - RCU_CFG2 = (reg | usart5_clock_source); -} - -/*! - \brief configure the I2C2 clock source selection - \param[in] i2c2_clock_source: I2C2 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_I2C2SRC_CKAPB1: APB1 clock selected as I2C2 source clock - \arg RCU_I2C2SRC_CKSYS: System clock selected as I2C2 source clock - \arg RCU_I2C2SRCSRC_CKIRC8M: CK_IRC8M clock selected as I2C2 source clock - \param[out] none - \retval none -*/ -void rcu_i2c2_clock_config(uint32_t i2c2_clock_source) -{ - uint32_t reg; - - reg = RCU_CFG2; - /* reset the I2S1SEL bit and set according to i2c2_clock_source */ - reg &= ~RCU_CFG2_I2C2SEL; - RCU_CFG2 = (reg | i2c2_clock_source); -} - -/*! - \brief configure the CK48M clock source selection - \param[in] ck48m_clock_source: CK48M clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_CK48MSRC_CKPLL: CK_PLL selected as CK48M source clock - \arg RCU_CK48MSRC_IRC48M: CK_IRC48M selected as CK48M source clock - \arg RCU_CK48MSRC_CKPLLUSB: (not available for EPRT series): CKPLLUSB selected as CK48M source clock - \arg RCU_CK48MSRC_CKPLL2: CKPLL2 selected as CK48M source clock - \param[out] none - \retval none -*/ -void rcu_ck48m_clock_config(uint32_t ck48m_clock_source) -{ - uint32_t reg; - - reg = RCU_ADDCTL; - /* reset the CK48MSEL bit and set according to ck48m_clock_source */ - reg &= ~RCU_ADDCTL_CK48MSEL; - RCU_ADDCTL = (reg | ck48m_clock_source); -} - -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) -/*! - \brief configure the I2S1 clock source selection - \param[in] i2s_clock_source: I2S1 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_I2S1SRC_CKSYS: system clock selected as I2S1 source clock - \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2 * 2 selected as I2S1 source clock - \param[out] none - \retval none -*/ -void rcu_i2s1_clock_config(uint32_t i2s_clock_source) -{ - uint32_t reg; - - reg = RCU_CFG1; - /* reset the I2S1SEL bit and set according to i2s_clock_source */ - reg &= ~RCU_CFG1_I2S1SEL; - RCU_CFG1 = (reg | i2s_clock_source); -} - -/*! - \brief configure the I2S2 clock source selection - \param[in] i2s_clock_source: I2S2 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock - \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2 * 2 selected as I2S2 source clock - \param[out] none - \retval none -*/ -void rcu_i2s2_clock_config(uint32_t i2s_clock_source) -{ - uint32_t reg; - - reg = RCU_CFG1; - /* reset the I2S2SEL bit and set according to i2s_clock_source */ - reg &= ~RCU_CFG1_I2S2SEL; - RCU_CFG1 = (reg | i2s_clock_source); -} -#endif /* GD32E50X_CL and GD32E50X_EPRT and GD32E508 */ - -#if defined(GD32E50X_CL) || defined(GD32E508) -/*! - \brief configure the USBHSSEL source clock selection - \param[in] usbhssel_clock_source: USBHSSEL clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_USBHSSRC_48M: 48M clock selected as USBHS source clock - \arg RCU_CK48MSRC_60M: 60M clock selected as USBHS source clock - \param[out] none - \retval none -*/ -void rcu_usbhssel_config(uint32_t usbhssel_clock_source) -{ - uint32_t reg = 0U; - - reg = RCU_ADDCTL; - - /* USBHS clock source selection */ - reg &= ~RCU_ADDCTL_USBHSSEL; - reg |= usbhssel_clock_source; - - RCU_ADDCTL = reg; -} - -/*! - \brief configure the USBHSDV division factor - \param[in] usbhs_dv: USBHSDV division factor - only one parameter can be selected which is shown as below: - \arg RCU_USBHSDV_DIV2: USBHSDV input source clock divided by 2 - \arg RCU_USBHSDV_DIV4: USBHSDV input source clock divided by 4 - \arg RCU_USBHSDV_DIV6: USBHSDV input source clock divided by 6 - \arg RCU_USBHSDV_DIV8: USBHSDV input source clock divided by 8 - \arg RCU_USBHSDV_DIV10: USBHSDV input source clock divided by 10 - \arg RCU_USBHSDV_DIV12: USBHSDV input source clock divided by 12 - \arg RCU_USBHSDV_DIV14: USBHSDV input source clock divided by 14 - \arg RCU_USBHSDV_DIV16: USBHSDV input source clock divided by 16 - \param[out] none - \retval none -*/ -void rcu_usbdv_config(uint32_t usbhs_dv) -{ - uint32_t reg = 0U; - - reg = RCU_ADDCTL; - - /* usbhs input clock source division factor */ - reg &= ~RCU_ADDCTL_USBHSDV; - reg |= usbhs_dv; - - RCU_ADDCTL = reg; -} -#endif /* GD32E50X_CL and GD32E508 */ - -/*! - \brief configure the LXTAL drive capability - \param[in] lxtal_dricap: drive capability of LXTAL - only one parameter can be selected which is shown as below: - \arg RCU_LXTAL_LOWDRI: lower driving capability - \arg RCU_LXTAL_MED_LOWDRI: medium low driving capability - \arg RCU_LXTAL_MED_HIGHDRI: medium high driving capability - \arg RCU_LXTAL_HIGHDRI: higher driving capability - \param[out] none - \retval none -*/ -void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap) -{ - uint32_t reg; - - reg = RCU_BDCTL; - - /* reset the LXTALDRI bits and set according to lxtal_dricap */ - reg &= ~RCU_BDCTL_LXTALDRI; - RCU_BDCTL = (reg | lxtal_dricap); -} - -/*! - \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) - \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) - \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) - \arg RCU_PLL_CK: phase locked loop(PLL) - \arg RCU_PLL1_CK: phase locked loop 1(CL, EPRT and E508 series available) - \arg RCU_PLL2_CK: phase locked loop 2(CL, EPRT and E508 series available) - \arg RCU_PLLUSB_CK: phase locked loop USB(CL and E508 series available) - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) -{ - uint32_t stb_cnt = 0U; - ErrStatus reval = ERROR; - FlagStatus osci_stat = RESET; - - switch(osci){ - /* wait HXTAL stable */ - case RCU_HXTAL: - while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){ - reval = SUCCESS; - } - break; - - /* wait LXTAL stable */ - case RCU_LXTAL: - while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){ - reval = SUCCESS; - } - break; - - /* wait IRC8M stable */ - case RCU_IRC8M: - while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){ - reval = SUCCESS; - } - break; - - /* wait IRC48M stable */ - case RCU_IRC48M: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if (RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)){ - reval = SUCCESS; - } - break; - - /* wait IRC40K stable */ - case RCU_IRC40K: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){ - reval = SUCCESS; - } - break; - - /* wait PLL stable */ - case RCU_PLL_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){ - reval = SUCCESS; - } - break; - -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - /* wait PLL1 stable */ - case RCU_PLL1_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){ - reval = SUCCESS; - } - break; - /* wait PLL2 stable */ - case RCU_PLL2_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){ - reval = SUCCESS; - } - break; -#endif /* GD32E50X_CL and GD32E50X_EPRT and GD32E508 */ -#if defined(GD32E50X_CL) || defined(GD32E508) - case RCU_PLLUSB_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ - osci_stat = rcu_flag_get(RCU_FLAG_PLLUSBSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLLUSBSTB)){ - reval = SUCCESS; - } - break; -#endif /* GD32E50X_CL and GD32E508 */ - - default: - break; - } - - /* return value */ - return reval; -} - -/*! - \brief turn on the oscillator - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) - \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) - \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) - \arg RCU_PLL_CK: phase locked loop(PLL) - \arg RCU_PLL1_CK: phase locked loop 1(CL, EPRT and E508 series available) - \arg RCU_PLL2_CK: phase locked loop 2(CL, EPRT and E508 series available) - \arg RCU_PLLUSB_CK: phase locked loop USB(CL and E508 series available) - \param[out] none - \retval none -*/ -void rcu_osci_on(rcu_osci_type_enum osci) -{ - RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci)); -} - -/*! - \brief turn off the oscillator - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) - \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) - \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) - \arg RCU_PLL_CK: phase locked loop(PLL) - \arg RCU_PLL1_CK: phase locked loop 1(CL, EPRT and E508 series available) - \arg RCU_PLL2_CK: phase locked loop 2(CL, EPRT and E508 series available) - \arg RCU_PLLUSB_CK: phase locked loop USB(CL and E508 series available) - \param[out] none - \retval none -*/ -void rcu_osci_off(rcu_osci_type_enum osci) -{ - RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci)); -} - -/*! - \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \param[out] none - \retval none -*/ -void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) -{ - uint32_t reg; - - switch(osci){ - /* enable HXTAL to bypass mode */ - case RCU_HXTAL: - reg = RCU_CTL; - RCU_CTL &= ~RCU_CTL_HXTALEN; - RCU_CTL = (reg | RCU_CTL_HXTALBPS); - break; - /* enable LXTAL to bypass mode */ - case RCU_LXTAL: - reg = RCU_BDCTL; - RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; - RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS); - break; - case RCU_IRC8M: - case RCU_IRC48M: - case RCU_IRC40K: - case RCU_PLL_CK: -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - case RCU_PLL1_CK: - case RCU_PLL2_CK: -#endif /* GD32E50X_CL and GD32EPRT and GD32E508 */ - break; - default: - break; - } -} - -/*! - \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \param[out] none - \retval none -*/ -void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) -{ - uint32_t reg; - - switch(osci){ - /* disable HXTAL to bypass mode */ - case RCU_HXTAL: - reg = RCU_CTL; - RCU_CTL &= ~RCU_CTL_HXTALEN; - RCU_CTL = (reg & ~RCU_CTL_HXTALBPS); - break; - /* disable LXTAL to bypass mode */ - case RCU_LXTAL: - reg = RCU_BDCTL; - RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; - RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS); - break; - case RCU_IRC8M: - case RCU_IRC48M: - case RCU_IRC40K: - case RCU_PLL_CK: -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - case RCU_PLL1_CK: - case RCU_PLL2_CK: -#endif /* GD32E50X_CL and GD32EPRT and GD32E508 */ - break; - default: - break; - } -} - -/*! - \brief set the IRC8M adjust value - \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F - \arg 0x00 - 0x1F - \param[out] none - \retval none -*/ -void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval) -{ - uint32_t reg; - - reg = RCU_CTL; - /* reset the IRC8MADJ bits and set according to irc8m_adjval */ - reg &= ~RCU_CTL_IRC8MADJ; - RCU_CTL = (reg | ((irc8m_adjval & RCU_IRC8M_ADJUST_MASK) << RCU_IRC8M_ADJUST_OFFSET)); -} - -/*! - \brief configure the spread spectrum modulation for the main PLL clock - \param[in] spread_spectrum_type: PLL spread spectrum modulation type select - \arg RCU_SS_TYPE_CENTER: center spread type is selected - \arg RCU_SS_TYPE_DOWN: down spread type is selected - \param[in] modstep: configure PLL spread spectrum modulation profile amplitude and frequency - \arg This parameter should be selected between 0 and 7FFF.The following criteria must be met: MODSTEP*MODCNT <=2^15-1 - \param[in] modcnt: configure PLL spread spectrum modulation profile amplitude and frequency - \arg This parameter should be selected between 0 and 1FFF.The following criteria must be met: MODSTEP*MODCNT <=2^15-1 - \param[out] none - \retval none -*/ -void rcu_spread_spectrum_config(uint32_t spread_spectrum_type, uint32_t modstep, uint32_t modcnt) -{ - uint32_t reg; - - reg = RCU_PLLSSCTL; - /* reset the RCU_PLLSSCTL register bits */ - reg &= ~(RCU_PLLSSCTL_MODCNT | RCU_PLLSSCTL_MODSTEP | RCU_PLLSSCTL_SS_TYPE); - RCU_PLLSSCTL = (reg | spread_spectrum_type | modstep << 13 | modcnt); -} - -/*! - \brief enable the PLL spread spectrum modulation - \param[in] none - \param[out] none - \retval none -*/ -void rcu_spread_spectrum_enable(void) -{ - RCU_PLLSSCTL |= RCU_PLLSSCTL_SSCGON; -} - -/*! - \brief disable the PLL spread spectrum modulation - \param[in] none - \param[out] none - \retval none -*/ -void rcu_spread_spectrum_disable(void) -{ - RCU_PLLSSCTL &= ~RCU_PLLSSCTL_SSCGON; -} - -/*! - \brief enable the HXTAL clock monitor - \param[in] none - \param[out] none - \retval none -*/ - -void rcu_hxtal_clock_monitor_enable(void) -{ - RCU_CTL |= RCU_CTL_CKMEN; -} - -/*! - \brief disable the HXTAL clock monitor - \param[in] none - \param[out] none - \retval none -*/ -void rcu_hxtal_clock_monitor_disable(void) -{ - RCU_CTL &= ~RCU_CTL_CKMEN; -} - - -/*! - \brief deep-sleep mode voltage select - \param[in] dsvol: deep sleep mode voltage - only one parameter can be selected which is shown as below: - \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V - \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V - \arg RCU_DEEPSLEEP_V_0_8: the core voltage is 0.8V - \arg RCU_DEEPSLEEP_V_0_7: the core voltage is 0.7V - \param[out] none - \retval none -*/ -void rcu_deepsleep_voltage_set(uint32_t dsvol) -{ - dsvol &= RCU_DSV_DSLPVS; - RCU_DSV = dsvol; -} - -/*! - \brief get the system clock, bus and peripheral clock frequency - \param[in] clock: the clock frequency which to get - only one parameter can be selected which is shown as below: - \arg CK_SYS: system clock frequency - \arg CK_AHB: AHB clock frequency - \arg CK_APB1: APB1 clock frequency - \arg CK_APB2: APB2 clock frequency - \arg CK_USART: USART5 clock frequency - \param[out] none - \retval clock frequency of system, AHB, APB1, APB2 -*/ -uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) -{ - uint32_t sws, ck_freq = 0U; - uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; - uint32_t usart_freq = 0U; - uint32_t pllsel, pllpresel, predv0sel, pllmf,ck_src, idx, clk_exp; -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - uint32_t predv0, predv1, pll1mf; -#endif /* GD32E50X_CL and GD32EPRT and GD32E508*/ - - /* exponent of AHB, APB1 and APB2 clock divider */ - uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; - uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; - uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; - - sws = GET_BITS(RCU_CFG0, 2, 3); - switch(sws){ - /* IRC8M is selected as CK_SYS */ - case SEL_IRC8M: - cksys_freq = IRC8M_VALUE; - break; - /* HXTAL is selected as CK_SYS */ - case SEL_HXTAL: - cksys_freq = HXTAL_VALUE; - break; - /* PLL is selected as CK_SYS */ - case SEL_PLL: - /* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */ - pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); - - if(RCU_PLLSRC_HXTAL_IRC48M == pllsel) { - /* PLL clock source is HXTAL or IRC48M */ - pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL); - - if(RCU_PLLPRESRC_HXTAL == pllpresel){ - /* PLL clock source is HXTAL */ - ck_src = HXTAL_VALUE; - }else{ - /* PLL clock source is IRC48 */ - ck_src = IRC48M_VALUE; - } - -#if defined(GD32E50X_HD) - predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); - /* PREDV0 input source clock divided by 2 */ - if(RCU_CFG0_PREDV0 == predv0sel){ - ck_src = HXTAL_VALUE/2U; - } -#elif defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); - /* source clock use PLL1 */ - if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ - predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> RCU_CFG1_PREDV1_OFFSET) + 1U; - pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> RCU_CFG1_PLL1MF_OFFSET) + 2U; - if(17U == pll1mf){ - pll1mf = 20U; - } - ck_src = (ck_src/predv1)*pll1mf; - } - predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; - ck_src /= predv0; -#endif /* GD32E50X_HD */ - }else{ - /* PLL clock source is IRC8M/2 */ - ck_src = IRC8M_VALUE/2U; - } - - /* PLL multiplication factor */ - pllmf = GET_BITS(RCU_CFG0, 18, 21); - if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ - pllmf |= 0x10U; - } - if((RCU_CFG0 & RCU_CFG0_PLLMF_5)){ - pllmf |= 0x20U; - } - if(pllmf < 15U){ - pllmf += 2U; - }else if((pllmf >= 15U) && (pllmf <= 64U)){ - pllmf += 1U; - }else{ - } - cksys_freq = ck_src*pllmf; -#if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508) - if(15U == pllmf){ - cksys_freq = ck_src*6U + ck_src/2U; - } -#endif /* GD32E50X_CL and GD32EPRT and GD32E508 */ - - break; - /* IRC8M is selected as CK_SYS */ - default: - cksys_freq = IRC8M_VALUE; - break; - } - - /* calculate AHB clock frequency */ - idx = GET_BITS(RCU_CFG0, 4, 7); - clk_exp = ahb_exp[idx]; - ahb_freq = cksys_freq >> clk_exp; - - /* calculate APB1 clock frequency */ - idx = GET_BITS(RCU_CFG0, 8, 10); - clk_exp = apb1_exp[idx]; - apb1_freq = ahb_freq >> clk_exp; - - /* calculate APB2 clock frequency */ - idx = GET_BITS(RCU_CFG0, 11, 13); - clk_exp = apb2_exp[idx]; - apb2_freq = ahb_freq >> clk_exp; - - /* return the clocks frequency */ - switch(clock){ - case CK_SYS: - ck_freq = cksys_freq; - break; - case CK_AHB: - ck_freq = ahb_freq; - break; - case CK_APB1: - ck_freq = apb1_freq; - break; - case CK_APB2: - ck_freq = apb2_freq; - break; - case CK_USART: - /* calculate USART5 clock frequency */ - if(RCU_USART5SRC_CKAPB2 == (RCU_CFG2 & RCU_CFG2_USART5SEL)){ - usart_freq = apb2_freq; - }else if(RCU_USART5SRC_CKSYS == (RCU_CFG2 & RCU_CFG2_USART5SEL)){ - usart_freq = cksys_freq; - }else if(RCU_USART5SRC_LXTAL == (RCU_CFG2 & RCU_CFG2_USART5SEL)){ - usart_freq = LXTAL_VALUE; - }else if(RCU_USART5SRC_IRC8M == (RCU_CFG2 & RCU_CFG2_USART5SEL)){ - usart_freq = IRC8M_VALUE; - }else{ - } - ck_freq = usart_freq; - break; - default: - break; - } - return ck_freq; -} - -/*! - \brief get the clock stabilization and periphral reset flags - \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum - only one parameter can be selected which is shown as below: - \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag - \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag - \arg RCU_FLAG_PLLSTB: PLL stabilization flag - \arg RCU_FLAG_PLLUSBSTB: PLLUSB stabilization flag(CL and E508 series available) - \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag(CL, EPRT and E508 series available) - \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag(CL, EPRT and E508 series available) - \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag - \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag - \arg RCU_FLAG_IRC48MSTB: IRC48M stabilization flag - \arg RCU_FLAG_EPRST: external PIN reset flag - \arg RCU_FLAG_PORRST: power reset flag - \arg RCU_FLAG_SWRST: software reset flag - \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag - \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag - \arg RCU_FLAG_LPRST: low-power reset flag - \param[out] none - \retval none -*/ -FlagStatus rcu_flag_get(rcu_flag_enum flag) -{ - /* get the rcu flag */ - if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear all the reset flag - \param[in] none - \param[out] none - \retval none -*/ -void rcu_all_reset_flag_clear(void) -{ - RCU_RSTSCK |= RCU_RSTSCK_RSTFC; -} - -/*! - \brief get the clock stabilization interrupt and ckm flags - \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag - \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag - \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag - \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag - \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag - \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag(CL, EPRT and E508 series available) - \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag(CL, EPRT and E508 series available) - \arg RCU_INT_FLAG_PLLUSBSTB: PLLUSB stabilization interrupt flag(CL and E508 series available) - \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag - \arg RCU_INT_FLAG_IRC48MSTB: IRC48M stabilization interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) -{ - /* get the rcu interrupt flag */ - if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear the interrupt flags - \param[in] int_flag: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear - \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear - \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear - \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear - \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear - \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear(CL, EPRT and E508 series available) - \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear(CL, EPRT and E508 series available) - \arg RCU_INT_FLAG_PLLUSBSTB_CLR: PLLUS stabilization interrupt flag clear(CL and E508 series available) - \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear - \arg RCU_INT_FLAG_IRC48MSTB_CLR: IRC48M stabilization interrupt flag clear - \param[out] none - \retval none -*/ -void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag) -{ - RCU_REG_VAL(int_flag) |= BIT(RCU_BIT_POS(int_flag)); -} - -/*! - \brief enable the stabilization interrupt - \param[in] interrupt clock stabilization interrupt, refer to rcu_int_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable - \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable - \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable - \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable - \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable - \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL, EPRT and E508 series available) - \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL, EPRT and E508 series available) - \arg RCU_INT_PLLUSBSTB: PLLUSB stabilization interrupt enable(CL and E508 series available) - \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable - \param[out] none - \retval none -*/ -void rcu_interrupt_enable(rcu_int_enum interrupt) -{ - RCU_REG_VAL(interrupt) |= BIT(RCU_BIT_POS(interrupt)); -} - -/*! - \brief disable the stabilization interrupt - \param[in] interrupt clock stabilization interrupt, refer to rcu_int_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable - \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable - \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable - \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable - \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable - \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL, EPRT and E508 series available) - \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL, EPRT and E508 series available) - \arg RCU_INT_PLLUSBSTB: PLLUSB stabilization interrupt enable(CL and E508 series available) - \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable - \param[out] none - \retval none -*/ -void rcu_interrupt_disable(rcu_int_enum interrupt) -{ - RCU_REG_VAL(interrupt) &= ~BIT(RCU_BIT_POS(interrupt)); -} \ No newline at end of file diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_timer.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_timer.c deleted file mode 100644 index 9a53c16..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_timer.c +++ /dev/null @@ -1,2039 +0,0 @@ -/*! - \file gd32e50x_timer.c - \brief TIMER 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_timer.h" - -/* TIMER init parameter mask */ -#define ALIGNEDMODE_MASK ((uint32_t)0x00000060U) /*!< TIMER init parameter aligne dmode mask */ -#define COUNTERDIRECTION_MASK ((uint32_t)0x00000010U) /*!< TIMER init parameter counter direction mask */ -#define CLOCKDIVISION_MASK ((uint32_t)0x00000300U) /*!< TIMER init parameter clock division value mask */ - -/*! - \brief deinit a TIMER - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_deinit(uint32_t timer_periph) -{ - switch(timer_periph){ - case TIMER0: - /* reset TIMER0 */ - rcu_periph_reset_enable(RCU_TIMER0RST); - rcu_periph_reset_disable(RCU_TIMER0RST); - break; - case TIMER1: - /* reset TIMER1 */ - rcu_periph_reset_enable(RCU_TIMER1RST); - rcu_periph_reset_disable(RCU_TIMER1RST); - break; - case TIMER2: - /* reset TIMER2 */ - rcu_periph_reset_enable(RCU_TIMER2RST); - rcu_periph_reset_disable(RCU_TIMER2RST); - break; - case TIMER3: - /* reset TIMER3 */ - rcu_periph_reset_enable(RCU_TIMER3RST); - rcu_periph_reset_disable(RCU_TIMER3RST); - break; - case TIMER4: - /* reset TIMER4 */ - rcu_periph_reset_enable(RCU_TIMER4RST); - rcu_periph_reset_disable(RCU_TIMER4RST); - break; - case TIMER5: - /* reset TIMER5 */ - rcu_periph_reset_enable(RCU_TIMER5RST); - rcu_periph_reset_disable(RCU_TIMER5RST); - break; - case TIMER6: - /* reset TIMER6 */ - rcu_periph_reset_enable(RCU_TIMER6RST); - rcu_periph_reset_disable(RCU_TIMER6RST); - break; - case TIMER7: - /* reset TIMER7 */ - rcu_periph_reset_enable(RCU_TIMER7RST); - rcu_periph_reset_disable(RCU_TIMER7RST); - break; -#ifndef GD32EPRT - case TIMER8: - /* reset TIMER8 */ - rcu_periph_reset_enable(RCU_TIMER8RST); - rcu_periph_reset_disable(RCU_TIMER8RST); - break; - case TIMER9: - /* reset TIMER9 */ - rcu_periph_reset_enable(RCU_TIMER9RST); - rcu_periph_reset_disable(RCU_TIMER9RST); - break; - case TIMER10: - /* reset TIMER10 */ - rcu_periph_reset_enable(RCU_TIMER10RST); - rcu_periph_reset_disable(RCU_TIMER10RST); - break; - case TIMER11: - /* reset TIMER11 */ - rcu_periph_reset_enable(RCU_TIMER11RST); - rcu_periph_reset_disable(RCU_TIMER11RST); - break; - case TIMER12: - /* reset TIMER12 */ - rcu_periph_reset_enable(RCU_TIMER12RST); - rcu_periph_reset_disable(RCU_TIMER12RST); - break; - case TIMER13: - /* reset TIMER13 */ - rcu_periph_reset_enable(RCU_TIMER13RST); - rcu_periph_reset_disable(RCU_TIMER13RST); - break; -#endif /* GD32EPRT */ - default: - break; - } -} - -/*! - \brief initialize TIMER init parameter struct with a default value - \param[in] initpara: init parameter struct - \param[out] none - \retval none -*/ -void timer_struct_para_init(timer_parameter_struct* initpara) -{ - /* initialize the init parameter struct member with the default value */ - initpara->prescaler = 0U; - initpara->alignedmode = TIMER_COUNTER_EDGE; - initpara->counterdirection = TIMER_COUNTER_UP; - initpara->period = 65535U; - initpara->clockdivision = TIMER_CKDIV_DIV1; - initpara->repetitioncounter = 0U; -} - -/*! - \brief initialize TIMER counter - \param[in] timer_periph: TIMERx(x=0..13) - \param[in] initpara: init parameter struct - prescaler: prescaler value of the counter clock, 0~65535 - alignedmode: TIMER_COUNTER_EDGE, TIMER_COUNTER_CENTER_DOWN, TIMER_COUNTER_CENTER_UP, TIMER_COUNTER_CENTER_BOTH - counterdirection: TIMER_COUNTER_UP, TIMER_COUNTER_DOWN - period: counter auto reload value, 0~65535 - clockdivision: TIMER_CKDIV_DIV1, TIMER_CKDIV_DIV2, TIMER_CKDIV_DIV4 - repetitioncounter: counter repetition value, 0~255 - \param[out] none - \retval none -*/ -void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) -{ - /* configure the counter prescaler value */ - TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler; - - /* configure the counter direction and aligned mode */ - if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) - || (TIMER3 == timer_periph) || (TIMER4 == timer_periph) || (TIMER7 == timer_periph)){ - TIMER_CTL0(timer_periph) &= (~(uint32_t)(TIMER_CTL0_DIR | TIMER_CTL0_CAM)); - TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->alignedmode & ALIGNEDMODE_MASK); - TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->counterdirection & COUNTERDIRECTION_MASK); - } - - /* configure the autoreload value */ - TIMER_CAR(timer_periph) = (uint32_t)initpara->period; - - if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){ - /* reset the CKDIV bit */ - TIMER_CTL0(timer_periph) &= (~(uint32_t)TIMER_CTL0_CKDIV); - TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->clockdivision & CLOCKDIVISION_MASK); - } - - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ - /* configure the repetition counter value */ - TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter; - } - - /* generate an update event */ - TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; -} - -/*! - \brief enable a TIMER - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_enable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_CEN; -} - -/*! - \brief disable a TIMER - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_disable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CEN; -} - -/*! - \brief enable the auto reload shadow function - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_auto_reload_shadow_enable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_ARSE; -} - -/*! - \brief disable the auto reload shadow function - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_auto_reload_shadow_disable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_ARSE; -} - -/*! - \brief enable the update event - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_update_event_enable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPDIS; -} - -/*! - \brief disable the update event - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_update_event_disable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) |= (uint32_t) TIMER_CTL0_UPDIS; -} - -/*! - \brief set TIMER counter alignment mode - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] aligned: - only one parameter can be selected which is shown as below: - \arg TIMER_COUNTER_EDGE: edge-aligned mode - \arg TIMER_COUNTER_CENTER_DOWN: center-aligned and counting down assert mode - \arg TIMER_COUNTER_CENTER_UP: center-aligned and counting up assert mode - \arg TIMER_COUNTER_CENTER_BOTH: center-aligned and counting up/down assert mode - \param[out] none - \retval none -*/ -void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned) -{ - TIMER_CTL0(timer_periph) &= (uint32_t)(~TIMER_CTL0_CAM); - TIMER_CTL0(timer_periph) |= (uint32_t)aligned; -} - -/*! - \brief set TIMER counter up direction - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_counter_up_direction(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_DIR; -} - -/*! - \brief set TIMER counter down direction - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_counter_down_direction(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_DIR; -} - -/*! - \brief configure TIMER prescaler - \param[in] timer_periph: TIMERx(x=0..13) - \param[in] prescaler: prescaler value,0~65535 - \param[in] pscreload: prescaler reload mode - only one parameter can be selected which is shown as below: - \arg TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now - \arg TIMER_PSC_RELOAD_UPDATE: the prescaler is loaded at the next update event - \param[out] none - \retval none -*/ -void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload) -{ - TIMER_PSC(timer_periph) = (uint32_t)prescaler; - - if(TIMER_PSC_RELOAD_NOW == pscreload){ - TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; - } -} - -/*! - \brief configure TIMER repetition register value - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] repetition: the counter repetition value, 0~255 - \param[out] none - \retval none -*/ -void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition) -{ - TIMER_CREP(timer_periph) = (uint32_t)repetition; -} - -/*! - \brief configure TIMER autoreload register value - \param[in] timer_periph: TIMERx(x=0..13) - \param[in] autoreload: the counter auto-reload value,0~65535 - \param[out] none - \retval none -*/ -void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload) -{ - TIMER_CAR(timer_periph) = (uint32_t)autoreload; -} - -/*! - \brief configure TIMER counter register value - \param[in] timer_periph: TIMERx(x=0..13) - \param[in] counter: the counter value,0~65535 - \param[out] none - \retval none -*/ -void timer_counter_value_config(uint32_t timer_periph, uint32_t counter) -{ - TIMER_CNT(timer_periph) = (uint32_t)counter; -} - -/*! - \brief read TIMER counter value - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval counter value -*/ -uint32_t timer_counter_read(uint32_t timer_periph) -{ - uint32_t count_value = 0U; - count_value = TIMER_CNT(timer_periph); - return (count_value); -} - -/*! - \brief read TIMER prescaler value - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval prescaler register value -*/ -uint16_t timer_prescaler_read(uint32_t timer_periph) -{ - uint16_t prescaler_value = 0U; - prescaler_value = (uint16_t)(TIMER_PSC(timer_periph)); - return (prescaler_value); -} - -/*! - \brief configure TIMER single pulse mode - \param[in] timer_periph: TIMERx(x=0..8,11) - \param[in] spmode: - only one parameter can be selected which is shown as below: - \arg TIMER_SP_MODE_SINGLE: single pulse mode - \arg TIMER_SP_MODE_REPETITIVE: repetitive pulse mode - \param[out] none - \retval none -*/ -void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) -{ - if(TIMER_SP_MODE_SINGLE == spmode){ - TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM; - }else if(TIMER_SP_MODE_REPETITIVE == spmode){ - TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM); - }else{ - /* illegal parameters */ - } -} - -/*! - \brief configure TIMER update source - \param[in] timer_periph: TIMERx(x=0..13) - \param[in] update: - only one parameter can be selected which is shown as below: - \arg TIMER_UPDATE_SRC_GLOBAL: update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger - \arg TIMER_UPDATE_SRC_REGULAR: update generate only by counter overflow/underflow - \param[out] none - \retval none -*/ -void timer_update_source_config(uint32_t timer_periph, uint32_t update) -{ - if(TIMER_UPDATE_SRC_REGULAR == update){ - TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS; - }else if(TIMER_UPDATE_SRC_GLOBAL == update){ - TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief enable the TIMER DMA - \param[in] timer_periph: please refer to the following parameters - \param[in] dma: specify which DMA to enable - only one parameter can be selected which is shown as below: - \arg TIMER_DMA_UPD: update DMA enable,TIMERx(x=0..7) - \arg TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH1D: channel 1 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH2D: channel 2 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH3D: channel 3 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CMTD: commutation DMA request enable,TIMERx(x=0,7) - \arg TIMER_DMA_TRGD: trigger DMA enable,TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_dma_enable(uint32_t timer_periph, uint16_t dma) -{ - TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; -} - -/*! - \brief disable the TIMER DMA - \param[in] timer_periph: please refer to the following parameters - \param[in] dma: specify which DMA to enable - one or more parameters can be selected which are shown as below: - \arg TIMER_DMA_UPD: update DMA ,TIMERx(x=0..7) - \arg TIMER_DMA_CH0D: channel 0 DMA request,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH1D: channel 1 DMA request,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH2D: channel 2 DMA request,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH3D: channel 3 DMA request,TIMERx(x=0..4,7) - \arg TIMER_DMA_CMTD: commutation DMA request ,TIMERx(x=0,7) - \arg TIMER_DMA_TRGD: trigger DMA request,TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_dma_disable(uint32_t timer_periph, uint16_t dma) -{ - TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); -} - -/*! - \brief channel DMA request source selection - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] dma_request: channel DMA request source selection - only one parameter can be selected which is shown as below: - \arg TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel y is sent when channel y event occurs - \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs - \param[out] none - \retval none -*/ -void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request) -{ - if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){ - TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS; - }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){ - TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief configure the TIMER DMA transfer - \param[in] timer_periph: please refer to the following parameters - \param[in] dma_baseaddr: - only one parameter can be selected which is shown as below: - \arg TIMER_DMACFG_DMATA_CTL0: DMA transfer address is TIMER_CTL0,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CTL1: DMA transfer address is TIMER_CTL1,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_SMCFG: DMA transfer address is TIMER_SMCFG,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_DMAINTEN: DMA transfer address is TIMER_DMAINTEN,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_INTF: DMA transfer address is TIMER_INTF,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_SWEVG: DMA transfer address is TIMER_SWEVG,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CHCTL0: DMA transfer address is TIMER_CHCTL0,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CHCTL1: DMA transfer address is TIMER_CHCTL1,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CHCTL2: DMA transfer address is TIMER_CHCTL2,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CNT: DMA transfer address is TIMER_CNT,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_PSC: DMA transfer address is TIMER_PSC,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CAR: DMA transfer address is TIMER_CAR,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CREP: DMA transfer address is TIMER_CREP,TIMERx(x=0,7) - \arg TIMER_DMACFG_DMATA_CH0CV: DMA transfer address is TIMER_CH0CV,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CH1CV: DMA transfer address is TIMER_CH1CV,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CH2CV: DMA transfer address is TIMER_CH2CV,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CH3CV: DMA transfer address is TIMER_CH3CV,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP,TIMERx(x=0,7) - \arg TIMER_DMACFG_DMATA_DMACFG: DMA transfer address is TIMER_DMACFG,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_DMATB: DMA transfer address is TIMER_DMATB,TIMERx(x=0..4,7) - \param[in] dma_lenth: - only one parameter can be selected which is shown as below: - \arg TIMER_DMACFG_DMATC_xTRANSFER(x=1..18): DMA transfer x time - \param[out] none - \retval none -*/ -void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth) -{ - TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); - TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth); -} - -/*! - \brief software generate events - \param[in] timer_periph: please refer to the following parameters - \param[in] event: the timer software event generation sources - one or more parameters can be selected which are shown as below: - \arg TIMER_EVENT_SRC_UPG: update event,TIMERx(x=0..13) - \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation,TIMERx(x=0..4,7..13) - \arg TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation,TIMERx(x=0..4,7,8,11) - \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation,TIMERx(x=0..4,7) - \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation,TIMERx(x=0..4,7) - \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation,TIMERx(x=0,7) - \arg TIMER_EVENT_SRC_TRGG: trigger event generation,TIMERx(x=0..4,7,8,11) - \arg TIMER_EVENT_SRC_BRKG: break event generation,TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_event_software_generate(uint32_t timer_periph, uint16_t event) -{ - TIMER_SWEVG(timer_periph) |= (uint32_t)event; -} - -/*! - \brief initialize TIMER break parameter struct with a default value - \param[in] breakpara: TIMER break parameter struct - \param[out] none - \retval none -*/ -void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) -{ - /* initialize the break parameter struct member with the default value */ - breakpara->runoffstate = TIMER_ROS_STATE_DISABLE; - breakpara->ideloffstate = TIMER_IOS_STATE_DISABLE; - breakpara->deadtime = 0U; - breakpara->breakpolarity = TIMER_BREAK_POLARITY_LOW; - breakpara->outputautostate = TIMER_OUTAUTO_DISABLE; - breakpara->protectmode = TIMER_CCHP_PROT_OFF; - breakpara->breakstate = TIMER_BREAK_DISABLE; -} - -/*! - \brief configure TIMER break function - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] breakpara: TIMER break parameter struct - runoffstate: TIMER_ROS_STATE_ENABLE,TIMER_ROS_STATE_DISABLE - ideloffstate: TIMER_IOS_STATE_ENABLE,TIMER_IOS_STATE_DISABLE - deadtime: 0~255 - breakpolarity: TIMER_BREAK_POLARITY_LOW,TIMER_BREAK_POLARITY_HIGH - outputautostate: TIMER_OUTAUTO_ENABLE,TIMER_OUTAUTO_DISABLE - protectmode: TIMER_CCHP_PROT_OFF,TIMER_CCHP_PROT_0,TIMER_CCHP_PROT_1,TIMER_CCHP_PROT_2 - breakstate: TIMER_BREAK_ENABLE,TIMER_BREAK_DISABLE - \param[out] none - \retval none -*/ -void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara) -{ - TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate))| - ((uint32_t)(breakpara->ideloffstate))| - ((uint32_t)(breakpara->deadtime))| - ((uint32_t)(breakpara->breakpolarity))| - ((uint32_t)(breakpara->outputautostate)) | - ((uint32_t)(breakpara->protectmode))| - ((uint32_t)(breakpara->breakstate))) ; -} - -/*! - \brief enable TIMER break function - \param[in] timer_periph: TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_break_enable(uint32_t timer_periph) -{ - TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_BRKEN; -} - -/*! - \brief disable TIMER break function - \param[in] timer_periph: TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_break_disable(uint32_t timer_periph) -{ - TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_BRKEN; -} - -/*! - \brief enable TIMER output automatic function - \param[in] timer_periph: TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_automatic_output_enable(uint32_t timer_periph) -{ - TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_OAEN; -} - -/*! - \brief disable TIMER output automatic function - \param[in] timer_periph: TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_automatic_output_disable(uint32_t timer_periph) -{ - TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_OAEN; -} - -/*! - \brief configure TIMER primary output function - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue) -{ - if(ENABLE == newvalue){ - TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN; - }else{ - TIMER_CCHP(timer_periph) &= (~(uint32_t)TIMER_CCHP_POEN); - } -} - -/*! - \brief enable or disable channel capture/compare control shadow register - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue) -{ - if(ENABLE == newvalue){ - TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE; - }else{ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCSE); - } -} - -/*! - \brief configure TIMER channel control shadow register update control - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] ccuctl: channel control shadow register update control - only one parameter can be selected which is shown as below: - \arg TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set - \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs - \param[out] none - \retval none -*/ -void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl) -{ - if(TIMER_UPDATECTL_CCU == ccuctl){ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC); - }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){ - TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief initialize TIMER channel output parameter struct with a default value - \param[in] ocpara: TIMER channel n output parameter struct - \param[out] none - \retval none -*/ -void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) -{ - /* initialize the channel output parameter struct member with the default value */ - ocpara->outputstate = TIMER_CCX_DISABLE; - ocpara->outputnstate = TIMER_CCXN_DISABLE; - ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH; - ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH; - ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW; - ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; -} - -/*! - \brief configure TIMER channel output function - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) - \param[in] ocpara: TIMER channeln output parameter struct - outputstate: TIMER_CCX_ENABLE,TIMER_CCX_DISABLE - outputnstate: TIMER_CCXN_ENABLE,TIMER_CCXN_DISABLE - ocpolarity: TIMER_OC_POLARITY_HIGH,TIMER_OC_POLARITY_LOW - ocnpolarity: TIMER_OCN_POLARITY_HIGH,TIMER_OCN_POLARITY_LOW - ocidlestate: TIMER_OC_IDLE_STATE_LOW,TIMER_OC_IDLE_STATE_HIGH - ocnidlestate: TIMER_OCN_IDLE_STATE_LOW,TIMER_OCN_IDLE_STATE_HIGH - \param[out] none - \retval none -*/ -void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - /* reset the CH0EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS; - /* set the CH0EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputstate; - /* reset the CH0P bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); - /* set the CH0P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity; - - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ - /* reset the CH0NEN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); - /* set the CH0NEN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputnstate; - /* reset the CH0NP bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); - /* set the CH0NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocnpolarity; - /* reset the ISO0 bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0); - /* set the ISO0 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocidlestate; - /* reset the ISO0N bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0N); - /* set the ISO0N bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocnidlestate; - } - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - /* reset the CH1EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS; - /* set the CH1EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 4U); - /* reset the CH1P bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); - /* set the CH1P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 4U); - - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ - /* reset the CH1NEN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); - /* set the CH1NEN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 4U); - /* reset the CH1NP bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); - /* set the CH1NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 4U); - /* reset the ISO1 bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1); - /* set the ISO1 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 2U); - /* reset the ISO1N bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N); - /* set the ISO1N bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 2U); - } - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - /* reset the CH2EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); - TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS; - /* set the CH2EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 8U); - /* reset the CH2P bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); - /* set the CH2P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 8U); - - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ - /* reset the CH2NEN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); - /* set the CH2NEN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 8U); - /* reset the CH2NP bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); - /* set the CH2NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 8U); - /* reset the ISO2 bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2); - /* set the ISO2 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 4U); - /* reset the ISO2N bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N); - /* set the ISO2N bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 4U); - } - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - /* reset the CH3EN bit */ - TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN); - TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; - /* set the CH3EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 12U); - /* reset the CH3P bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); - /* set the CH3P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 12U); - - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ - /* reset the ISO3 bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3); - /* set the ISO3 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 6U); - } - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output compare mode - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] ocmode: channel output compare mode - only one parameter can be selected which is shown as below: - \arg TIMER_OC_MODE_TIMING: timing mode - \arg TIMER_OC_MODE_ACTIVE: active mode - \arg TIMER_OC_MODE_INACTIVE: inactive mode - \arg TIMER_OC_MODE_TOGGLE: toggle mode - \arg TIMER_OC_MODE_LOW: force low mode - \arg TIMER_OC_MODE_HIGH: force high mode - \arg TIMER_OC_MODE_PWM0: PWM0 mode - \arg TIMER_OC_MODE_PWM1: PWM1 mode - \param[out] none - \retval none -*/ -void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL); - TIMER_CHCTL0(timer_periph) |= (uint32_t)ocmode; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCTL); - TIMER_CHCTL1(timer_periph) |= (uint32_t)ocmode; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output pulse value - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] pulse: channel output pulse value - \param[out] none - \retval none -*/ -void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CH0CV(timer_periph) = (uint32_t)pulse; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CH1CV(timer_periph) = (uint32_t)pulse; - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CH2CV(timer_periph) = (uint32_t)pulse; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CH3CV(timer_periph) = (uint32_t)pulse; - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output shadow function - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] ocshadow: channel output shadow state - only one parameter can be selected which is shown as below: - \arg TIMER_OC_SHADOW_ENABLE: channel output shadow state enable - \arg TIMER_OC_SHADOW_DISABLE: channel output shadow state disable - \param[out] none - \retval none -*/ -void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)ocshadow; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMSEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMSEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)ocshadow; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMSEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output fast function - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] ocfast: channel output fast function - only one parameter can be selected which is shown as below: - \arg TIMER_OC_FAST_ENABLE: channel output fast function enable - \arg TIMER_OC_FAST_DISABLE: channel output fast function disable - \param[out] none - \retval none -*/ -void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)ocfast; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMFEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMFEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)ocfast; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMFEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output clear function - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0 - \arg TIMER_CH_1: TIMER channel1 - \arg TIMER_CH_2: TIMER channel2 - \arg TIMER_CH_3: TIMER channel3 - \param[in] occlear: channel output clear function - only one parameter can be selected which is shown as below: - \arg TIMER_OC_CLEAR_ENABLE: channel output clear function enable - \arg TIMER_OC_CLEAR_DISABLE: channel output clear function disable - \param[out] none - \retval none -*/ -void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)occlear; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)occlear; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output polarity - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] ocpolarity: channel output polarity - only one parameter can be selected which is shown as below: - \arg TIMER_OC_POLARITY_HIGH: channel output polarity is high - \arg TIMER_OC_POLARITY_LOW: channel output polarity is low - \param[out] none - \retval none -*/ -void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpolarity; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 4U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 8U); - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 12U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel complementary output polarity - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0,7)) - \param[in] ocnpolarity: channel complementary output polarity - only one parameter can be selected which is shown as below: - \arg TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high - \arg TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low - \param[out] none - \retval none -*/ -void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnpolarity; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 4U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 8U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel enable state - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] state: TIMER channel enable state - only one parameter can be selected which is shown as below: - \arg TIMER_CCX_ENABLE: channel enable - \arg TIMER_CCX_DISABLE: channel disable - \param[out] none - \retval none -*/ -void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)state; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 4U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 8U); - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 12U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel complementary output enable state - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0,7)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0,7)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0,7)) - \param[in] ocnstate: TIMER channel complementary output enable state - only one parameter can be selected which is shown as below: - \arg TIMER_CCXN_ENABLE: channel complementary enable - \arg TIMER_CCXN_DISABLE: channel complementary disable - \param[out] none - \retval none -*/ -void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnstate; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 4U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 8U); - break; - default: - break; - } -} - -/*! - \brief initialize TIMER channel input parameter struct with a default value - \param[in] icpara: TIMER channel intput parameter struct - \param[out] none - \retval none -*/ -void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) -{ - /* initialize the channel input parameter struct member with the default value */ - icpara->icpolarity = TIMER_IC_POLARITY_RISING; - icpara->icselection = TIMER_IC_SELECTION_DIRECTTI; - icpara->icprescaler = TIMER_IC_PSC_DIV1; - icpara->icfilter = 0U; -} - -/*! - \brief configure TIMER input capture parameter - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] icpara: TIMER channel intput parameter struct - icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING,TIMER_IC_POLARITY_BOTH_EDGE - icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI,TIMER_IC_SELECTION_ITS - icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 - icfilter: 0~15 - \param[out] none - \retval none -*/ -void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - /* reset the CH0EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - - /* reset the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpara->icpolarity); - /* reset the CH0MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); - TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpara->icselection); - /* reset the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); - - /* set the CH0EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; - break; - - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - /* reset the CH1EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - - /* reset the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 4U); - /* reset the CH1MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); - /* reset the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); - - /* set the CH1EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - /* reset the CH2EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); - - /* reset the CH2P and CH2NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH2P | TIMER_CHCTL2_CH2NP)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 8U); - - /* reset the CH2MS bit */ - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2MS); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection)); - - /* reset the CH2CAPFLT bit */ - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPFLT); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); - - /* set the CH2EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH2EN; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - /* reset the CH3EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); - - /* reset the CH3P and CH3NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH3P|TIMER_CHCTL2_CH3NP)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 12U); - - /* reset the CH3MS bit */ - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3MS); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); - - /* reset the CH3CAPFLT bit */ - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPFLT); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); - - /* set the CH3EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH3EN; - break; - default: - break; - } - /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph, channel, (uint16_t)(icpara->icprescaler)); -} - -/*! - \brief configure TIMER channel input capture prescaler value - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] prescaler: channel input capture prescaler value - only one parameter can be selected which is shown as below: - \arg TIMER_IC_PSC_DIV1: no prescaler - \arg TIMER_IC_PSC_DIV2: divided by 2 - \arg TIMER_IC_PSC_DIV4: divided by 4 - \arg TIMER_IC_PSC_DIV8: divided by 8 - \param[out] none - \retval none -*/ -void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC); - TIMER_CHCTL0(timer_periph) |= (uint32_t)prescaler; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPPSC); - TIMER_CHCTL0(timer_periph) |= ((uint32_t)prescaler << 8U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPPSC); - TIMER_CHCTL1(timer_periph) |= (uint32_t)prescaler; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPPSC); - TIMER_CHCTL1(timer_periph) |= ((uint32_t)prescaler << 8U); - break; - default: - break; - } -} - -/*! - \brief read TIMER channel capture compare register value - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[out] none - \retval channel capture compare register value -*/ -uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel) -{ - uint32_t count_value = 0U; - - switch(channel){ - /* read TIMER channel 0 capture compare register value */ - case TIMER_CH_0: - count_value = TIMER_CH0CV(timer_periph); - break; - /* read TIMER channel 1 capture compare register value */ - case TIMER_CH_1: - count_value = TIMER_CH1CV(timer_periph); - break; - /* read TIMER channel 2 capture compare register value */ - case TIMER_CH_2: - count_value = TIMER_CH2CV(timer_periph); - break; - /* read TIMER channel 3 capture compare register value */ - case TIMER_CH_3: - count_value = TIMER_CH3CV(timer_periph); - break; - default: - break; - } - return (count_value); -} - -/*! - \brief configure TIMER input pwm capture function - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0 - \arg TIMER_CH_1: TIMER channel1 - \param[in] icpwm:TIMER channel intput pwm parameter struct - icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING - icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI - icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 - icfilter: 0~15 - \param[out] none - \retval none -*/ -void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm) -{ - uint16_t icpolarity = 0x0U; - uint16_t icselection = 0x0U; - - /* Set channel input polarity */ - if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){ - icpolarity = TIMER_IC_POLARITY_FALLING; - }else{ - icpolarity = TIMER_IC_POLARITY_RISING; - } - /* Set channel input mode selection */ - if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){ - icselection = TIMER_IC_SELECTION_INDIRECTTI; - }else{ - icselection = TIMER_IC_SELECTION_DIRECTTI; - } - - if(TIMER_CH_0 == channel){ - /* reset the CH0EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - /* reset the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); - /* set the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpwm->icpolarity); - /* reset the CH0MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); - /* set the CH0MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpwm->icselection); - /* reset the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); - /* set the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); - /* set the CH0EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; - /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_0, (uint16_t)(icpwm->icprescaler)); - - /* reset the CH1EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - /* reset the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); - /* set the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity<< 4U); - /* reset the CH1MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); - /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection << 8U); - /* reset the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); - /* set the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); - /* set the CH1EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; - /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_1, (uint16_t)(icpwm->icprescaler)); - }else{ - /* reset the CH1EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - /* reset the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); - /* set the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity) << 4U); - /* reset the CH1MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); - /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection) << 8U); - /* reset the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); - /* set the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); - /* set the CH1EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; - /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_1, (uint16_t)(icpwm->icprescaler)); - - /* reset the CH0EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - /* reset the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); - /* set the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)icpolarity; - /* reset the CH0MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); - /* set the CH0MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)icselection; - /* reset the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); - /* set the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); - /* set the CH0EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; - /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_0, (uint16_t)(icpwm->icprescaler)); - } -} - -/*! - \brief configure TIMER hall sensor mode - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] hallmode: - only one parameter can be selected which is shown as below: - \arg TIMER_HALLINTERFACE_ENABLE: TIMER hall sensor mode enable - \arg TIMER_HALLINTERFACE_DISABLE: TIMER hall sensor mode disable - \param[out] none - \retval none -*/ -void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) -{ - if(TIMER_HALLINTERFACE_ENABLE == hallmode){ - TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S; - }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){ - TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief select TIMER input trigger source - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] intrigger: - only one parameter can be selected which is shown as below: - \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 - \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 - \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 - \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 - \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector - \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 - \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 - \arg TIMER_SMCFG_TRGSEL_ETIFP: external trigger(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger) -{ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS); - TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger; -} - -/*! - \brief select TIMER master mode output trigger source - \param[in] timer_periph: TIMERx(x=0..7) - \param[in] outrigger: - only one parameter can be selected which is shown as below: - \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output - \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output - \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output - \arg TIMER_TRI_OUT_SRC_CH0: a capture or a compare match occurred in channal0 as trigger output TRGO - \arg TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output - \arg TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output - \arg TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output - \arg TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output - \param[out] none - \retval none -*/ -void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger) -{ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_MMC); - TIMER_CTL1(timer_periph) |= (uint32_t)outrigger; -} - -/*! - \brief select TIMER slave mode - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] slavemode: - only one parameter can be selected which is shown as below: - \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable - \arg TIMER_QUAD_DECODER_MODE0: quadrature decoder mode 0 - \arg TIMER_QUAD_DECODER_MODE1: quadrature decoder mode 1 - \arg TIMER_QUAD_DECODER_MODE2: quadrature decoder mode 2 - \arg TIMER_SLAVE_MODE_RESTART: restart mode - \arg TIMER_SLAVE_MODE_PAUSE: pause mode - \arg TIMER_SLAVE_MODE_EVENT: event mode - \arg TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0 - \param[out] none - \retval none -*/ - -void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) -{ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); - TIMER_SMCFG(timer_periph) |= (uint32_t)slavemode; -} - -/*! - \brief configure TIMER master slave mode - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] masterslave: - only one parameter can be selected which is shown as below: - \arg TIMER_MASTER_SLAVE_MODE_ENABLE: master slave mode enable - \arg TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable - \param[out] none - \retval none -*/ -void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) -{ - if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){ - TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM; - }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){ - TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief configure TIMER external trigger input - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] extprescaler: - only one parameter can be selected which is shown as below: - \arg TIMER_EXT_TRI_PSC_OFF: no divided - \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 - \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 - \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 - \param[in] extpolarity: - only one parameter can be selected which is shown as below: - \arg TIMER_ETP_FALLING: active low or falling edge active - \arg TIMER_ETP_RISING: active high or rising edge active - \param[in] extfilter: a value between 0 and 15 - \param[out] none - \retval none -*/ -void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) -{ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC)); - TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity); - TIMER_SMCFG(timer_periph) |= (uint32_t)(extfilter << 8U); -} - -/*! - \brief configure TIMER quadrature decoder mode - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] decomode: - only one parameter can be selected which is shown as below: - \arg TIMER_QUAD_DECODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level - \arg TIMER_QUAD_DECODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level - \arg TIMER_QUAD_DECODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input - \param[in] ic0polarity: - only one parameter can be selected which is shown as below: - \arg TIMER_IC_POLARITY_RISING: capture rising edge - \arg TIMER_IC_POLARITY_FALLING: capture falling edge - \arg TIMER_IC_POLARITY_BOTH_EDGE: active both edge - \param[in] ic1polarity: - only one parameter can be selected which is shown as below: - \arg TIMER_IC_POLARITY_RISING: capture rising edge - \arg TIMER_IC_POLARITY_FALLING: capture falling edge - \arg TIMER_IC_POLARITY_BOTH_EDGE: active both edge - \param[out] none - \retval none -*/ -void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity) -{ - /* configure the quadrature decoder mode */ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); - TIMER_SMCFG(timer_periph) |= (uint32_t)decomode; - /* configure input capture selection */ - TIMER_CHCTL0(timer_periph) &= (uint32_t)(((~(uint32_t)TIMER_CHCTL0_CH0MS)) & ((~(uint32_t)TIMER_CHCTL0_CH1MS))); - TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI | ((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U)); - /* configure channel input capture polarity */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); - TIMER_CHCTL2(timer_periph) |= ((uint32_t)ic0polarity | ((uint32_t)ic1polarity << 4U)); -} - -/*! - \brief configure TIMER internal clock mode - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[out] none - \retval none -*/ -void timer_internal_clock_config(uint32_t timer_periph) -{ - TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; -} - -/*! - \brief configure TIMER the internal trigger as external clock input - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] intrigger: - only one parameter can be selected which is shown as below: - \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 - \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 - \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 - \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 - \param[out] none - \retval none -*/ -void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger) -{ - timer_input_trigger_source_select(timer_periph, intrigger); - TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; - TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; -} - -/*! - \brief configure TIMER the external trigger as external clock input - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] extrigger: - only one parameter can be selected which is shown as below: - \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector - \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 - \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 - \param[in] extpolarity: - only one parameter can be selected which is shown as below: - \arg TIMER_IC_POLARITY_RISING: active high or rising edge active - \arg TIMER_IC_POLARITY_FALLING: active low or falling edge active - \arg TIMER_IC_POLARITY_BOTH_EDGE: active both edge - \param[in] extfilter: a value between 0 and 15 - \param[out] none - \retval none -*/ -void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint32_t extfilter) -{ - if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){ - /* reset the CH1EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - /* reset the CH1NP bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); - /* set the CH1NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U); - /* reset the CH1MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); - /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U); - /* reset the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); - /* set the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U); - /* set the CH1EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; - }else{ - /* reset the CH0EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - /* reset the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); - /* set the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity; - /* reset the CH0MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); - /* set the CH0MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)TIMER_IC_SELECTION_DIRECTTI; - /* reset the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); - /* reset the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 4U); - /* set the CH0EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; - } - /* select TIMER input trigger source */ - timer_input_trigger_source_select(timer_periph, extrigger); - /* reset the SMC bit */ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); - /* set the SMC bit */ - TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; -} - -/*! - \brief configure TIMER the external clock mode0 - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] extprescaler: - only one parameter can be selected which is shown as below: - \arg TIMER_EXT_TRI_PSC_OFF: no divided - \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 - \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 - \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 - \param[in] extpolarity: - only one parameter can be selected which is shown as below: - \arg TIMER_ETP_FALLING: active low or falling edge active - \arg TIMER_ETP_RISING: active high or rising edge active - \param[in] extfilter: a value between 0 and 15 - \param[out] none - \retval none -*/ -void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) -{ - /* configure TIMER external trigger input */ - timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); - - /* reset the SMC bit,TRGS bit */ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); - /* set the SMC bit,TRGS bit */ - TIMER_SMCFG(timer_periph) |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP); -} - -/*! - \brief configure TIMER the external clock mode1 - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] extprescaler: - only one parameter can be selected which is shown as below: - \arg TIMER_EXT_TRI_PSC_OFF: no divided - \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 - \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 - \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 - \param[in] extpolarity: - only one parameter can be selected which is shown as below: - \arg TIMER_ETP_FALLING: active low or falling edge active - \arg TIMER_ETP_RISING: active high or rising edge active - \param[in] extfilter: a value between 0 and 15 - \param[out] none - \retval none -*/ -void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) -{ - /* configure TIMER external trigger input */ - timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); - - TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_SMC1; -} - -/*! - \brief disable TIMER the external clock mode1 - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_external_clock_mode1_disable(uint32_t timer_periph) -{ - TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC1; -} - -/*! - \brief configure TIMER write CHxVAL register selection - \param[in] timer_periph: TIMERx(x=0..4,7..13) - \param[in] ccsel: - only one parameter can be selected which is shown as below: - \arg TIMER_CHVSEL_DISABLE: no effect - \arg TIMER_CHVSEL_ENABLE: when write the CHxVAL register, if the write value is same as the CHxVAL value, the write access is ignored - \param[out] none - \retval none -*/ -void timer_write_chxval_register_config(uint32_t timer_periph, uint16_t ccsel) -{ - if(TIMER_CHVSEL_ENABLE == ccsel){ - TIMER_CFG(timer_periph) |= (uint32_t)TIMER_CFG_CHVSEL; - }else if(TIMER_CHVSEL_DISABLE == ccsel){ - TIMER_CFG(timer_periph) &= ~(uint32_t)TIMER_CFG_CHVSEL; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief configure TIMER output value selection - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] outsel: - only one parameter can be selected which is shown as below: - \arg TIMER_OUTSEL_DISABLE: no effect - \arg TIMER_OUTSEL_ENABLE: if POEN and IOS is 0, the output disabled - \param[out] none - \retval none -*/ -void timer_output_value_selection_config(uint32_t timer_periph, uint16_t outsel) -{ - if(TIMER_OUTSEL_ENABLE == outsel){ - TIMER_CFG(timer_periph) |= (uint32_t)TIMER_CFG_OUTSEL; - }else if(TIMER_OUTSEL_DISABLE == outsel){ - TIMER_CFG(timer_periph) &= ~(uint32_t)TIMER_CFG_OUTSEL; - }else{ - /* illegal parameters */ - } -} -/*! - \brief get TIMER flags - \param[in] timer_periph: please refer to the following parameters - \param[in] flag: the timer interrupt flags - only one parameter can be selected which is shown as below: - \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) - \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) - \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) - \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) - \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) - \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) - \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) -{ - if(RESET != (TIMER_INTF(timer_periph) & flag)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear TIMER flags - \param[in] timer_periph: please refer to the following parameters - \param[in] flag: the timer interrupt flags - only one parameter can be selected which is shown as below: - \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) - \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) - \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) - \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) - \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) - \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) - \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_flag_clear(uint32_t timer_periph, uint32_t flag) -{ - TIMER_INTF(timer_periph) = (~(uint32_t)flag); -} -/*! - \brief enable the TIMER interrupt - \param[in] timer_periph: please refer to the following parameters - \param[in] interrupt: timer interrupt enable source - only one parameter can be selected which is shown as below: - \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13) - \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4,7..13) - \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_CH2: channel 2 interrupt enable, TIMERx(x=0..4,7) - \arg TIMER_INT_CH3: channel 3 interrupt enable , TIMERx(x=0..4,7) - \arg TIMER_INT_CMT: commutation interrupt enable, TIMERx(x=0,7) - \arg TIMER_INT_TRG: trigger interrupt enable, TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_BRK: break interrupt enable, TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) -{ - TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; -} - -/*! - \brief disable the TIMER interrupt - \param[in] timer_periph: please refer to the following parameters - \param[in] interrupt: timer interrupt source disable - only one parameter can be selected which is shown as below: - \arg TIMER_INT_UP: update interrupt disable, TIMERx(x=0..13) - \arg TIMER_INT_CH0: channel 0 interrupt disable, TIMERx(x=0..4,7..13) - \arg TIMER_INT_CH1: channel 1 interrupt disable, TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_CH2: channel 2 interrupt disable, TIMERx(x=0..4,7) - \arg TIMER_INT_CH3: channel 3 interrupt disable , TIMERx(x=0..4,7) - \arg TIMER_INT_CMT: commutation interrupt disable, TIMERx(x=0,7) - \arg TIMER_INT_TRG: trigger interrupt disable, TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_BRK: break interrupt disable, TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt) -{ - TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); -} - -/*! - \brief get timer interrupt flag - \param[in] timer_periph: please refer to the following parameters - \param[in] int_flag: the timer interrupt bits - only one parameter can be selected which is shown as below: - \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) - \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) - \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) - \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) - \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t int_flag) -{ - uint32_t val; - val = (TIMER_DMAINTEN(timer_periph) & int_flag); - if((RESET != (TIMER_INTF(timer_periph) & int_flag) ) && (RESET != val)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear TIMER interrupt flag - \param[in] timer_periph: please refer to the following parameters - \param[in] int_flag: the timer interrupt bits - only one parameter can be selected which is shown as below: - \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) - \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) - \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) - \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) - \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t int_flag) -{ - TIMER_INTF(timer_periph) = (~(uint32_t)int_flag); -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_timer.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_timer.c.base@1.5.0 deleted file mode 100644 index 9a53c16..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_timer.c.base@1.5.0 +++ /dev/null @@ -1,2039 +0,0 @@ -/*! - \file gd32e50x_timer.c - \brief TIMER 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_timer.h" - -/* TIMER init parameter mask */ -#define ALIGNEDMODE_MASK ((uint32_t)0x00000060U) /*!< TIMER init parameter aligne dmode mask */ -#define COUNTERDIRECTION_MASK ((uint32_t)0x00000010U) /*!< TIMER init parameter counter direction mask */ -#define CLOCKDIVISION_MASK ((uint32_t)0x00000300U) /*!< TIMER init parameter clock division value mask */ - -/*! - \brief deinit a TIMER - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_deinit(uint32_t timer_periph) -{ - switch(timer_periph){ - case TIMER0: - /* reset TIMER0 */ - rcu_periph_reset_enable(RCU_TIMER0RST); - rcu_periph_reset_disable(RCU_TIMER0RST); - break; - case TIMER1: - /* reset TIMER1 */ - rcu_periph_reset_enable(RCU_TIMER1RST); - rcu_periph_reset_disable(RCU_TIMER1RST); - break; - case TIMER2: - /* reset TIMER2 */ - rcu_periph_reset_enable(RCU_TIMER2RST); - rcu_periph_reset_disable(RCU_TIMER2RST); - break; - case TIMER3: - /* reset TIMER3 */ - rcu_periph_reset_enable(RCU_TIMER3RST); - rcu_periph_reset_disable(RCU_TIMER3RST); - break; - case TIMER4: - /* reset TIMER4 */ - rcu_periph_reset_enable(RCU_TIMER4RST); - rcu_periph_reset_disable(RCU_TIMER4RST); - break; - case TIMER5: - /* reset TIMER5 */ - rcu_periph_reset_enable(RCU_TIMER5RST); - rcu_periph_reset_disable(RCU_TIMER5RST); - break; - case TIMER6: - /* reset TIMER6 */ - rcu_periph_reset_enable(RCU_TIMER6RST); - rcu_periph_reset_disable(RCU_TIMER6RST); - break; - case TIMER7: - /* reset TIMER7 */ - rcu_periph_reset_enable(RCU_TIMER7RST); - rcu_periph_reset_disable(RCU_TIMER7RST); - break; -#ifndef GD32EPRT - case TIMER8: - /* reset TIMER8 */ - rcu_periph_reset_enable(RCU_TIMER8RST); - rcu_periph_reset_disable(RCU_TIMER8RST); - break; - case TIMER9: - /* reset TIMER9 */ - rcu_periph_reset_enable(RCU_TIMER9RST); - rcu_periph_reset_disable(RCU_TIMER9RST); - break; - case TIMER10: - /* reset TIMER10 */ - rcu_periph_reset_enable(RCU_TIMER10RST); - rcu_periph_reset_disable(RCU_TIMER10RST); - break; - case TIMER11: - /* reset TIMER11 */ - rcu_periph_reset_enable(RCU_TIMER11RST); - rcu_periph_reset_disable(RCU_TIMER11RST); - break; - case TIMER12: - /* reset TIMER12 */ - rcu_periph_reset_enable(RCU_TIMER12RST); - rcu_periph_reset_disable(RCU_TIMER12RST); - break; - case TIMER13: - /* reset TIMER13 */ - rcu_periph_reset_enable(RCU_TIMER13RST); - rcu_periph_reset_disable(RCU_TIMER13RST); - break; -#endif /* GD32EPRT */ - default: - break; - } -} - -/*! - \brief initialize TIMER init parameter struct with a default value - \param[in] initpara: init parameter struct - \param[out] none - \retval none -*/ -void timer_struct_para_init(timer_parameter_struct* initpara) -{ - /* initialize the init parameter struct member with the default value */ - initpara->prescaler = 0U; - initpara->alignedmode = TIMER_COUNTER_EDGE; - initpara->counterdirection = TIMER_COUNTER_UP; - initpara->period = 65535U; - initpara->clockdivision = TIMER_CKDIV_DIV1; - initpara->repetitioncounter = 0U; -} - -/*! - \brief initialize TIMER counter - \param[in] timer_periph: TIMERx(x=0..13) - \param[in] initpara: init parameter struct - prescaler: prescaler value of the counter clock, 0~65535 - alignedmode: TIMER_COUNTER_EDGE, TIMER_COUNTER_CENTER_DOWN, TIMER_COUNTER_CENTER_UP, TIMER_COUNTER_CENTER_BOTH - counterdirection: TIMER_COUNTER_UP, TIMER_COUNTER_DOWN - period: counter auto reload value, 0~65535 - clockdivision: TIMER_CKDIV_DIV1, TIMER_CKDIV_DIV2, TIMER_CKDIV_DIV4 - repetitioncounter: counter repetition value, 0~255 - \param[out] none - \retval none -*/ -void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) -{ - /* configure the counter prescaler value */ - TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler; - - /* configure the counter direction and aligned mode */ - if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) - || (TIMER3 == timer_periph) || (TIMER4 == timer_periph) || (TIMER7 == timer_periph)){ - TIMER_CTL0(timer_periph) &= (~(uint32_t)(TIMER_CTL0_DIR | TIMER_CTL0_CAM)); - TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->alignedmode & ALIGNEDMODE_MASK); - TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->counterdirection & COUNTERDIRECTION_MASK); - } - - /* configure the autoreload value */ - TIMER_CAR(timer_periph) = (uint32_t)initpara->period; - - if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){ - /* reset the CKDIV bit */ - TIMER_CTL0(timer_periph) &= (~(uint32_t)TIMER_CTL0_CKDIV); - TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->clockdivision & CLOCKDIVISION_MASK); - } - - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ - /* configure the repetition counter value */ - TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter; - } - - /* generate an update event */ - TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; -} - -/*! - \brief enable a TIMER - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_enable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_CEN; -} - -/*! - \brief disable a TIMER - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_disable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CEN; -} - -/*! - \brief enable the auto reload shadow function - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_auto_reload_shadow_enable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_ARSE; -} - -/*! - \brief disable the auto reload shadow function - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_auto_reload_shadow_disable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_ARSE; -} - -/*! - \brief enable the update event - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_update_event_enable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPDIS; -} - -/*! - \brief disable the update event - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval none -*/ -void timer_update_event_disable(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) |= (uint32_t) TIMER_CTL0_UPDIS; -} - -/*! - \brief set TIMER counter alignment mode - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] aligned: - only one parameter can be selected which is shown as below: - \arg TIMER_COUNTER_EDGE: edge-aligned mode - \arg TIMER_COUNTER_CENTER_DOWN: center-aligned and counting down assert mode - \arg TIMER_COUNTER_CENTER_UP: center-aligned and counting up assert mode - \arg TIMER_COUNTER_CENTER_BOTH: center-aligned and counting up/down assert mode - \param[out] none - \retval none -*/ -void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned) -{ - TIMER_CTL0(timer_periph) &= (uint32_t)(~TIMER_CTL0_CAM); - TIMER_CTL0(timer_periph) |= (uint32_t)aligned; -} - -/*! - \brief set TIMER counter up direction - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_counter_up_direction(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_DIR; -} - -/*! - \brief set TIMER counter down direction - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_counter_down_direction(uint32_t timer_periph) -{ - TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_DIR; -} - -/*! - \brief configure TIMER prescaler - \param[in] timer_periph: TIMERx(x=0..13) - \param[in] prescaler: prescaler value,0~65535 - \param[in] pscreload: prescaler reload mode - only one parameter can be selected which is shown as below: - \arg TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now - \arg TIMER_PSC_RELOAD_UPDATE: the prescaler is loaded at the next update event - \param[out] none - \retval none -*/ -void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload) -{ - TIMER_PSC(timer_periph) = (uint32_t)prescaler; - - if(TIMER_PSC_RELOAD_NOW == pscreload){ - TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; - } -} - -/*! - \brief configure TIMER repetition register value - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] repetition: the counter repetition value, 0~255 - \param[out] none - \retval none -*/ -void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition) -{ - TIMER_CREP(timer_periph) = (uint32_t)repetition; -} - -/*! - \brief configure TIMER autoreload register value - \param[in] timer_periph: TIMERx(x=0..13) - \param[in] autoreload: the counter auto-reload value,0~65535 - \param[out] none - \retval none -*/ -void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload) -{ - TIMER_CAR(timer_periph) = (uint32_t)autoreload; -} - -/*! - \brief configure TIMER counter register value - \param[in] timer_periph: TIMERx(x=0..13) - \param[in] counter: the counter value,0~65535 - \param[out] none - \retval none -*/ -void timer_counter_value_config(uint32_t timer_periph, uint32_t counter) -{ - TIMER_CNT(timer_periph) = (uint32_t)counter; -} - -/*! - \brief read TIMER counter value - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval counter value -*/ -uint32_t timer_counter_read(uint32_t timer_periph) -{ - uint32_t count_value = 0U; - count_value = TIMER_CNT(timer_periph); - return (count_value); -} - -/*! - \brief read TIMER prescaler value - \param[in] timer_periph: TIMERx(x=0..13) - \param[out] none - \retval prescaler register value -*/ -uint16_t timer_prescaler_read(uint32_t timer_periph) -{ - uint16_t prescaler_value = 0U; - prescaler_value = (uint16_t)(TIMER_PSC(timer_periph)); - return (prescaler_value); -} - -/*! - \brief configure TIMER single pulse mode - \param[in] timer_periph: TIMERx(x=0..8,11) - \param[in] spmode: - only one parameter can be selected which is shown as below: - \arg TIMER_SP_MODE_SINGLE: single pulse mode - \arg TIMER_SP_MODE_REPETITIVE: repetitive pulse mode - \param[out] none - \retval none -*/ -void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) -{ - if(TIMER_SP_MODE_SINGLE == spmode){ - TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM; - }else if(TIMER_SP_MODE_REPETITIVE == spmode){ - TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM); - }else{ - /* illegal parameters */ - } -} - -/*! - \brief configure TIMER update source - \param[in] timer_periph: TIMERx(x=0..13) - \param[in] update: - only one parameter can be selected which is shown as below: - \arg TIMER_UPDATE_SRC_GLOBAL: update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger - \arg TIMER_UPDATE_SRC_REGULAR: update generate only by counter overflow/underflow - \param[out] none - \retval none -*/ -void timer_update_source_config(uint32_t timer_periph, uint32_t update) -{ - if(TIMER_UPDATE_SRC_REGULAR == update){ - TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS; - }else if(TIMER_UPDATE_SRC_GLOBAL == update){ - TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief enable the TIMER DMA - \param[in] timer_periph: please refer to the following parameters - \param[in] dma: specify which DMA to enable - only one parameter can be selected which is shown as below: - \arg TIMER_DMA_UPD: update DMA enable,TIMERx(x=0..7) - \arg TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH1D: channel 1 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH2D: channel 2 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH3D: channel 3 DMA enable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CMTD: commutation DMA request enable,TIMERx(x=0,7) - \arg TIMER_DMA_TRGD: trigger DMA enable,TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_dma_enable(uint32_t timer_periph, uint16_t dma) -{ - TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; -} - -/*! - \brief disable the TIMER DMA - \param[in] timer_periph: please refer to the following parameters - \param[in] dma: specify which DMA to enable - one or more parameters can be selected which are shown as below: - \arg TIMER_DMA_UPD: update DMA ,TIMERx(x=0..7) - \arg TIMER_DMA_CH0D: channel 0 DMA request,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH1D: channel 1 DMA request,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH2D: channel 2 DMA request,TIMERx(x=0..4,7) - \arg TIMER_DMA_CH3D: channel 3 DMA request,TIMERx(x=0..4,7) - \arg TIMER_DMA_CMTD: commutation DMA request ,TIMERx(x=0,7) - \arg TIMER_DMA_TRGD: trigger DMA request,TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_dma_disable(uint32_t timer_periph, uint16_t dma) -{ - TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); -} - -/*! - \brief channel DMA request source selection - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] dma_request: channel DMA request source selection - only one parameter can be selected which is shown as below: - \arg TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel y is sent when channel y event occurs - \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs - \param[out] none - \retval none -*/ -void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request) -{ - if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){ - TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS; - }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){ - TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief configure the TIMER DMA transfer - \param[in] timer_periph: please refer to the following parameters - \param[in] dma_baseaddr: - only one parameter can be selected which is shown as below: - \arg TIMER_DMACFG_DMATA_CTL0: DMA transfer address is TIMER_CTL0,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CTL1: DMA transfer address is TIMER_CTL1,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_SMCFG: DMA transfer address is TIMER_SMCFG,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_DMAINTEN: DMA transfer address is TIMER_DMAINTEN,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_INTF: DMA transfer address is TIMER_INTF,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_SWEVG: DMA transfer address is TIMER_SWEVG,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CHCTL0: DMA transfer address is TIMER_CHCTL0,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CHCTL1: DMA transfer address is TIMER_CHCTL1,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CHCTL2: DMA transfer address is TIMER_CHCTL2,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CNT: DMA transfer address is TIMER_CNT,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_PSC: DMA transfer address is TIMER_PSC,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CAR: DMA transfer address is TIMER_CAR,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CREP: DMA transfer address is TIMER_CREP,TIMERx(x=0,7) - \arg TIMER_DMACFG_DMATA_CH0CV: DMA transfer address is TIMER_CH0CV,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CH1CV: DMA transfer address is TIMER_CH1CV,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CH2CV: DMA transfer address is TIMER_CH2CV,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CH3CV: DMA transfer address is TIMER_CH3CV,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP,TIMERx(x=0,7) - \arg TIMER_DMACFG_DMATA_DMACFG: DMA transfer address is TIMER_DMACFG,TIMERx(x=0..4,7) - \arg TIMER_DMACFG_DMATA_DMATB: DMA transfer address is TIMER_DMATB,TIMERx(x=0..4,7) - \param[in] dma_lenth: - only one parameter can be selected which is shown as below: - \arg TIMER_DMACFG_DMATC_xTRANSFER(x=1..18): DMA transfer x time - \param[out] none - \retval none -*/ -void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth) -{ - TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); - TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth); -} - -/*! - \brief software generate events - \param[in] timer_periph: please refer to the following parameters - \param[in] event: the timer software event generation sources - one or more parameters can be selected which are shown as below: - \arg TIMER_EVENT_SRC_UPG: update event,TIMERx(x=0..13) - \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation,TIMERx(x=0..4,7..13) - \arg TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation,TIMERx(x=0..4,7,8,11) - \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation,TIMERx(x=0..4,7) - \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation,TIMERx(x=0..4,7) - \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation,TIMERx(x=0,7) - \arg TIMER_EVENT_SRC_TRGG: trigger event generation,TIMERx(x=0..4,7,8,11) - \arg TIMER_EVENT_SRC_BRKG: break event generation,TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_event_software_generate(uint32_t timer_periph, uint16_t event) -{ - TIMER_SWEVG(timer_periph) |= (uint32_t)event; -} - -/*! - \brief initialize TIMER break parameter struct with a default value - \param[in] breakpara: TIMER break parameter struct - \param[out] none - \retval none -*/ -void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) -{ - /* initialize the break parameter struct member with the default value */ - breakpara->runoffstate = TIMER_ROS_STATE_DISABLE; - breakpara->ideloffstate = TIMER_IOS_STATE_DISABLE; - breakpara->deadtime = 0U; - breakpara->breakpolarity = TIMER_BREAK_POLARITY_LOW; - breakpara->outputautostate = TIMER_OUTAUTO_DISABLE; - breakpara->protectmode = TIMER_CCHP_PROT_OFF; - breakpara->breakstate = TIMER_BREAK_DISABLE; -} - -/*! - \brief configure TIMER break function - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] breakpara: TIMER break parameter struct - runoffstate: TIMER_ROS_STATE_ENABLE,TIMER_ROS_STATE_DISABLE - ideloffstate: TIMER_IOS_STATE_ENABLE,TIMER_IOS_STATE_DISABLE - deadtime: 0~255 - breakpolarity: TIMER_BREAK_POLARITY_LOW,TIMER_BREAK_POLARITY_HIGH - outputautostate: TIMER_OUTAUTO_ENABLE,TIMER_OUTAUTO_DISABLE - protectmode: TIMER_CCHP_PROT_OFF,TIMER_CCHP_PROT_0,TIMER_CCHP_PROT_1,TIMER_CCHP_PROT_2 - breakstate: TIMER_BREAK_ENABLE,TIMER_BREAK_DISABLE - \param[out] none - \retval none -*/ -void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara) -{ - TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate))| - ((uint32_t)(breakpara->ideloffstate))| - ((uint32_t)(breakpara->deadtime))| - ((uint32_t)(breakpara->breakpolarity))| - ((uint32_t)(breakpara->outputautostate)) | - ((uint32_t)(breakpara->protectmode))| - ((uint32_t)(breakpara->breakstate))) ; -} - -/*! - \brief enable TIMER break function - \param[in] timer_periph: TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_break_enable(uint32_t timer_periph) -{ - TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_BRKEN; -} - -/*! - \brief disable TIMER break function - \param[in] timer_periph: TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_break_disable(uint32_t timer_periph) -{ - TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_BRKEN; -} - -/*! - \brief enable TIMER output automatic function - \param[in] timer_periph: TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_automatic_output_enable(uint32_t timer_periph) -{ - TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_OAEN; -} - -/*! - \brief disable TIMER output automatic function - \param[in] timer_periph: TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_automatic_output_disable(uint32_t timer_periph) -{ - TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_OAEN; -} - -/*! - \brief configure TIMER primary output function - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue) -{ - if(ENABLE == newvalue){ - TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN; - }else{ - TIMER_CCHP(timer_periph) &= (~(uint32_t)TIMER_CCHP_POEN); - } -} - -/*! - \brief enable or disable channel capture/compare control shadow register - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] newvalue: ENABLE or DISABLE - \param[out] none - \retval none -*/ -void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue) -{ - if(ENABLE == newvalue){ - TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE; - }else{ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCSE); - } -} - -/*! - \brief configure TIMER channel control shadow register update control - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] ccuctl: channel control shadow register update control - only one parameter can be selected which is shown as below: - \arg TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set - \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs - \param[out] none - \retval none -*/ -void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl) -{ - if(TIMER_UPDATECTL_CCU == ccuctl){ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC); - }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){ - TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief initialize TIMER channel output parameter struct with a default value - \param[in] ocpara: TIMER channel n output parameter struct - \param[out] none - \retval none -*/ -void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) -{ - /* initialize the channel output parameter struct member with the default value */ - ocpara->outputstate = TIMER_CCX_DISABLE; - ocpara->outputnstate = TIMER_CCXN_DISABLE; - ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH; - ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH; - ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW; - ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; -} - -/*! - \brief configure TIMER channel output function - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) - \param[in] ocpara: TIMER channeln output parameter struct - outputstate: TIMER_CCX_ENABLE,TIMER_CCX_DISABLE - outputnstate: TIMER_CCXN_ENABLE,TIMER_CCXN_DISABLE - ocpolarity: TIMER_OC_POLARITY_HIGH,TIMER_OC_POLARITY_LOW - ocnpolarity: TIMER_OCN_POLARITY_HIGH,TIMER_OCN_POLARITY_LOW - ocidlestate: TIMER_OC_IDLE_STATE_LOW,TIMER_OC_IDLE_STATE_HIGH - ocnidlestate: TIMER_OCN_IDLE_STATE_LOW,TIMER_OCN_IDLE_STATE_HIGH - \param[out] none - \retval none -*/ -void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - /* reset the CH0EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS; - /* set the CH0EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputstate; - /* reset the CH0P bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); - /* set the CH0P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity; - - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ - /* reset the CH0NEN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); - /* set the CH0NEN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputnstate; - /* reset the CH0NP bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); - /* set the CH0NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocnpolarity; - /* reset the ISO0 bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0); - /* set the ISO0 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocidlestate; - /* reset the ISO0N bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0N); - /* set the ISO0N bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocnidlestate; - } - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - /* reset the CH1EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS; - /* set the CH1EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 4U); - /* reset the CH1P bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); - /* set the CH1P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 4U); - - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ - /* reset the CH1NEN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); - /* set the CH1NEN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 4U); - /* reset the CH1NP bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); - /* set the CH1NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 4U); - /* reset the ISO1 bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1); - /* set the ISO1 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 2U); - /* reset the ISO1N bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N); - /* set the ISO1N bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 2U); - } - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - /* reset the CH2EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); - TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS; - /* set the CH2EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 8U); - /* reset the CH2P bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); - /* set the CH2P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 8U); - - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ - /* reset the CH2NEN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); - /* set the CH2NEN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 8U); - /* reset the CH2NP bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); - /* set the CH2NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 8U); - /* reset the ISO2 bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2); - /* set the ISO2 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 4U); - /* reset the ISO2N bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N); - /* set the ISO2N bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 4U); - } - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - /* reset the CH3EN bit */ - TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN); - TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; - /* set the CH3EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 12U); - /* reset the CH3P bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); - /* set the CH3P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 12U); - - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ - /* reset the ISO3 bit */ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3); - /* set the ISO3 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 6U); - } - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output compare mode - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] ocmode: channel output compare mode - only one parameter can be selected which is shown as below: - \arg TIMER_OC_MODE_TIMING: timing mode - \arg TIMER_OC_MODE_ACTIVE: active mode - \arg TIMER_OC_MODE_INACTIVE: inactive mode - \arg TIMER_OC_MODE_TOGGLE: toggle mode - \arg TIMER_OC_MODE_LOW: force low mode - \arg TIMER_OC_MODE_HIGH: force high mode - \arg TIMER_OC_MODE_PWM0: PWM0 mode - \arg TIMER_OC_MODE_PWM1: PWM1 mode - \param[out] none - \retval none -*/ -void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL); - TIMER_CHCTL0(timer_periph) |= (uint32_t)ocmode; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCTL); - TIMER_CHCTL1(timer_periph) |= (uint32_t)ocmode; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output pulse value - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] pulse: channel output pulse value - \param[out] none - \retval none -*/ -void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CH0CV(timer_periph) = (uint32_t)pulse; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CH1CV(timer_periph) = (uint32_t)pulse; - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CH2CV(timer_periph) = (uint32_t)pulse; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CH3CV(timer_periph) = (uint32_t)pulse; - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output shadow function - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] ocshadow: channel output shadow state - only one parameter can be selected which is shown as below: - \arg TIMER_OC_SHADOW_ENABLE: channel output shadow state enable - \arg TIMER_OC_SHADOW_DISABLE: channel output shadow state disable - \param[out] none - \retval none -*/ -void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)ocshadow; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMSEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMSEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)ocshadow; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMSEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output fast function - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] ocfast: channel output fast function - only one parameter can be selected which is shown as below: - \arg TIMER_OC_FAST_ENABLE: channel output fast function enable - \arg TIMER_OC_FAST_DISABLE: channel output fast function disable - \param[out] none - \retval none -*/ -void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)ocfast; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMFEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMFEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)ocfast; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMFEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output clear function - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0 - \arg TIMER_CH_1: TIMER channel1 - \arg TIMER_CH_2: TIMER channel2 - \arg TIMER_CH_3: TIMER channel3 - \param[in] occlear: channel output clear function - only one parameter can be selected which is shown as below: - \arg TIMER_OC_CLEAR_ENABLE: channel output clear function enable - \arg TIMER_OC_CLEAR_DISABLE: channel output clear function disable - \param[out] none - \retval none -*/ -void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)occlear; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCEN); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)occlear; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCEN); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel output polarity - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] ocpolarity: channel output polarity - only one parameter can be selected which is shown as below: - \arg TIMER_OC_POLARITY_HIGH: channel output polarity is high - \arg TIMER_OC_POLARITY_LOW: channel output polarity is low - \param[out] none - \retval none -*/ -void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpolarity; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 4U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 8U); - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 12U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel complementary output polarity - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0,7)) - \param[in] ocnpolarity: channel complementary output polarity - only one parameter can be selected which is shown as below: - \arg TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high - \arg TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low - \param[out] none - \retval none -*/ -void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnpolarity; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 4U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 8U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel enable state - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] state: TIMER channel enable state - only one parameter can be selected which is shown as below: - \arg TIMER_CCX_ENABLE: channel enable - \arg TIMER_CCX_DISABLE: channel disable - \param[out] none - \retval none -*/ -void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)state; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 4U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 8U); - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 12U); - break; - default: - break; - } -} - -/*! - \brief configure TIMER channel complementary output enable state - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0,7)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0,7)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0,7)) - \param[in] ocnstate: TIMER channel complementary output enable state - only one parameter can be selected which is shown as below: - \arg TIMER_CCXN_ENABLE: channel complementary enable - \arg TIMER_CCXN_DISABLE: channel complementary disable - \param[out] none - \retval none -*/ -void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnstate; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 4U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 8U); - break; - default: - break; - } -} - -/*! - \brief initialize TIMER channel input parameter struct with a default value - \param[in] icpara: TIMER channel intput parameter struct - \param[out] none - \retval none -*/ -void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) -{ - /* initialize the channel input parameter struct member with the default value */ - icpara->icpolarity = TIMER_IC_POLARITY_RISING; - icpara->icselection = TIMER_IC_SELECTION_DIRECTTI; - icpara->icprescaler = TIMER_IC_PSC_DIV1; - icpara->icfilter = 0U; -} - -/*! - \brief configure TIMER input capture parameter - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] icpara: TIMER channel intput parameter struct - icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING,TIMER_IC_POLARITY_BOTH_EDGE - icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI,TIMER_IC_SELECTION_ITS - icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 - icfilter: 0~15 - \param[out] none - \retval none -*/ -void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - /* reset the CH0EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - - /* reset the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpara->icpolarity); - /* reset the CH0MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); - TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpara->icselection); - /* reset the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); - - /* set the CH0EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; - break; - - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - /* reset the CH1EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - - /* reset the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 4U); - /* reset the CH1MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); - /* reset the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); - - /* set the CH1EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - /* reset the CH2EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); - - /* reset the CH2P and CH2NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH2P | TIMER_CHCTL2_CH2NP)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 8U); - - /* reset the CH2MS bit */ - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2MS); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection)); - - /* reset the CH2CAPFLT bit */ - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPFLT); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); - - /* set the CH2EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH2EN; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - /* reset the CH3EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); - - /* reset the CH3P and CH3NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH3P|TIMER_CHCTL2_CH3NP)); - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 12U); - - /* reset the CH3MS bit */ - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3MS); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); - - /* reset the CH3CAPFLT bit */ - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPFLT); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); - - /* set the CH3EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH3EN; - break; - default: - break; - } - /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph, channel, (uint16_t)(icpara->icprescaler)); -} - -/*! - \brief configure TIMER channel input capture prescaler value - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] prescaler: channel input capture prescaler value - only one parameter can be selected which is shown as below: - \arg TIMER_IC_PSC_DIV1: no prescaler - \arg TIMER_IC_PSC_DIV2: divided by 2 - \arg TIMER_IC_PSC_DIV4: divided by 4 - \arg TIMER_IC_PSC_DIV8: divided by 8 - \param[out] none - \retval none -*/ -void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler) -{ - switch(channel){ - /* configure TIMER_CH_0 */ - case TIMER_CH_0: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC); - TIMER_CHCTL0(timer_periph) |= (uint32_t)prescaler; - break; - /* configure TIMER_CH_1 */ - case TIMER_CH_1: - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPPSC); - TIMER_CHCTL0(timer_periph) |= ((uint32_t)prescaler << 8U); - break; - /* configure TIMER_CH_2 */ - case TIMER_CH_2: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPPSC); - TIMER_CHCTL1(timer_periph) |= (uint32_t)prescaler; - break; - /* configure TIMER_CH_3 */ - case TIMER_CH_3: - TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPPSC); - TIMER_CHCTL1(timer_periph) |= ((uint32_t)prescaler << 8U); - break; - default: - break; - } -} - -/*! - \brief read TIMER channel capture compare register value - \param[in] timer_periph: please refer to the following parameters - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) - \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) - \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[out] none - \retval channel capture compare register value -*/ -uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel) -{ - uint32_t count_value = 0U; - - switch(channel){ - /* read TIMER channel 0 capture compare register value */ - case TIMER_CH_0: - count_value = TIMER_CH0CV(timer_periph); - break; - /* read TIMER channel 1 capture compare register value */ - case TIMER_CH_1: - count_value = TIMER_CH1CV(timer_periph); - break; - /* read TIMER channel 2 capture compare register value */ - case TIMER_CH_2: - count_value = TIMER_CH2CV(timer_periph); - break; - /* read TIMER channel 3 capture compare register value */ - case TIMER_CH_3: - count_value = TIMER_CH3CV(timer_periph); - break; - default: - break; - } - return (count_value); -} - -/*! - \brief configure TIMER input pwm capture function - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] channel: - only one parameter can be selected which is shown as below: - \arg TIMER_CH_0: TIMER channel0 - \arg TIMER_CH_1: TIMER channel1 - \param[in] icpwm:TIMER channel intput pwm parameter struct - icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING - icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI - icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 - icfilter: 0~15 - \param[out] none - \retval none -*/ -void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm) -{ - uint16_t icpolarity = 0x0U; - uint16_t icselection = 0x0U; - - /* Set channel input polarity */ - if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){ - icpolarity = TIMER_IC_POLARITY_FALLING; - }else{ - icpolarity = TIMER_IC_POLARITY_RISING; - } - /* Set channel input mode selection */ - if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){ - icselection = TIMER_IC_SELECTION_INDIRECTTI; - }else{ - icselection = TIMER_IC_SELECTION_DIRECTTI; - } - - if(TIMER_CH_0 == channel){ - /* reset the CH0EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - /* reset the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); - /* set the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpwm->icpolarity); - /* reset the CH0MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); - /* set the CH0MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpwm->icselection); - /* reset the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); - /* set the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); - /* set the CH0EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; - /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_0, (uint16_t)(icpwm->icprescaler)); - - /* reset the CH1EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - /* reset the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); - /* set the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity<< 4U); - /* reset the CH1MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); - /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection << 8U); - /* reset the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); - /* set the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); - /* set the CH1EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; - /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_1, (uint16_t)(icpwm->icprescaler)); - }else{ - /* reset the CH1EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - /* reset the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); - /* set the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity) << 4U); - /* reset the CH1MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); - /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection) << 8U); - /* reset the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); - /* set the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); - /* set the CH1EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; - /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_1, (uint16_t)(icpwm->icprescaler)); - - /* reset the CH0EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - /* reset the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); - /* set the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)icpolarity; - /* reset the CH0MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); - /* set the CH0MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)icselection; - /* reset the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); - /* set the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); - /* set the CH0EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; - /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_0, (uint16_t)(icpwm->icprescaler)); - } -} - -/*! - \brief configure TIMER hall sensor mode - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] hallmode: - only one parameter can be selected which is shown as below: - \arg TIMER_HALLINTERFACE_ENABLE: TIMER hall sensor mode enable - \arg TIMER_HALLINTERFACE_DISABLE: TIMER hall sensor mode disable - \param[out] none - \retval none -*/ -void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) -{ - if(TIMER_HALLINTERFACE_ENABLE == hallmode){ - TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S; - }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){ - TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief select TIMER input trigger source - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] intrigger: - only one parameter can be selected which is shown as below: - \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 - \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 - \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 - \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 - \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector - \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 - \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 - \arg TIMER_SMCFG_TRGSEL_ETIFP: external trigger(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger) -{ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS); - TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger; -} - -/*! - \brief select TIMER master mode output trigger source - \param[in] timer_periph: TIMERx(x=0..7) - \param[in] outrigger: - only one parameter can be selected which is shown as below: - \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output - \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output - \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output - \arg TIMER_TRI_OUT_SRC_CH0: a capture or a compare match occurred in channal0 as trigger output TRGO - \arg TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output - \arg TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output - \arg TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output - \arg TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output - \param[out] none - \retval none -*/ -void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger) -{ - TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_MMC); - TIMER_CTL1(timer_periph) |= (uint32_t)outrigger; -} - -/*! - \brief select TIMER slave mode - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] slavemode: - only one parameter can be selected which is shown as below: - \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable - \arg TIMER_QUAD_DECODER_MODE0: quadrature decoder mode 0 - \arg TIMER_QUAD_DECODER_MODE1: quadrature decoder mode 1 - \arg TIMER_QUAD_DECODER_MODE2: quadrature decoder mode 2 - \arg TIMER_SLAVE_MODE_RESTART: restart mode - \arg TIMER_SLAVE_MODE_PAUSE: pause mode - \arg TIMER_SLAVE_MODE_EVENT: event mode - \arg TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0 - \param[out] none - \retval none -*/ - -void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) -{ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); - TIMER_SMCFG(timer_periph) |= (uint32_t)slavemode; -} - -/*! - \brief configure TIMER master slave mode - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] masterslave: - only one parameter can be selected which is shown as below: - \arg TIMER_MASTER_SLAVE_MODE_ENABLE: master slave mode enable - \arg TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable - \param[out] none - \retval none -*/ -void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) -{ - if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){ - TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM; - }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){ - TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief configure TIMER external trigger input - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] extprescaler: - only one parameter can be selected which is shown as below: - \arg TIMER_EXT_TRI_PSC_OFF: no divided - \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 - \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 - \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 - \param[in] extpolarity: - only one parameter can be selected which is shown as below: - \arg TIMER_ETP_FALLING: active low or falling edge active - \arg TIMER_ETP_RISING: active high or rising edge active - \param[in] extfilter: a value between 0 and 15 - \param[out] none - \retval none -*/ -void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) -{ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC)); - TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity); - TIMER_SMCFG(timer_periph) |= (uint32_t)(extfilter << 8U); -} - -/*! - \brief configure TIMER quadrature decoder mode - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] decomode: - only one parameter can be selected which is shown as below: - \arg TIMER_QUAD_DECODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level - \arg TIMER_QUAD_DECODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level - \arg TIMER_QUAD_DECODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input - \param[in] ic0polarity: - only one parameter can be selected which is shown as below: - \arg TIMER_IC_POLARITY_RISING: capture rising edge - \arg TIMER_IC_POLARITY_FALLING: capture falling edge - \arg TIMER_IC_POLARITY_BOTH_EDGE: active both edge - \param[in] ic1polarity: - only one parameter can be selected which is shown as below: - \arg TIMER_IC_POLARITY_RISING: capture rising edge - \arg TIMER_IC_POLARITY_FALLING: capture falling edge - \arg TIMER_IC_POLARITY_BOTH_EDGE: active both edge - \param[out] none - \retval none -*/ -void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity) -{ - /* configure the quadrature decoder mode */ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); - TIMER_SMCFG(timer_periph) |= (uint32_t)decomode; - /* configure input capture selection */ - TIMER_CHCTL0(timer_periph) &= (uint32_t)(((~(uint32_t)TIMER_CHCTL0_CH0MS)) & ((~(uint32_t)TIMER_CHCTL0_CH1MS))); - TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI | ((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U)); - /* configure channel input capture polarity */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); - TIMER_CHCTL2(timer_periph) |= ((uint32_t)ic0polarity | ((uint32_t)ic1polarity << 4U)); -} - -/*! - \brief configure TIMER internal clock mode - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[out] none - \retval none -*/ -void timer_internal_clock_config(uint32_t timer_periph) -{ - TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; -} - -/*! - \brief configure TIMER the internal trigger as external clock input - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] intrigger: - only one parameter can be selected which is shown as below: - \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 - \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 - \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 - \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 - \param[out] none - \retval none -*/ -void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger) -{ - timer_input_trigger_source_select(timer_periph, intrigger); - TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; - TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; -} - -/*! - \brief configure TIMER the external trigger as external clock input - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] extrigger: - only one parameter can be selected which is shown as below: - \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector - \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 - \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 - \param[in] extpolarity: - only one parameter can be selected which is shown as below: - \arg TIMER_IC_POLARITY_RISING: active high or rising edge active - \arg TIMER_IC_POLARITY_FALLING: active low or falling edge active - \arg TIMER_IC_POLARITY_BOTH_EDGE: active both edge - \param[in] extfilter: a value between 0 and 15 - \param[out] none - \retval none -*/ -void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint32_t extfilter) -{ - if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){ - /* reset the CH1EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); - /* reset the CH1NP bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); - /* set the CH1NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U); - /* reset the CH1MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); - /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U); - /* reset the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); - /* set the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U); - /* set the CH1EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; - }else{ - /* reset the CH0EN bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); - /* reset the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); - /* set the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity; - /* reset the CH0MS bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); - /* set the CH0MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)TIMER_IC_SELECTION_DIRECTTI; - /* reset the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); - /* reset the CH0CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 4U); - /* set the CH0EN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; - } - /* select TIMER input trigger source */ - timer_input_trigger_source_select(timer_periph, extrigger); - /* reset the SMC bit */ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); - /* set the SMC bit */ - TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; -} - -/*! - \brief configure TIMER the external clock mode0 - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] extprescaler: - only one parameter can be selected which is shown as below: - \arg TIMER_EXT_TRI_PSC_OFF: no divided - \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 - \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 - \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 - \param[in] extpolarity: - only one parameter can be selected which is shown as below: - \arg TIMER_ETP_FALLING: active low or falling edge active - \arg TIMER_ETP_RISING: active high or rising edge active - \param[in] extfilter: a value between 0 and 15 - \param[out] none - \retval none -*/ -void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) -{ - /* configure TIMER external trigger input */ - timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); - - /* reset the SMC bit,TRGS bit */ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); - /* set the SMC bit,TRGS bit */ - TIMER_SMCFG(timer_periph) |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP); -} - -/*! - \brief configure TIMER the external clock mode1 - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[in] extprescaler: - only one parameter can be selected which is shown as below: - \arg TIMER_EXT_TRI_PSC_OFF: no divided - \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 - \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 - \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 - \param[in] extpolarity: - only one parameter can be selected which is shown as below: - \arg TIMER_ETP_FALLING: active low or falling edge active - \arg TIMER_ETP_RISING: active high or rising edge active - \param[in] extfilter: a value between 0 and 15 - \param[out] none - \retval none -*/ -void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) -{ - /* configure TIMER external trigger input */ - timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); - - TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_SMC1; -} - -/*! - \brief disable TIMER the external clock mode1 - \param[in] timer_periph: TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_external_clock_mode1_disable(uint32_t timer_periph) -{ - TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC1; -} - -/*! - \brief configure TIMER write CHxVAL register selection - \param[in] timer_periph: TIMERx(x=0..4,7..13) - \param[in] ccsel: - only one parameter can be selected which is shown as below: - \arg TIMER_CHVSEL_DISABLE: no effect - \arg TIMER_CHVSEL_ENABLE: when write the CHxVAL register, if the write value is same as the CHxVAL value, the write access is ignored - \param[out] none - \retval none -*/ -void timer_write_chxval_register_config(uint32_t timer_periph, uint16_t ccsel) -{ - if(TIMER_CHVSEL_ENABLE == ccsel){ - TIMER_CFG(timer_periph) |= (uint32_t)TIMER_CFG_CHVSEL; - }else if(TIMER_CHVSEL_DISABLE == ccsel){ - TIMER_CFG(timer_periph) &= ~(uint32_t)TIMER_CFG_CHVSEL; - }else{ - /* illegal parameters */ - } -} - -/*! - \brief configure TIMER output value selection - \param[in] timer_periph: TIMERx(x=0,7) - \param[in] outsel: - only one parameter can be selected which is shown as below: - \arg TIMER_OUTSEL_DISABLE: no effect - \arg TIMER_OUTSEL_ENABLE: if POEN and IOS is 0, the output disabled - \param[out] none - \retval none -*/ -void timer_output_value_selection_config(uint32_t timer_periph, uint16_t outsel) -{ - if(TIMER_OUTSEL_ENABLE == outsel){ - TIMER_CFG(timer_periph) |= (uint32_t)TIMER_CFG_OUTSEL; - }else if(TIMER_OUTSEL_DISABLE == outsel){ - TIMER_CFG(timer_periph) &= ~(uint32_t)TIMER_CFG_OUTSEL; - }else{ - /* illegal parameters */ - } -} -/*! - \brief get TIMER flags - \param[in] timer_periph: please refer to the following parameters - \param[in] flag: the timer interrupt flags - only one parameter can be selected which is shown as below: - \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) - \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) - \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) - \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) - \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) - \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) - \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) -{ - if(RESET != (TIMER_INTF(timer_periph) & flag)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear TIMER flags - \param[in] timer_periph: please refer to the following parameters - \param[in] flag: the timer interrupt flags - only one parameter can be selected which is shown as below: - \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) - \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) - \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) - \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) - \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) - \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) - \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_flag_clear(uint32_t timer_periph, uint32_t flag) -{ - TIMER_INTF(timer_periph) = (~(uint32_t)flag); -} -/*! - \brief enable the TIMER interrupt - \param[in] timer_periph: please refer to the following parameters - \param[in] interrupt: timer interrupt enable source - only one parameter can be selected which is shown as below: - \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13) - \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4,7..13) - \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_CH2: channel 2 interrupt enable, TIMERx(x=0..4,7) - \arg TIMER_INT_CH3: channel 3 interrupt enable , TIMERx(x=0..4,7) - \arg TIMER_INT_CMT: commutation interrupt enable, TIMERx(x=0,7) - \arg TIMER_INT_TRG: trigger interrupt enable, TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_BRK: break interrupt enable, TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) -{ - TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; -} - -/*! - \brief disable the TIMER interrupt - \param[in] timer_periph: please refer to the following parameters - \param[in] interrupt: timer interrupt source disable - only one parameter can be selected which is shown as below: - \arg TIMER_INT_UP: update interrupt disable, TIMERx(x=0..13) - \arg TIMER_INT_CH0: channel 0 interrupt disable, TIMERx(x=0..4,7..13) - \arg TIMER_INT_CH1: channel 1 interrupt disable, TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_CH2: channel 2 interrupt disable, TIMERx(x=0..4,7) - \arg TIMER_INT_CH3: channel 3 interrupt disable , TIMERx(x=0..4,7) - \arg TIMER_INT_CMT: commutation interrupt disable, TIMERx(x=0,7) - \arg TIMER_INT_TRG: trigger interrupt disable, TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_BRK: break interrupt disable, TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt) -{ - TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); -} - -/*! - \brief get timer interrupt flag - \param[in] timer_periph: please refer to the following parameters - \param[in] int_flag: the timer interrupt bits - only one parameter can be selected which is shown as below: - \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) - \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) - \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) - \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) - \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t int_flag) -{ - uint32_t val; - val = (TIMER_DMAINTEN(timer_periph) & int_flag); - if((RESET != (TIMER_INTF(timer_periph) & int_flag) ) && (RESET != val)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear TIMER interrupt flag - \param[in] timer_periph: please refer to the following parameters - \param[in] int_flag: the timer interrupt bits - only one parameter can be selected which is shown as below: - \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) - \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) - \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) - \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) - \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) - \param[out] none - \retval none -*/ -void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t int_flag) -{ - TIMER_INTF(timer_periph) = (~(uint32_t)int_flag); -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_usart.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_usart.c deleted file mode 100644 index 196f7cd..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_usart.c +++ /dev/null @@ -1,1764 +0,0 @@ -/*! - \file gd32e50x_usart.c - \brief USART 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_usart.h" - -/* USART register bit offset */ -#define GP_GUAT_OFFSET ((uint32_t)8U) /* bit offset of GUAT in USART_GP */ -#define CTL2_SCRTNUM_OFFSET ((uint32_t)17U) /* bit offset of SCRTNUM in USART_CTL2 */ -#define CTL3_SCRTNUM_OFFSET ((uint32_t)1U) /* bit offset of SCRTNUM in USART_CTL3 */ -#define RT_BL_OFFSET ((uint32_t)24U) /* bit offset of BL in USART_RT */ - -/*! - \brief reset USART/UART - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_deinit(uint32_t usart_periph) -{ - switch(usart_periph){ - case USART0: - rcu_periph_reset_enable(RCU_USART0RST); - rcu_periph_reset_disable(RCU_USART0RST); - break; - case USART1: - rcu_periph_reset_enable(RCU_USART1RST); - rcu_periph_reset_disable(RCU_USART1RST); - break; - case USART2: - rcu_periph_reset_enable(RCU_USART2RST); - rcu_periph_reset_disable(RCU_USART2RST); - break; - case USART5: - rcu_periph_reset_enable(RCU_USART5RST); - rcu_periph_reset_disable(RCU_USART5RST); - break; - case UART3: - rcu_periph_reset_enable(RCU_UART3RST); - rcu_periph_reset_disable(RCU_UART3RST); - break; - case UART4: - rcu_periph_reset_enable(RCU_UART4RST); - rcu_periph_reset_disable(RCU_UART4RST); - break; - default: - break; - } -} - -/*! - \brief configure USART baud rate value - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] baudval: baud rate value - \param[out] none - \retval none -*/ -void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) -{ - uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U; - switch(usart_periph){ - /* get clock frequency */ - case USART0: - uclk=rcu_clock_freq_get(CK_APB2); - break; - case USART5: - uclk=rcu_clock_freq_get(CK_USART); - break; - case USART1: - uclk=rcu_clock_freq_get(CK_APB1); - break; - case USART2: - uclk=rcu_clock_freq_get(CK_APB1); - break; - case UART3: - uclk=rcu_clock_freq_get(CK_APB1); - break; - case UART4: - uclk=rcu_clock_freq_get(CK_APB1); - break; - default: - break; - } - - if(USART5 == usart_periph){ - /* configure USART5 baud rate value */ - if(USART5_CTL0(usart_periph) & USART5_CTL0_OVSMOD){ - /* when oversampling by 8, configure the value of USART_BAUD */ - udiv = ((2U*uclk) + baudval/2U)/baudval; - intdiv = udiv & 0x0000fff0U; - fradiv = (udiv>>1) & 0x00000007U; - }else{ - /* when oversampling by 16, configure the value of USART_BAUD */ - udiv = (uclk+baudval/2U)/baudval; - intdiv = udiv & 0x0000fff0U; - fradiv = udiv & 0x0000000fU; - } - USART5_BAUD(usart_periph) = ((USART5_BAUD_FRADIV | USART5_BAUD_INTDIV) & (intdiv | fradiv)); - }else{ - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) baud rate value */ - if(USART_CTL0(usart_periph) & USART_CTL0_OVSMOD){ - /* when oversampling by 8, configure the value of USART_BAUD */ - udiv = ((2U*uclk) + baudval/2U)/baudval; - intdiv = udiv & 0x0000fff0U; - fradiv = (udiv>>1) & 0x00000007U; - }else{ - /* when oversampling by 16, configure the value of USART_BAUD */ - udiv = (uclk+baudval/2U)/baudval; - intdiv = udiv & 0x0000fff0U; - fradiv = udiv & 0x0000000fU; - } - USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); - } -} - -/*! - \brief configure USART parity function - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] paritycfg: configure USART parity - only one parameter can be selected which is shown as below: - \arg USART_PM_NONE: no parity - \arg USART_PM_EVEN: even parity - \arg USART_PM_ODD: odd parity - \param[out] none - \retval none -*/ -void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear USART5_CTL0 PM,PCEN Bits */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_PM | USART5_CTL0_PCEN); - /* configure USART5 parity mode */ - USART5_CTL0(usart_periph) |= ((USART5_CTL0_PM | USART5_CTL0_PCEN) & paritycfg); - }else{ - /* clear USART_CTL0 PM,PCEN Bits */ - USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) parity mode */ - USART_CTL0(usart_periph) |= ((USART_CTL0_PM | USART_CTL0_PCEN) & paritycfg); - } -} - -/*! - \brief configure USART word length - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] wlen: USART word length configure - only one parameter can be selected which is shown as below: - \arg USART_WL_8BIT: 8 bits - \arg USART_WL_9BIT: 9 bits - \param[out] none - \retval none -*/ -void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear USART5_CTL0 WL bit */ - USART5_CTL0(usart_periph) &= ~USART5_CTL0_WL; - /* configure USART word length */ - USART5_CTL0(usart_periph) |= (USART5_CTL0_WL & wlen); - }else{ - /* clear USART_CTL0 WL bit */ - USART_CTL0(usart_periph) &= ~USART_CTL0_WL; - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) word length */ - USART_CTL0(usart_periph) |= (USART_CTL0_WL & wlen); - } -} - -/*! - \brief configure USART stop bit length - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] stblen: USART stop bit configure - only one parameter can be selected which is shown as below: - \arg USART_STB_1BIT: 1 bit - \arg USART_STB_0_5BIT: 0.5 bit(not available for UARTx(x=3,4,6,7)) - \arg USART_STB_2BIT: 2 bits - \arg USART_STB_1_5BIT: 1.5 bits(not available for UARTx(x=3,4,6,7)) - \param[out] none - \retval none -*/ -void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear USART5_CTL1 STB bits */ - USART5_CTL1(usart_periph) &= ~USART5_CTL1_STB; - /* configure USART stop bits */ - USART5_CTL1(usart_periph) |= (USART5_CTL1_STB & stblen); - }else{ - /* clear USART_CTL1 STB bits */ - USART_CTL1(usart_periph) &= ~USART_CTL1_STB; - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) stop bits */ - USART_CTL1(usart_periph) |= (USART_CTL1_STB & stblen); - } -} - -/*! - \brief enable USART - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* enable USART5 */ - USART5_CTL0(usart_periph) |= USART5_CTL0_UEN; - }else{ - /* enable USARTx(x=0,1,2)/UARTx(x=3,4) */ - USART_CTL0(usart_periph) |= USART_CTL0_UEN; - } -} - -/*! - \brief disable USART - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - }else{ - /* disable USARTx(x=0,1,2)/UARTx(x=3,4) */ - USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN); - } -} - -/*! - \brief configure USART transmitter - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] txconfig: enable or disable USART transmitter - only one parameter can be selected which is shown as below: - \arg USART_TRANSMIT_ENABLE: enable USART transmission - \arg USART_TRANSMIT_DISABLE: enable USART transmission - \param[out] none - \retval none -*/ -void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) -{ - uint32_t ctl = 0U; - - if(USART5 == usart_periph){ - ctl = USART5_CTL0(usart_periph); - ctl &= ~USART5_CTL0_TEN; - ctl |= (USART5_CTL0_TEN & txconfig); - /* configure USART5 transfer mode */ - USART5_CTL0(usart_periph) = ctl; - }else{ - ctl = USART_CTL0(usart_periph); - ctl &= ~USART_CTL0_TEN; - ctl |= (USART_CTL0_TEN & txconfig); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) transfer mode */ - USART_CTL0(usart_periph) = ctl; - } -} - -/*! - \brief configure USART receiver - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] rxconfig: enable or disable USART receiver - only one parameter can be selected which is shown as below: - \arg USART_RECEIVE_ENABLE: enable USART reception - \arg USART_RECEIVE_DISABLE: disable USART reception - \param[out] none - \retval none -*/ -void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) -{ - uint32_t ctl = 0U; - - if(USART5 == usart_periph){ - ctl = USART5_CTL0(usart_periph); - ctl &= ~USART5_CTL0_REN; - ctl |= (USART5_CTL0_REN & rxconfig); - /* configure USART5 receive mode */ - USART5_CTL0(usart_periph) = ctl; - }else{ - ctl = USART_CTL0(usart_periph); - ctl &= ~USART_CTL0_REN; - ctl |= (USART_CTL0_REN & rxconfig); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) receive mode */ - USART_CTL0(usart_periph) = ctl; - } -} - -/*! - \brief configure the USART oversample mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] oversamp: oversample value - only one parameter can be selected which is shown as below: - \arg USART_OVSMOD_8: 8 bits - \arg USART_OVSMOD_16: 16 bits - \param[out] none - \retval none -*/ -void usart_oversample_config(uint32_t usart_periph, uint32_t oversamp) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear OVSMOD bit */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_OVSMOD); - /* configure the USART5 oversample mode */ - USART5_CTL0(usart_periph) |= (USART5_CTL0_OVSMOD & oversamp); - }else{ - /* clear OVSMOD bit */ - USART_CTL0(usart_periph) &= ~(USART_CTL0_OVSMOD); - /* configure the USARTx(x=0,1,2)/UARTx(x=3,4) oversample mode */ - USART_CTL0(usart_periph) |= (USART_CTL0_OVSMOD & oversamp); - } -} - -/*! - \brief configure sample bit method - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] obsm: sample bit - only one parameter can be selected which is shown as below: - \arg USART_OSB_1bit: 1 bit - \arg USART_OSB_3bit: 3 bits - \param[out] none - \retval none -*/ -void usart_sample_bit_config(uint32_t usart_periph, uint32_t obsm) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear USART5 OSB bit */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_OSB); - /* configure USART5 sample bit method */ - USART5_CTL2(usart_periph) |= (USART5_CTL2_OSB & obsm); - }else{ - USART_CTL2(usart_periph) &= ~(USART_CTL2_OSB); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) sample bit method */ - USART_CTL2(usart_periph) |= (USART_CTL2_OSB & obsm); - } -} - -/*! - \brief enable receiver timeout of USART - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_receiver_timeout_enable(uint32_t usart_periph) -{ - if(USART5 ==usart_periph){ - /* enable receiver timeout of USART5 */ - USART5_CTL1(usart_periph) |= USART5_CTL1_RTEN; - }else{ - /* enable receiver timeout of USARTx(x=0,1,2) */ - USART_CTL3(usart_periph) |= USART_CTL3_RTEN; - } -} - -/*! - \brief disable receiver timeout of USART - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_receiver_timeout_disable(uint32_t usart_periph) -{ - if(USART5 ==usart_periph){ - /* disable receiver timeout of USART5 */ - USART5_CTL1(usart_periph) &= ~USART5_CTL1_RTEN; - }else{ - /* disable receiver timeout of USARTx(x=0,1,2) */ - USART_CTL3(usart_periph) &= ~(USART_CTL3_RTEN); - } -} - -/*! - \brief configure the receiver timeout threshold of USART - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] rtimeout: 0x00000000-0x00FFFFFF - \param[out] none - \retval none -*/ -void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout) -{ - if(USART5 == usart_periph){ - USART5_RT(usart_periph) &= ~(USART5_RT_RT); - /* configure USART5 receiver timeout threshold */ - USART5_RT(usart_periph) |= (USART5_RT_RT & rtimeout); - }else{ - USART_RT(usart_periph) &= ~(USART_RT_RT); - /* configure USARTx(x=0,1,2) receiver timeout threshold */ - USART_RT(usart_periph) |= (USART_RT_RT & rtimeout); - } -} - -/*! - \brief USART transmit data function - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] data: data of transmission - \param[out] none - \retval none -*/ -void usart_data_transmit(uint32_t usart_periph, uint16_t data) -{ - if(USART5 == usart_periph){ - /* USART5 transmit data */ - USART5_TDATA(usart_periph) = USART5_TDATA_TDATA & (uint32_t)data; - }else{ - /* USARTx(x=0,1,2)/UARTx(x=3,4) transmit data */ - USART_DATA(usart_periph) = USART_DATA_DATA & (uint32_t)data; - } -} - -/*! - \brief USART receive data function - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval data of received -*/ -uint16_t usart_data_receive(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* USART5 receive data */ - return (uint16_t)(GET_BITS(USART5_RDATA(usart_periph), 0U, 8U)); - }else{ - /* USARTx(x=0,1,2)/UARTx(x=3,4) receive data */ - return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U)); - } -} - -/*! - \brief enable mute mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_mute_mode_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* enable USART5 mute mode */ - USART5_CTL0(usart_periph) |= USART5_CTL0_MEN; - }else{ - /* enable USARTx(x=0,1,2)/UARTx(x=3,4) mute mode */ - USART_CTL0(usart_periph) |= USART_CTL0_RWU; - } -} - -/*! - \brief disable mute mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_mute_mode_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 mute mode */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_MEN); - }else{ - /* disable USARTx(x=0,1,2)/UARTx(x=3,4) mute mode */ - USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU); - } -} - -/*! - \brief configure wakeup method in mute mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] wmethod: two method be used to enter or exit the mute mode - only one parameter can be selected which is shown as below: - \arg USART_WM_IDLE: idle line - \arg USART_WM_ADDR: address mask - \param[out] none - \retval none -*/ -void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear USART5 WM bit */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_WM); - /* configure USART5 wakeup method in mute mode */ - USART5_CTL0(usart_periph) |= (USART5_CTL0_WM & wmethod); - }else{ - /* clear USARTx(x=0,1,2)/UARTx(x=3,4) WM bit */ - USART_CTL0(usart_periph) &= ~(USART_CTL0_WM); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) wakeup method in mute mode */ - USART_CTL0(usart_periph) |= (USART_CTL0_WM & wmethod); - } -} - -/*! - \brief enable LIN mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_lin_mode_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable USART5 LIN mode */ - USART5_CTL1(usart_periph) |= USART5_CTL1_LMEN; - }else{ - /* enable USARTx(x=0,1,2)/UARTx(x=3,4) LIN mode */ - USART_CTL1(usart_periph) |= USART_CTL1_LMEN; - } -} - -/*! - \brief disable LIN mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_lin_mode_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 LIN mode */ - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_LMEN); - }else{ - /* disable USARTx(x=0,1,2)/UARTx(x=3,4) LIN mode */ - USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); - } -} - -/*! - \brief configure lin break frame length - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] lblen: lin break frame length - only one parameter can be selected which is shown as below: - \arg USART_LBLEN_10B: 10 bits - \arg USART_LBLEN_11B: 11 bits - \param[out] none - \retval none -*/ -void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_LBLEN); - /* configure USART5 lin brek frame length */ - USART5_CTL1(usart_periph) |= USART5_CTL1_LBLEN & (lblen); - }else{ - USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) lin brek frame length */ - USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen); - } -} - -/*! - \brief enable half duplex mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_halfduplex_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable USART5 half duplex mode */ - USART5_CTL2(usart_periph) |= (USART5_CTL2_HDEN); - }else{ - /* enable USARTx(x=0,1,2)/UARTx(x=3,4) half duplex mode */ - USART_CTL2(usart_periph) |= USART_CTL2_HDEN; - } -} - -/*! - \brief disable half duplex mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_halfduplex_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 half duplex mode */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_HDEN); - }else{ - /* disable USARTx(x=0,1,2)/UARTx(x=3,4) half duplex mode */ - USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN); - } -} - -/*! - \brief enable CK pin in synchronous mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_synchronous_clock_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable USART5 CK pin in synchronous mode */ - USART5_CTL1(usart_periph) |= USART5_CTL1_CKEN; - }else{ - /* enable USARTx(x=0,1,2) CK pin in synchronous mode */ - USART_CTL1(usart_periph) |= USART_CTL1_CKEN; - } -} - -/*! - \brief disable CK pin in synchronous mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_synchronous_clock_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 CK pin in synchronous mode */ - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_CKEN); - }else{ - /* disable USARTx(x=0,1,2) CK pin in synchronous mode */ - USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN); - } -} - -/*! - \brief configure USART synchronous mode parameters - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] clen: CK length - only one parameter can be selected which is shown as below: - \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame - \arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame - \param[in] cph: clock phase - only one parameter can be selected which is shown as below: - \arg USART_CPH_1CK: first clock transition is the first data capture edge - \arg USART_CPH_2CK: second clock transition is the first data capture edge - \param[in] cpl: clock polarity - only one parameter can be selected which is shown as below: - \arg USART_CPL_LOW: steady low value on CK pin - \arg USART_CPL_HIGH: steady high value on CK pin - \param[out] none - \retval none -*/ -void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL1(usart_periph) &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); - USART5_CTL1(usart_periph) |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); - }else{ - USART_CTL1(usart_periph) &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); - USART_CTL1(usart_periph) |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); - } -} - -/*! - \brief configure guard time value in smartcard mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] guat: guard time value, 0x00000000-0x000000FF - \param[out] none - \retval none -*/ -void usart_guard_time_config(uint32_t usart_periph,uint8_t guat) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_GP(usart_periph) &= ~(USART5_GP_GUAT); - /* configure USART5 guard time value */ - USART5_GP(usart_periph) |= (USART5_GP_GUAT & ((uint32_t)guat << GP_GUAT_OFFSET)); - }else{ - USART_GP(usart_periph) &= ~(USART_GP_GUAT); - /* configure USARTx(x=0,1,2) guard time value */ - USART_GP(usart_periph) |= (USART_GP_GUAT & ((uint32_t)guat << GP_GUAT_OFFSET)); - } -} - -/*! - \brief enable smartcard mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_smartcard_mode_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - /* enable USART5 smartcard mode */ - USART5_CTL2(usart_periph) |= USART5_CTL2_SCEN; - }else{ - /* enable USARTx(x=0,1,2) smartcard mode */ - USART_CTL2(usart_periph) |= USART_CTL2_SCEN; - } -} - -/*! - \brief disable smartcard mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_smartcard_mode_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 smartcard mode */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_SCEN); - }else{ - /* disable USARTx(x=0,1,2) smartcard mode */ - USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN); - } -} - -/*! - \brief enable NACK in smartcard mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_smartcard_mode_nack_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable USART5 NACK in smartcard mode */ - USART5_CTL2(usart_periph) |= USART5_CTL2_NKEN; - }else{ - /* enable USARTx(x=0,1,2) NACK in smartcard mode */ - USART_CTL2(usart_periph) |= USART_CTL2_NKEN; - } -} - -/*! - \brief disable NACK in smartcard mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_smartcard_mode_nack_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 NACK in smartcard mode */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_NKEN); - }else{ - /* disable USARTx(x=0,1,2) NACK in smartcard mode */ - USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN); - } -} - -/*! - \brief configure smartcard auto-retry number - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] scrtnum: smartcard auto-retry number, 0x00000000-0x00000007 - \param[out] none - \retval none -*/ -void usart_smartcard_autoretry_config(uint32_t usart_periph, uint8_t scrtnum) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_SCRTNUM); - /* configure USART5 smartcard auto-retry number */ - USART5_CTL2(usart_periph) |= (USART5_CTL2_SCRTNUM & ((uint32_t) scrtnum << CTL2_SCRTNUM_OFFSET)); - }else{ - USART_CTL3(usart_periph) &= ~(USART_CTL3_SCRTNUM); - /* configure USARTx(x=0,1,2) smartcard auto-retry number */ - USART_CTL3(usart_periph) |= (USART_CTL3_SCRTNUM & ((uint32_t)scrtnum << CTL3_SCRTNUM_OFFSET)); - } -} - -/*! - \brief configure block length in Smartcard T=1 reception - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] bl: block length, 0x00000000-0x000000FF - \param[out] none - \retval none -*/ -void usart_block_length_config(uint32_t usart_periph, uint8_t bl) -{ - if(USART5 == usart_periph){ - USART5_RT(usart_periph) &= ~(USART5_RT_BL); - /* configure USART5 block length */ - USART5_RT(usart_periph) |= (USART5_RT_BL & ((uint32_t)bl << RT_BL_OFFSET)); - }else{ - USART_RT(usart_periph) &= ~(USART_RT_BL); - /* configure USARTx(x=0,1,2) block length */ - USART_RT(usart_periph) |= (USART_RT_BL & ((uint32_t)bl << RT_BL_OFFSET)); - } -} - -/*! - \brief enable IrDA mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_irda_mode_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable USART5 IrDA mode */ - USART5_CTL2(usart_periph) |= USART5_CTL2_IREN; - }else{ - /* enable USARTx(x=0,1,2)/UARTx(x=3,4) IrDA mode */ - USART_CTL2(usart_periph) |= USART_CTL2_IREN; - } -} - -/*! - \brief disable IrDA mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_irda_mode_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 IrDA mode */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_IREN); - }else{ - /* disable USARTx(x=0,1,2)/UARTx(x=3,4) IrDA mode */ - USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN); - } -} - -/*! - \brief configure the peripheral clock prescaler in USART IrDA low-power mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] psc: 0x00000000-0x000000FF - \param[out] none - \retval none -*/ -void usart_prescaler_config(uint32_t usart_periph, uint8_t psc) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_GP(usart_periph) &= ~(USART5_GP_PSC); - /* configure the psc in USART5 */ - USART5_GP(usart_periph) |= (uint32_t)psc; - }else{ - USART_GP(usart_periph) &= ~(USART_GP_PSC); - /* configure the psc in USARTx(x=0,1,2)/UARTx(x=3,4) */ - USART_GP(usart_periph) |= (uint32_t)psc; - } -} - -/*! - \brief configure IrDA low-power - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] irlp: IrDA low-power or normal - only one parameter can be selected which is shown as below: - \arg USART_IRLP_LOW: low-power - \arg USART_IRLP_NORMAL: normal - \param[out] none - \retval none -*/ -void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_IRLP); - /* configure USART5 IrDA low-power */ - USART5_CTL2(usart_periph) |= (USART5_CTL2_IRLP & irlp); - }else{ - USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) IrDA low-power */ - USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp); - } -} - -/*! - \brief configure USART DMA reception - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] dmaconfig: enable or disable DMA for reception - only one parameter can be selected which is shown as below: - \arg USART_RECEIVE_DMA_ENABLE: DMA enable for reception - \arg USART_RECEIVE_DMA_DISABLE: DMA disable for reception - \param[out] none - \retval none -*/ -void usart_dma_receive_config(uint32_t usart_periph, uint8_t dmacmd) -{ - uint32_t ctl = 0U; - - if(USART5 == usart_periph){ - ctl = USART5_CTL2(usart_periph); - ctl &= ~USART5_CTL2_DENR; - ctl |= dmacmd; - /* configure DMA reception */ - USART5_CTL2(usart_periph) = ctl; - }else{ - ctl = USART_CTL2(usart_periph); - ctl &= ~USART_CTL2_DENR; - ctl |= dmacmd; - /* configure DMA reception */ - USART_CTL2(usart_periph) = ctl; - } -} - -/*! - \brief configure USART DMA transmission - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] dmaconfig: enable or disable DMA for transmission - only one parameter can be selected which is shown as below: - \arg USART_TRANSMIT_DMA_ENABLE: DMA enable for transmission - \arg USART_TRANSMIT_DMA_DISABLE: DMA disable for transmission - \param[out] none - \retval none -*/ -void usart_dma_transmit_config(uint32_t usart_periph, uint8_t dmacmd) -{ - uint32_t ctl = 0U; - - if(USART5 == usart_periph){ - ctl = USART5_CTL2(usart_periph); - ctl &= ~USART5_CTL2_DENT; - ctl |= dmacmd; - /* configure DMA reception */ - USART5_CTL2(usart_periph) = ctl; - }else{ - ctl = USART_CTL2(usart_periph); - ctl &= ~USART_CTL2_DENT; - ctl |= dmacmd; - /* configure DMA reception */ - USART_CTL2(usart_periph) = ctl; - } -} - -/*! - \brief configure hardware flow control RTS - \param[in] usart_periph: USARTx(x=0,1,2) - \param[in] rtsconfig: enable or disable RTS - only one parameter can be selected which is shown as below: - \arg USART_RTS_ENABLE: enable RTS - \arg USART_RTS_DISABLE: disable RTS - \param[out] none - \retval none -*/ -void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig) -{ - USART_CTL2(usart_periph) &= ~(USART_CTL2_RTSEN); - USART_CTL2(usart_periph) |= (USART_CTL2_RTSEN & rtsconfig); -} - -/*! - \brief configure hardware flow control CTS - \param[in] usart_periph: USARTx(x=0,1,2) - \param[in] ctsconfig: enable or disable CTS - only one parameter can be selected which is shown as below: - \arg USART_CTS_ENABLE: enable CTS - \arg USART_CTS_DISABLE: disable CTS - \param[out] none - \retval none -*/ -void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig) -{ - USART_CTL2(usart_periph) &= ~(USART_CTL2_CTSEN); - USART_CTL2(usart_periph) |= (USART_CTL2_CTSEN & ctsconfig); -} - -/*! - \brief data is transmitted/received with the LSB/MSB first - \param[in] usart_periph: USARTx(x=0,1,2) - \param[in] msbf: LSB/MSB - only one parameter can be selected which is shown as below: - \arg USART_MSBF_LSB: LSB first - \arg USART_MSBF_MSB: MSB first - \param[out] none - \retval none -*/ -void usart_data_first_config(uint32_t usart_periph, uint32_t msbf) -{ - uint32_t ctl = 0U; - - ctl = USART_CTL3(usart_periph); - ctl &= ~(USART_CTL3_MSBF); - ctl |= (USART_CTL3_MSBF & msbf); - /* configure data transmitted/received mode */ - USART_CTL3(usart_periph) = ctl; -} - -/*! - \brief configure USART inversion - \param[in] usart_periph: USARTx(x=0,1,2) - \param[in] invertpara: refer to enum USART_INVERT_CONFIG - only one parameter can be selected which is shown as below: - \arg USART_DINV_ENABLE: data bit level inversion - \arg USART_DINV_DISABLE: data bit level not inversion - \arg USART_TXPIN_ENABLE: TX pin level inversion - \arg USART_TXPIN_DISABLE: TX pin level not inversion - \arg USART_RXPIN_ENABLE: RX pin level inversion - \arg USART_RXPIN_DISABLE: RX pin level not inversion - \param[out] none - \retval none -*/ -void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara) -{ - /* inverted or not the specified siginal */ - switch(invertpara){ - case USART_DINV_ENABLE: - USART_CTL3(usart_periph) |= USART_CTL3_DINV; - break; - case USART_DINV_DISABLE: - USART_CTL3(usart_periph) &= ~(USART_CTL3_DINV); - break; - case USART_TXPIN_ENABLE: - USART_CTL3(usart_periph) |= USART_CTL3_TINV; - break; - case USART_TXPIN_DISABLE: - USART_CTL3(usart_periph) &= ~(USART_CTL3_TINV); - break; - case USART_RXPIN_ENABLE: - USART_CTL3(usart_periph) |= USART_CTL3_RINV; - break; - case USART_RXPIN_DISABLE: - USART_CTL3(usart_periph) &= ~(USART_CTL3_RINV); - break; - default: - break; - } -} - -/*! - \brief configure the address of the USART in wake up by address match mode - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] addr: address of USART/UART, 0x00000000-0x0000000F - \param[out] none - \retval none -*/ -void usart_address_config(uint32_t usart_periph, uint8_t addr) -{ - USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR); - USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & (uint32_t)addr); -} - -/*! - \brief send break frame - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_send_break(uint32_t usart_periph) -{ - USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD; -} - -/*! - \brief enable collision detected interrupt - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_collision_detected_interrupt_enable(uint32_t usart_periph) -{ - USART_GDCTL(usart_periph) |= USART_GDCTL_CDIE; -} - -/*! - \brief disable collision detected interrupt - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_collision_detected_interrupt_disable(uint32_t usart_periph) -{ - USART_GDCTL(usart_periph) &= ~(USART_GDCTL_CDIE); -} - -/*! - \brief enable collision detection - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_collision_detection_enable(uint32_t usart_periph) -{ - USART_GDCTL(usart_periph) |= USART_GDCTL_CDEN; -} - -/*! - \brief disable collision detection - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_collision_detection_disable(uint32_t usart_periph) -{ - USART_GDCTL(usart_periph) &= ~(USART_GDCTL_CDEN); -} - -/*! - \brief get flag in STAT0/STAT1/GDCTL register - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] flag: USART flags, refer to usart_flag_enum - only one parameter can be selected which is shown as below: - \arg USART_FLAG_CTS: CTS change flag - \arg USART_FLAG_LBD: LIN break detected flag - \arg USART_FLAG_TBE: transmit data buffer empty - \arg USART_FLAG_TC: transmission complete - \arg USART_FLAG_RBNE: read data buffer not empty - \arg USART_FLAG_IDLE: IDLE frame detected flag - \arg USART_FLAG_ORERR: overrun error flag - \arg USART_FLAG_NERR: noise error flag - \arg USART_FLAG_FERR: frame error flag - \arg USART_FLAG_PERR: parity error flag - \arg USART_FLAG_BSY: busy flag - \arg USART_FLAG_EB: end of block flag - \arg USART_FLAG_RT: receiver timeout flag - \arg USART_FLAG_CD: collision detected flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag) -{ - if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear flag in STAT0/STAT1/GDCTL register - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] flag: USART flags, refer to usart_flag_enum - only one parameter can be selected which is shown as below: - \arg USART_FLAG_CTS: CTS change flag - \arg USART_FLAG_LBD: LIN break detected flag - \arg USART_FLAG_TC: transmission complete - \arg USART_FLAG_RBNE: read data buffer not empty - \arg USART_FLAG_EB: end of block flag - \arg USART_FLAG_RT: receiver timeout flag - \arg USART_FLAG_CD: collision detected flag - \param[out] none - \retval none -*/ -void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag) -{ - if (USART_FLAG_CD == flag) { - USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag)); - } else { - USART_REG_VAL(usart_periph, flag) = ~BIT(USART_BIT_POS(flag)); - } -} - -/*! - \brief enable USART interrupt - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] interrupt: USART interrupts, refer to usart_interrupt_enum - only one parameter can be selected which is shown as below: - \arg USART_INT_PERR: parity error interrupt - \arg USART_INT_TBE: transmitter buffer empty interrupt - \arg USART_INT_TC: transmission complete interrupt - \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt - \arg USART_INT_IDLE: IDLE line detected interrupt - \arg USART_INT_LBD: LIN break detected interrupt - \arg USART_INT_ERR: error interrupt - \arg USART_INT_CTS: CTS interrupt - \arg USART_INT_RT: interrupt enable bit of receive timeout event - \arg USART_INT_EB: interrupt enable bit of end of block event - \arg USART_INT_CD: collision detected interrupt - \param[out] none - \retval none -*/ -void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt) -{ - USART_REG_VAL(usart_periph, interrupt) |= BIT(USART_BIT_POS(interrupt)); -} - -/*! - \brief disable USART interrupt - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] interrupt: USART interrupts, refer to usart_interrupt_enum - only one parameter can be selected which is shown as below: - \arg USART_INT_PERR: parity error interrupt - \arg USART_INT_TBE: transmitter buffer empty interrupt - \arg USART_INT_TC: transmission complete interrupt - \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt - \arg USART_INT_IDLE: IDLE line detected interrupt - \arg USART_INT_LBD: LIN break detected interrupt - \arg USART_INT_ERR: error interrupt - \arg USART_INT_CTS: CTS interrupt - \arg USART_INT_RT: interrupt enable bit of receive timeout event - \arg USART_INT_EB: interrupt enable bit of end of block event - \arg USART_INT_CD: collision detected interrupt - \param[out] none - \retval none -*/ -void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt) -{ - USART_REG_VAL(usart_periph, interrupt) &= ~BIT(USART_BIT_POS(interrupt)); -} - -/*! - \brief get USART interrupt and flag status - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] int_flag: USART interrupt flags, refer to usart_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg USART_INT_FLAG_PERR: parity error interrupt and flag - \arg USART_INT_FLAG_TBE: transmitter buffer empty interrupt and flag - \arg USART_INT_FLAG_TC: transmission complete interrupt and flag - \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag - \arg USART_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag - \arg USART_INT_FLAG_IDLE: IDLE line detected interrupt and flag - \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag - \arg USART_INT_FLAG_CTS: CTS interrupt and flag - \arg USART_INT_FLAG_ERR_ORERR: error interrupt and overrun error - \arg USART_INT_FLAG_ERR_NERR: error interrupt and noise error flag - \arg USART_INT_FLAG_ERR_FERR: error interrupt and frame error flag - \arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag - \arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag - \arg USART_INT_FLAG_CD: collision detected interrupt and flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag) -{ - uint32_t intenable = 0U, flagstatus = 0U; - /* get the interrupt enable bit status */ - intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag))); - /* get the corresponding flag bit status */ - flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag))); - - if((0U != flagstatus) && (0U != intenable)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear USART interrupt flag in STAT0/STAT1 register - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] int_flag: USART interrupt flags, refer to usart_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg USART_INT_FLAG_CTS: CTS interrupt and flag - \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag - \arg USART_INT_FLAG_TC: transmission complete interrupt and flag - \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag - \arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag - \arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag - \arg USART_INT_FLAG_CD: collision detected interrupt and flag - \param[out] none - \retval none -*/ -void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag) -{ - USART_REG_VAL2(usart_periph, int_flag) = ~BIT(USART_BIT_POS2(int_flag)); -} - -/*! - \brief data is transmitted/received with the LSB/MSB first - \param[in] usart_periph: USART5 - \param[in] msbf: LSB/MSB - only one parameter can be selected which is shown as below: - \arg USART5_MSBF_LSB: LSB first - \arg USART5_MSBF_MSB: MSB first - \param[out] none - \retval none -*/ -void usart5_data_first_config(uint32_t usart_periph, uint32_t msbf) -{ - uint32_t ctl = 0U; - - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - ctl = USART5_CTL1(usart_periph); - ctl &= ~(USART5_CTL1_MSBF); - ctl |= (USART5_CTL1_MSBF & msbf); - /* configure data transmitted/received mode */ - USART5_CTL1(usart_periph) = ctl; -} - -/*! - \brief configure USART5 inversion - \param[in] usart_periph: USART5 - \param[in] invertpara: refer to enum USART5_INVERT_CONFIG - only one parameter can be selected which is shown as below: - \arg USART5_DINV_ENABLE: data bit level inversion - \arg USART5_DINV_DISABLE: data bit level not inversion - \arg USART5_TXPIN_ENABLE: TX pin level inversion - \arg USART5_TXPIN_DISABLE: TX pin level not inversion - \arg USART5_RXPIN_ENABLE: RX pin level inversion - \arg USART5_RXPIN_DISABLE: RX pin level not inversion - \arg USART5_SWAP_ENABLE: swap TX/RX pins - \arg USART5_SWAP_DISABLE: not swap TX/RX pins - \param[out] none - \retval none -*/ -void usart5_invert_config(uint32_t usart_periph, usart5_invert_enum invertpara) -{ - /* inverted or not the specified siginal */ - switch(invertpara){ - case USART5_DINV_ENABLE: - USART5_CTL1(usart_periph) |= USART5_CTL1_DINV; - break; - case USART5_DINV_DISABLE: - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_DINV); - break; - case USART5_TXPIN_ENABLE: - USART5_CTL1(usart_periph) |= USART5_CTL1_TINV; - break; - case USART5_TXPIN_DISABLE: - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_TINV); - break; - case USART5_RXPIN_ENABLE: - USART5_CTL1(usart_periph) |= USART5_CTL1_RINV; - break; - case USART5_RXPIN_DISABLE: - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_RINV); - break; - case USART5_SWAP_ENABLE: - USART5_CTL1(usart_periph) |= USART5_CTL1_STRP; - break; - case USART5_SWAP_DISABLE: - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_STRP); - break; - default: - break; - } -} - -/*! - \brief enable the USART5 overrun function - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_overrun_enable(uint32_t usart_periph) -{ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable overrun function */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_OVRD); -} - -/*! - \brief disable the USART5 overrun function - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_overrun_disable(uint32_t usart_periph) -{ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable overrun function */ - USART5_CTL2(usart_periph) |= USART5_CTL2_OVRD; -} - -/*! - \brief address of the USART terminal - \param[in] usart_periph: USART5 - \param[in] addr: address of USART terminal, 0x00000000-0x000000FF - \param[out] none - \retval none -*/ -void usart5_address_config(uint32_t usart_periph, uint8_t addr) -{ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_ADDR); - USART5_CTL1(usart_periph) |= (USART5_CTL1_ADDR & (((uint32_t)addr) << 24)); -} - -/*! - \brief configure address detection mode - \param[in] usart_periph: USART5 - \param[in] addmod: address detection mode - only one parameter can be selected which is shown as below: - \arg USART5_ADDM_4BIT: 4 bits - \arg USART5_ADDM_FULLBIT: full bits - \param[out] none - \retval none -*/ -void usart5_address_detection_mode_config(uint32_t usart_periph, uint32_t addmod) -{ - /* disable USART */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_ADDM); - USART5_CTL1(usart_periph) |= (USART5_CTL1_ADDM & addmod); -} - -/*! - \brief enable early NACK in smartcard mode - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_smartcard_mode_early_nack_enable(uint32_t usart_periph) -{ - USART5_RFCS(usart_periph) |= USART5_RFCS_ELNACK; -} - -/*! - \brief disable early NACK in smartcard mode - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_smartcard_mode_early_nack_disable(uint32_t usart_periph) -{ - USART5_RFCS(usart_periph) &= ~USART5_RFCS_ELNACK; -} - -/*! - \brief enable DMA on reception error - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_reception_error_dma_enable(uint32_t usart_periph) -{ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_DDRE); -} - -/*! - \brief disable DMA on reception error - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_reception_error_dma_disable(uint32_t usart_periph) -{ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL2(usart_periph) |= USART5_CTL2_DDRE; -} - -/*! - \brief enable USART to wakeup the mcu from deep-sleep mode - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_wakeup_enable(uint32_t usart_periph) -{ - USART5_CTL0(usart_periph) |= USART5_CTL0_UESM; -} - -/*! - \brief disable USART to wakeup the mcu from deep-sleep mode - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_wakeup_disable(uint32_t usart_periph) -{ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UESM); -} - -/*! - \brief configure the USART wakeup mode from deep-sleep mode - \param[in] usart_periph: USART5 - \param[in] wum: wakeup mode - only one parameter can be selected which is shown as below: - \arg USART5_WUM_ADDR: WUF active on address match - \arg USART5_WUM_STARTB: WUF active on start bit - \arg USART5_WUM_RBNE: WUF active on RBNE - \param[out] none - \retval none -*/ -void usart5_wakeup_mode_config(uint32_t usart_periph, uint32_t wum) -{ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* reset WUM bit */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_WUM); - USART5_CTL2(usart_periph) |= (USART5_CTL2_WUM & wum); -} - -/*! - \brief enable receive FIFO - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_receive_fifo_enable(uint32_t usart_periph) -{ - USART5_RFCS(usart_periph) |= USART5_RFCS_RFEN; -} - -/*! - \brief disable receive FIFO - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_receive_fifo_disable(uint32_t usart_periph) -{ - USART5_RFCS(usart_periph) &= ~(USART5_RFCS_RFEN); -} - -/*! - \brief read receive FIFO counter number - \param[in] usart_periph: USART5 - \param[out] none - \retval receive FIFO counter number -*/ -uint8_t usart5_receive_fifo_counter_number(uint32_t usart_periph) -{ - return (uint8_t)(GET_BITS(USART5_RFCS(usart_periph), 12U, 14U)); -} - -/*! - \brief get flag in STAT/CHC/RFCS register - \param[in] usart_periph: USART5 - \param[in] flag: flag type - only one parameter can be selected which is shown as below: - \arg USART5_FLAG_PERR: parity error flag - \arg USART5_FLAG_FERR: frame error flag - \arg USART5_FLAG_NERR: noise error flag - \arg USART5_FLAG_ORERR: overrun error - \arg USART5_FLAG_IDLE: idle line detected flag - \arg USART5_FLAG_RBNE: read data buffer not empty - \arg USART5_FLAG_TC: transmission completed - \arg USART5_FLAG_TBE: transmit data register empty - \arg USART5_FLAG_LBD: LIN break detected flag - \arg USART5_FLAG_RT: receiver timeout flag - \arg USART5_FLAG_EB: end of block flag - \arg USART5_FLAG_BSY: busy flag - \arg USART5_FLAG_AM: address match flag - \arg USART5_FLAG_SB: send break flag - \arg USART5_FLAG_RWU: receiver wakeup from mute mode. - \arg USART5_FLAG_WU: wakeup from deep-sleep mode flag - \arg USART5_FLAG_TEA: transmit enable acknowledge flag - \arg USART5_FLAG_REA: receive enable acknowledge flag - \arg USART5_FLAG_EPERR: early parity error flag - \arg USART5_FLAG_RFE: receive FIFO empty flag - \arg USART5_FLAG_RFF: receive FIFO full flag - \arg USART5_FLAG_RFFINT: receive FIFO full interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus usart5_flag_get(uint32_t usart_periph, usart5_flag_enum flag) -{ - if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear USART status - \param[in] usart_periph: USART5 - \param[in] flag: flag type - only one parameter can be selected which is shown as below: - \arg USART5_FLAG_PERR: parity error flag - \arg USART5_FLAG_FERR: frame error flag - \arg USART5_FLAG_NERR: noise detected flag - \arg USART5_FLAG_ORERR: overrun error flag - \arg USART5_FLAG_IDLE: idle line detected flag - \arg USART5_FLAG_TC: transmission complete flag - \arg USART5_FLAG_LBD: LIN break detected flag - \arg USART5_FLAG_RT: receiver timeout flag - \arg USART5_FLAG_EB: end of block flag - \arg USART5_FLAG_AM: address match flag - \arg USART5_FLAG_WU: wakeup from deep-sleep mode flag - \arg USART5_FLAG_EPERR: early parity error flag - \param[out] none - \retval none -*/ -void usart5_flag_clear(uint32_t usart_periph, usart5_flag_enum flag) -{ - USART5_INTC(usart_periph) |= BIT(USART_BIT_POS(flag)); -} - -/*! - \brief enable USART interrupt - \param[in] usart_periph: USART5 - \param[in] interrupt: USART5 interrupts, refer to usart5_interrupt_enum - only one parameter can be selected which is shown as below: - \arg USART5_INT_IDLE: idle interrupt - \arg USART5_INT_RBNE: read data buffer not empty interrupt and - overrun error interrupt enable interrupt - \arg USART5_INT_TC: transmission complete interrupt - \arg USART5_INT_TBE: transmit data register empty interrupt - \arg USART5_INT_PERR: parity error interrupt - \arg USART5_INT_AM: address match interrupt - \arg USART5_INT_RT: receiver timeout interrupt - \arg USART5_INT_EB: end of block interrupt - \arg USART5_INT_LBD: LIN break detection interrupt - \arg USART5_INT_ERR: error interrupt enable in multibuffer communication - \arg USART5_INT_WU: wakeup from deep-sleep mode interrupt - \arg USART5_INT_RFF: receive FIFO full interrupt enable - \param[out] none - \retval none -*/ -void usart5_interrupt_enable(uint32_t usart_periph, usart5_interrupt_enum interrupt) -{ - USART_REG_VAL(usart_periph, interrupt) |= BIT(USART_BIT_POS(interrupt)); -} - -/*! - \brief disable USART interrupt - \param[in] usart_periph: USART5 - \param[in] interrupt: USART5 interrupts, refer to usart5_interrupt_enum - only one parameter can be selected which is shown as below: - \arg USART5_INT_IDLE: idle interrupt - \arg USART5_INT_RBNE: read data buffer not empty interrupt and - overrun error interrupt - \arg USART5_INT_TC: transmission complete interrupt - \arg USART5_INT_TBE: transmit data register empty interrupt - \arg USART5_INT_PERR: parity error interrupt - \arg USART5_INT_AM: address match interrupt - \arg USART5_INT_RT: receiver timeout interrupt - \arg USART5_INT_EB: end of block interrupt - \arg USART5_INT_LBD: LIN break detection interrupt - \arg USART5_INT_ERR: error interrupt enable in multibuffer communication - \arg USART5_INT_WU: wakeup from deep-sleep mode interrupt - \arg USART5_INT_RFF: receive FIFO full interrupt enable - \param[out] none - \retval none -*/ -void usart5_interrupt_disable(uint32_t usart_periph, usart5_interrupt_enum interrupt) -{ - USART_REG_VAL(usart_periph, interrupt) &= ~BIT(USART_BIT_POS(interrupt)); -} - -/*! - \brief enable USART command - \param[in] usart_periph: USART5 - \param[in] cmdtype: command type - only one parameter can be selected which is shown as below: - \arg USART5_CMD_SBKCMD: send break command - \arg USART5_CMD_MMCMD: mute mode command - \arg USART5_CMD_RXFCMD: receive data flush command - \arg USART5_CMD_TXFCMD: transmit data flush request - \param[out] none - \retval none -*/ -void usart5_command_enable(uint32_t usart_periph, uint32_t cmdtype) -{ - USART5_CMD(usart_periph) |= (cmdtype); -} - -/*! - \brief get USART interrupt and flag status - \param[in] usart_periph: USART5 - \param[in] int_flag: interrupt and flag type, refer to usart5_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg USART5_INT_FLAG_EB: end of block interrupt and flag - \arg USART5_INT_FLAG_RT: receiver timeout interrupt and flag - \arg USART5_INT_FLAG_AM: address match interrupt and flag - \arg USART5_INT_FLAG_PERR: parity error interrupt and flag - \arg USART5_INT_FLAG_TBE: transmitter buffer empty interrupt and flag - \arg USART5_INT_FLAG_TC: transmission complete interrupt and flag - \arg USART5_INT_FLAG_RBNE: read data buffer not empty interrupt and flag - \arg USART5_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag - \arg USART5_INT_FLAG_IDLE: IDLE line detected interrupt and flag - \arg USART5_INT_FLAG_LBD: LIN break detected interrupt and flag - \arg USART5_INT_FLAG_WU: wakeup from deep-sleep mode interrupt and flag - \arg USART5_INT_FLAG_ERR_NERR: error interrupt and noise error flag - \arg USART5_INT_FLAG_ERR_ORERR: error interrupt and overrun error - \arg USART5_INT_FLAG_ERR_FERR: error interrupt and frame error flag - \arg USART5_INT_FLAG_RFF: receive FIFO full interrupt and flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus usart5_interrupt_flag_get(uint32_t usart_periph, usart5_interrupt_flag_enum int_flag) -{ - uint32_t intenable = 0U, flagstatus = 0U; - /* get the interrupt enable bit status */ - intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag))); - /* get the corresponding flag bit status */ - flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag))); - - if(flagstatus && intenable){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear USART interrupt flag - \param[in] usart_periph: USART5 - \param[in] int_flag: interrupt and flag type, refer to usart5_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg USART5_INT_FLAG_PERR: parity error interrupt and flag - \arg USART5_INT_FLAG_ERR_FERR: error interrupt and frame error flag - \arg USART5_INT_FLAG_ERR_NERR: error interrupt and noise error flag - \arg USART5_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag - \arg USART5_INT_FLAG_ERR_ORERR: error interrupt and overrun error - \arg USART5_INT_FLAG_IDLE: IDLE line detected interrupt and flag - \arg USART5_INT_FLAG_TC: transmission complete interrupt and flag - \arg USART5_INT_FLAG_LBD: LIN break detected interrupt and flag - \arg USART5_INT_FLAG_RT: receiver timeout interrupt and flag - \arg USART5_INT_FLAG_EB: end of block interrupt and flag - \arg USART5_INT_FLAG_AM: address match interrupt and flag - \arg USART5_INT_FLAG_WU: wakeup from deep-sleep mode interrupt and flag - \arg USART5_INT_FLAG_RFF: receive FIFO full interrupt and flag - \param[out] none - \retval none -*/ -void usart5_interrupt_flag_clear(uint32_t usart_periph, usart5_interrupt_flag_enum int_flag) -{ - if(USART5_INT_FLAG_RFF == int_flag){ - USART5_RFCS(usart_periph) &= (uint32_t)(~USART5_RFCS_RFFINT); - }else{ - USART5_INTC(usart_periph) |= BIT(USART_BIT_POS2(int_flag)); - } -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_usart.c.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_usart.c.base@1.5.0 deleted file mode 100644 index 196f7cd..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/gd32e50x_usart.c.base@1.5.0 +++ /dev/null @@ -1,1764 +0,0 @@ -/*! - \file gd32e50x_usart.c - \brief USART 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_usart.h" - -/* USART register bit offset */ -#define GP_GUAT_OFFSET ((uint32_t)8U) /* bit offset of GUAT in USART_GP */ -#define CTL2_SCRTNUM_OFFSET ((uint32_t)17U) /* bit offset of SCRTNUM in USART_CTL2 */ -#define CTL3_SCRTNUM_OFFSET ((uint32_t)1U) /* bit offset of SCRTNUM in USART_CTL3 */ -#define RT_BL_OFFSET ((uint32_t)24U) /* bit offset of BL in USART_RT */ - -/*! - \brief reset USART/UART - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_deinit(uint32_t usart_periph) -{ - switch(usart_periph){ - case USART0: - rcu_periph_reset_enable(RCU_USART0RST); - rcu_periph_reset_disable(RCU_USART0RST); - break; - case USART1: - rcu_periph_reset_enable(RCU_USART1RST); - rcu_periph_reset_disable(RCU_USART1RST); - break; - case USART2: - rcu_periph_reset_enable(RCU_USART2RST); - rcu_periph_reset_disable(RCU_USART2RST); - break; - case USART5: - rcu_periph_reset_enable(RCU_USART5RST); - rcu_periph_reset_disable(RCU_USART5RST); - break; - case UART3: - rcu_periph_reset_enable(RCU_UART3RST); - rcu_periph_reset_disable(RCU_UART3RST); - break; - case UART4: - rcu_periph_reset_enable(RCU_UART4RST); - rcu_periph_reset_disable(RCU_UART4RST); - break; - default: - break; - } -} - -/*! - \brief configure USART baud rate value - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] baudval: baud rate value - \param[out] none - \retval none -*/ -void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) -{ - uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U; - switch(usart_periph){ - /* get clock frequency */ - case USART0: - uclk=rcu_clock_freq_get(CK_APB2); - break; - case USART5: - uclk=rcu_clock_freq_get(CK_USART); - break; - case USART1: - uclk=rcu_clock_freq_get(CK_APB1); - break; - case USART2: - uclk=rcu_clock_freq_get(CK_APB1); - break; - case UART3: - uclk=rcu_clock_freq_get(CK_APB1); - break; - case UART4: - uclk=rcu_clock_freq_get(CK_APB1); - break; - default: - break; - } - - if(USART5 == usart_periph){ - /* configure USART5 baud rate value */ - if(USART5_CTL0(usart_periph) & USART5_CTL0_OVSMOD){ - /* when oversampling by 8, configure the value of USART_BAUD */ - udiv = ((2U*uclk) + baudval/2U)/baudval; - intdiv = udiv & 0x0000fff0U; - fradiv = (udiv>>1) & 0x00000007U; - }else{ - /* when oversampling by 16, configure the value of USART_BAUD */ - udiv = (uclk+baudval/2U)/baudval; - intdiv = udiv & 0x0000fff0U; - fradiv = udiv & 0x0000000fU; - } - USART5_BAUD(usart_periph) = ((USART5_BAUD_FRADIV | USART5_BAUD_INTDIV) & (intdiv | fradiv)); - }else{ - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) baud rate value */ - if(USART_CTL0(usart_periph) & USART_CTL0_OVSMOD){ - /* when oversampling by 8, configure the value of USART_BAUD */ - udiv = ((2U*uclk) + baudval/2U)/baudval; - intdiv = udiv & 0x0000fff0U; - fradiv = (udiv>>1) & 0x00000007U; - }else{ - /* when oversampling by 16, configure the value of USART_BAUD */ - udiv = (uclk+baudval/2U)/baudval; - intdiv = udiv & 0x0000fff0U; - fradiv = udiv & 0x0000000fU; - } - USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); - } -} - -/*! - \brief configure USART parity function - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] paritycfg: configure USART parity - only one parameter can be selected which is shown as below: - \arg USART_PM_NONE: no parity - \arg USART_PM_EVEN: even parity - \arg USART_PM_ODD: odd parity - \param[out] none - \retval none -*/ -void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear USART5_CTL0 PM,PCEN Bits */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_PM | USART5_CTL0_PCEN); - /* configure USART5 parity mode */ - USART5_CTL0(usart_periph) |= ((USART5_CTL0_PM | USART5_CTL0_PCEN) & paritycfg); - }else{ - /* clear USART_CTL0 PM,PCEN Bits */ - USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) parity mode */ - USART_CTL0(usart_periph) |= ((USART_CTL0_PM | USART_CTL0_PCEN) & paritycfg); - } -} - -/*! - \brief configure USART word length - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] wlen: USART word length configure - only one parameter can be selected which is shown as below: - \arg USART_WL_8BIT: 8 bits - \arg USART_WL_9BIT: 9 bits - \param[out] none - \retval none -*/ -void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear USART5_CTL0 WL bit */ - USART5_CTL0(usart_periph) &= ~USART5_CTL0_WL; - /* configure USART word length */ - USART5_CTL0(usart_periph) |= (USART5_CTL0_WL & wlen); - }else{ - /* clear USART_CTL0 WL bit */ - USART_CTL0(usart_periph) &= ~USART_CTL0_WL; - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) word length */ - USART_CTL0(usart_periph) |= (USART_CTL0_WL & wlen); - } -} - -/*! - \brief configure USART stop bit length - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] stblen: USART stop bit configure - only one parameter can be selected which is shown as below: - \arg USART_STB_1BIT: 1 bit - \arg USART_STB_0_5BIT: 0.5 bit(not available for UARTx(x=3,4,6,7)) - \arg USART_STB_2BIT: 2 bits - \arg USART_STB_1_5BIT: 1.5 bits(not available for UARTx(x=3,4,6,7)) - \param[out] none - \retval none -*/ -void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear USART5_CTL1 STB bits */ - USART5_CTL1(usart_periph) &= ~USART5_CTL1_STB; - /* configure USART stop bits */ - USART5_CTL1(usart_periph) |= (USART5_CTL1_STB & stblen); - }else{ - /* clear USART_CTL1 STB bits */ - USART_CTL1(usart_periph) &= ~USART_CTL1_STB; - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) stop bits */ - USART_CTL1(usart_periph) |= (USART_CTL1_STB & stblen); - } -} - -/*! - \brief enable USART - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* enable USART5 */ - USART5_CTL0(usart_periph) |= USART5_CTL0_UEN; - }else{ - /* enable USARTx(x=0,1,2)/UARTx(x=3,4) */ - USART_CTL0(usart_periph) |= USART_CTL0_UEN; - } -} - -/*! - \brief disable USART - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - }else{ - /* disable USARTx(x=0,1,2)/UARTx(x=3,4) */ - USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN); - } -} - -/*! - \brief configure USART transmitter - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] txconfig: enable or disable USART transmitter - only one parameter can be selected which is shown as below: - \arg USART_TRANSMIT_ENABLE: enable USART transmission - \arg USART_TRANSMIT_DISABLE: enable USART transmission - \param[out] none - \retval none -*/ -void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) -{ - uint32_t ctl = 0U; - - if(USART5 == usart_periph){ - ctl = USART5_CTL0(usart_periph); - ctl &= ~USART5_CTL0_TEN; - ctl |= (USART5_CTL0_TEN & txconfig); - /* configure USART5 transfer mode */ - USART5_CTL0(usart_periph) = ctl; - }else{ - ctl = USART_CTL0(usart_periph); - ctl &= ~USART_CTL0_TEN; - ctl |= (USART_CTL0_TEN & txconfig); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) transfer mode */ - USART_CTL0(usart_periph) = ctl; - } -} - -/*! - \brief configure USART receiver - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] rxconfig: enable or disable USART receiver - only one parameter can be selected which is shown as below: - \arg USART_RECEIVE_ENABLE: enable USART reception - \arg USART_RECEIVE_DISABLE: disable USART reception - \param[out] none - \retval none -*/ -void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) -{ - uint32_t ctl = 0U; - - if(USART5 == usart_periph){ - ctl = USART5_CTL0(usart_periph); - ctl &= ~USART5_CTL0_REN; - ctl |= (USART5_CTL0_REN & rxconfig); - /* configure USART5 receive mode */ - USART5_CTL0(usart_periph) = ctl; - }else{ - ctl = USART_CTL0(usart_periph); - ctl &= ~USART_CTL0_REN; - ctl |= (USART_CTL0_REN & rxconfig); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) receive mode */ - USART_CTL0(usart_periph) = ctl; - } -} - -/*! - \brief configure the USART oversample mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] oversamp: oversample value - only one parameter can be selected which is shown as below: - \arg USART_OVSMOD_8: 8 bits - \arg USART_OVSMOD_16: 16 bits - \param[out] none - \retval none -*/ -void usart_oversample_config(uint32_t usart_periph, uint32_t oversamp) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear OVSMOD bit */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_OVSMOD); - /* configure the USART5 oversample mode */ - USART5_CTL0(usart_periph) |= (USART5_CTL0_OVSMOD & oversamp); - }else{ - /* clear OVSMOD bit */ - USART_CTL0(usart_periph) &= ~(USART_CTL0_OVSMOD); - /* configure the USARTx(x=0,1,2)/UARTx(x=3,4) oversample mode */ - USART_CTL0(usart_periph) |= (USART_CTL0_OVSMOD & oversamp); - } -} - -/*! - \brief configure sample bit method - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] obsm: sample bit - only one parameter can be selected which is shown as below: - \arg USART_OSB_1bit: 1 bit - \arg USART_OSB_3bit: 3 bits - \param[out] none - \retval none -*/ -void usart_sample_bit_config(uint32_t usart_periph, uint32_t obsm) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear USART5 OSB bit */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_OSB); - /* configure USART5 sample bit method */ - USART5_CTL2(usart_periph) |= (USART5_CTL2_OSB & obsm); - }else{ - USART_CTL2(usart_periph) &= ~(USART_CTL2_OSB); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) sample bit method */ - USART_CTL2(usart_periph) |= (USART_CTL2_OSB & obsm); - } -} - -/*! - \brief enable receiver timeout of USART - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_receiver_timeout_enable(uint32_t usart_periph) -{ - if(USART5 ==usart_periph){ - /* enable receiver timeout of USART5 */ - USART5_CTL1(usart_periph) |= USART5_CTL1_RTEN; - }else{ - /* enable receiver timeout of USARTx(x=0,1,2) */ - USART_CTL3(usart_periph) |= USART_CTL3_RTEN; - } -} - -/*! - \brief disable receiver timeout of USART - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_receiver_timeout_disable(uint32_t usart_periph) -{ - if(USART5 ==usart_periph){ - /* disable receiver timeout of USART5 */ - USART5_CTL1(usart_periph) &= ~USART5_CTL1_RTEN; - }else{ - /* disable receiver timeout of USARTx(x=0,1,2) */ - USART_CTL3(usart_periph) &= ~(USART_CTL3_RTEN); - } -} - -/*! - \brief configure the receiver timeout threshold of USART - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] rtimeout: 0x00000000-0x00FFFFFF - \param[out] none - \retval none -*/ -void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout) -{ - if(USART5 == usart_periph){ - USART5_RT(usart_periph) &= ~(USART5_RT_RT); - /* configure USART5 receiver timeout threshold */ - USART5_RT(usart_periph) |= (USART5_RT_RT & rtimeout); - }else{ - USART_RT(usart_periph) &= ~(USART_RT_RT); - /* configure USARTx(x=0,1,2) receiver timeout threshold */ - USART_RT(usart_periph) |= (USART_RT_RT & rtimeout); - } -} - -/*! - \brief USART transmit data function - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] data: data of transmission - \param[out] none - \retval none -*/ -void usart_data_transmit(uint32_t usart_periph, uint16_t data) -{ - if(USART5 == usart_periph){ - /* USART5 transmit data */ - USART5_TDATA(usart_periph) = USART5_TDATA_TDATA & (uint32_t)data; - }else{ - /* USARTx(x=0,1,2)/UARTx(x=3,4) transmit data */ - USART_DATA(usart_periph) = USART_DATA_DATA & (uint32_t)data; - } -} - -/*! - \brief USART receive data function - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval data of received -*/ -uint16_t usart_data_receive(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* USART5 receive data */ - return (uint16_t)(GET_BITS(USART5_RDATA(usart_periph), 0U, 8U)); - }else{ - /* USARTx(x=0,1,2)/UARTx(x=3,4) receive data */ - return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U)); - } -} - -/*! - \brief enable mute mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_mute_mode_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* enable USART5 mute mode */ - USART5_CTL0(usart_periph) |= USART5_CTL0_MEN; - }else{ - /* enable USARTx(x=0,1,2)/UARTx(x=3,4) mute mode */ - USART_CTL0(usart_periph) |= USART_CTL0_RWU; - } -} - -/*! - \brief disable mute mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_mute_mode_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 mute mode */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_MEN); - }else{ - /* disable USARTx(x=0,1,2)/UARTx(x=3,4) mute mode */ - USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU); - } -} - -/*! - \brief configure wakeup method in mute mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] wmethod: two method be used to enter or exit the mute mode - only one parameter can be selected which is shown as below: - \arg USART_WM_IDLE: idle line - \arg USART_WM_ADDR: address mask - \param[out] none - \retval none -*/ -void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* clear USART5 WM bit */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_WM); - /* configure USART5 wakeup method in mute mode */ - USART5_CTL0(usart_periph) |= (USART5_CTL0_WM & wmethod); - }else{ - /* clear USARTx(x=0,1,2)/UARTx(x=3,4) WM bit */ - USART_CTL0(usart_periph) &= ~(USART_CTL0_WM); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) wakeup method in mute mode */ - USART_CTL0(usart_periph) |= (USART_CTL0_WM & wmethod); - } -} - -/*! - \brief enable LIN mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_lin_mode_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable USART5 LIN mode */ - USART5_CTL1(usart_periph) |= USART5_CTL1_LMEN; - }else{ - /* enable USARTx(x=0,1,2)/UARTx(x=3,4) LIN mode */ - USART_CTL1(usart_periph) |= USART_CTL1_LMEN; - } -} - -/*! - \brief disable LIN mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_lin_mode_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 LIN mode */ - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_LMEN); - }else{ - /* disable USARTx(x=0,1,2)/UARTx(x=3,4) LIN mode */ - USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); - } -} - -/*! - \brief configure lin break frame length - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] lblen: lin break frame length - only one parameter can be selected which is shown as below: - \arg USART_LBLEN_10B: 10 bits - \arg USART_LBLEN_11B: 11 bits - \param[out] none - \retval none -*/ -void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_LBLEN); - /* configure USART5 lin brek frame length */ - USART5_CTL1(usart_periph) |= USART5_CTL1_LBLEN & (lblen); - }else{ - USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) lin brek frame length */ - USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen); - } -} - -/*! - \brief enable half duplex mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_halfduplex_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable USART5 half duplex mode */ - USART5_CTL2(usart_periph) |= (USART5_CTL2_HDEN); - }else{ - /* enable USARTx(x=0,1,2)/UARTx(x=3,4) half duplex mode */ - USART_CTL2(usart_periph) |= USART_CTL2_HDEN; - } -} - -/*! - \brief disable half duplex mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_halfduplex_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 half duplex mode */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_HDEN); - }else{ - /* disable USARTx(x=0,1,2)/UARTx(x=3,4) half duplex mode */ - USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN); - } -} - -/*! - \brief enable CK pin in synchronous mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_synchronous_clock_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable USART5 CK pin in synchronous mode */ - USART5_CTL1(usart_periph) |= USART5_CTL1_CKEN; - }else{ - /* enable USARTx(x=0,1,2) CK pin in synchronous mode */ - USART_CTL1(usart_periph) |= USART_CTL1_CKEN; - } -} - -/*! - \brief disable CK pin in synchronous mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_synchronous_clock_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 CK pin in synchronous mode */ - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_CKEN); - }else{ - /* disable USARTx(x=0,1,2) CK pin in synchronous mode */ - USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN); - } -} - -/*! - \brief configure USART synchronous mode parameters - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] clen: CK length - only one parameter can be selected which is shown as below: - \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame - \arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame - \param[in] cph: clock phase - only one parameter can be selected which is shown as below: - \arg USART_CPH_1CK: first clock transition is the first data capture edge - \arg USART_CPH_2CK: second clock transition is the first data capture edge - \param[in] cpl: clock polarity - only one parameter can be selected which is shown as below: - \arg USART_CPL_LOW: steady low value on CK pin - \arg USART_CPL_HIGH: steady high value on CK pin - \param[out] none - \retval none -*/ -void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL1(usart_periph) &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); - USART5_CTL1(usart_periph) |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); - }else{ - USART_CTL1(usart_periph) &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); - USART_CTL1(usart_periph) |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); - } -} - -/*! - \brief configure guard time value in smartcard mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] guat: guard time value, 0x00000000-0x000000FF - \param[out] none - \retval none -*/ -void usart_guard_time_config(uint32_t usart_periph,uint8_t guat) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_GP(usart_periph) &= ~(USART5_GP_GUAT); - /* configure USART5 guard time value */ - USART5_GP(usart_periph) |= (USART5_GP_GUAT & ((uint32_t)guat << GP_GUAT_OFFSET)); - }else{ - USART_GP(usart_periph) &= ~(USART_GP_GUAT); - /* configure USARTx(x=0,1,2) guard time value */ - USART_GP(usart_periph) |= (USART_GP_GUAT & ((uint32_t)guat << GP_GUAT_OFFSET)); - } -} - -/*! - \brief enable smartcard mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_smartcard_mode_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - /* enable USART5 smartcard mode */ - USART5_CTL2(usart_periph) |= USART5_CTL2_SCEN; - }else{ - /* enable USARTx(x=0,1,2) smartcard mode */ - USART_CTL2(usart_periph) |= USART_CTL2_SCEN; - } -} - -/*! - \brief disable smartcard mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_smartcard_mode_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 smartcard mode */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_SCEN); - }else{ - /* disable USARTx(x=0,1,2) smartcard mode */ - USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN); - } -} - -/*! - \brief enable NACK in smartcard mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_smartcard_mode_nack_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable USART5 NACK in smartcard mode */ - USART5_CTL2(usart_periph) |= USART5_CTL2_NKEN; - }else{ - /* enable USARTx(x=0,1,2) NACK in smartcard mode */ - USART_CTL2(usart_periph) |= USART_CTL2_NKEN; - } -} - -/*! - \brief disable NACK in smartcard mode - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[out] none - \retval none -*/ -void usart_smartcard_mode_nack_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 NACK in smartcard mode */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_NKEN); - }else{ - /* disable USARTx(x=0,1,2) NACK in smartcard mode */ - USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN); - } -} - -/*! - \brief configure smartcard auto-retry number - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] scrtnum: smartcard auto-retry number, 0x00000000-0x00000007 - \param[out] none - \retval none -*/ -void usart_smartcard_autoretry_config(uint32_t usart_periph, uint8_t scrtnum) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_SCRTNUM); - /* configure USART5 smartcard auto-retry number */ - USART5_CTL2(usart_periph) |= (USART5_CTL2_SCRTNUM & ((uint32_t) scrtnum << CTL2_SCRTNUM_OFFSET)); - }else{ - USART_CTL3(usart_periph) &= ~(USART_CTL3_SCRTNUM); - /* configure USARTx(x=0,1,2) smartcard auto-retry number */ - USART_CTL3(usart_periph) |= (USART_CTL3_SCRTNUM & ((uint32_t)scrtnum << CTL3_SCRTNUM_OFFSET)); - } -} - -/*! - \brief configure block length in Smartcard T=1 reception - \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] bl: block length, 0x00000000-0x000000FF - \param[out] none - \retval none -*/ -void usart_block_length_config(uint32_t usart_periph, uint8_t bl) -{ - if(USART5 == usart_periph){ - USART5_RT(usart_periph) &= ~(USART5_RT_BL); - /* configure USART5 block length */ - USART5_RT(usart_periph) |= (USART5_RT_BL & ((uint32_t)bl << RT_BL_OFFSET)); - }else{ - USART_RT(usart_periph) &= ~(USART_RT_BL); - /* configure USARTx(x=0,1,2) block length */ - USART_RT(usart_periph) |= (USART_RT_BL & ((uint32_t)bl << RT_BL_OFFSET)); - } -} - -/*! - \brief enable IrDA mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_irda_mode_enable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable USART5 IrDA mode */ - USART5_CTL2(usart_periph) |= USART5_CTL2_IREN; - }else{ - /* enable USARTx(x=0,1,2)/UARTx(x=3,4) IrDA mode */ - USART_CTL2(usart_periph) |= USART_CTL2_IREN; - } -} - -/*! - \brief disable IrDA mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_irda_mode_disable(uint32_t usart_periph) -{ - if(USART5 == usart_periph){ - /* disable USART */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable USART5 IrDA mode */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_IREN); - }else{ - /* disable USARTx(x=0,1,2)/UARTx(x=3,4) IrDA mode */ - USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN); - } -} - -/*! - \brief configure the peripheral clock prescaler in USART IrDA low-power mode - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] psc: 0x00000000-0x000000FF - \param[out] none - \retval none -*/ -void usart_prescaler_config(uint32_t usart_periph, uint8_t psc) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_GP(usart_periph) &= ~(USART5_GP_PSC); - /* configure the psc in USART5 */ - USART5_GP(usart_periph) |= (uint32_t)psc; - }else{ - USART_GP(usart_periph) &= ~(USART_GP_PSC); - /* configure the psc in USARTx(x=0,1,2)/UARTx(x=3,4) */ - USART_GP(usart_periph) |= (uint32_t)psc; - } -} - -/*! - \brief configure IrDA low-power - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] irlp: IrDA low-power or normal - only one parameter can be selected which is shown as below: - \arg USART_IRLP_LOW: low-power - \arg USART_IRLP_NORMAL: normal - \param[out] none - \retval none -*/ -void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp) -{ - if(USART5 == usart_periph){ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_IRLP); - /* configure USART5 IrDA low-power */ - USART5_CTL2(usart_periph) |= (USART5_CTL2_IRLP & irlp); - }else{ - USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP); - /* configure USARTx(x=0,1,2)/UARTx(x=3,4) IrDA low-power */ - USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp); - } -} - -/*! - \brief configure USART DMA reception - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] dmaconfig: enable or disable DMA for reception - only one parameter can be selected which is shown as below: - \arg USART_RECEIVE_DMA_ENABLE: DMA enable for reception - \arg USART_RECEIVE_DMA_DISABLE: DMA disable for reception - \param[out] none - \retval none -*/ -void usart_dma_receive_config(uint32_t usart_periph, uint8_t dmacmd) -{ - uint32_t ctl = 0U; - - if(USART5 == usart_periph){ - ctl = USART5_CTL2(usart_periph); - ctl &= ~USART5_CTL2_DENR; - ctl |= dmacmd; - /* configure DMA reception */ - USART5_CTL2(usart_periph) = ctl; - }else{ - ctl = USART_CTL2(usart_periph); - ctl &= ~USART_CTL2_DENR; - ctl |= dmacmd; - /* configure DMA reception */ - USART_CTL2(usart_periph) = ctl; - } -} - -/*! - \brief configure USART DMA transmission - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4) - \param[in] dmaconfig: enable or disable DMA for transmission - only one parameter can be selected which is shown as below: - \arg USART_TRANSMIT_DMA_ENABLE: DMA enable for transmission - \arg USART_TRANSMIT_DMA_DISABLE: DMA disable for transmission - \param[out] none - \retval none -*/ -void usart_dma_transmit_config(uint32_t usart_periph, uint8_t dmacmd) -{ - uint32_t ctl = 0U; - - if(USART5 == usart_periph){ - ctl = USART5_CTL2(usart_periph); - ctl &= ~USART5_CTL2_DENT; - ctl |= dmacmd; - /* configure DMA reception */ - USART5_CTL2(usart_periph) = ctl; - }else{ - ctl = USART_CTL2(usart_periph); - ctl &= ~USART_CTL2_DENT; - ctl |= dmacmd; - /* configure DMA reception */ - USART_CTL2(usart_periph) = ctl; - } -} - -/*! - \brief configure hardware flow control RTS - \param[in] usart_periph: USARTx(x=0,1,2) - \param[in] rtsconfig: enable or disable RTS - only one parameter can be selected which is shown as below: - \arg USART_RTS_ENABLE: enable RTS - \arg USART_RTS_DISABLE: disable RTS - \param[out] none - \retval none -*/ -void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig) -{ - USART_CTL2(usart_periph) &= ~(USART_CTL2_RTSEN); - USART_CTL2(usart_periph) |= (USART_CTL2_RTSEN & rtsconfig); -} - -/*! - \brief configure hardware flow control CTS - \param[in] usart_periph: USARTx(x=0,1,2) - \param[in] ctsconfig: enable or disable CTS - only one parameter can be selected which is shown as below: - \arg USART_CTS_ENABLE: enable CTS - \arg USART_CTS_DISABLE: disable CTS - \param[out] none - \retval none -*/ -void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig) -{ - USART_CTL2(usart_periph) &= ~(USART_CTL2_CTSEN); - USART_CTL2(usart_periph) |= (USART_CTL2_CTSEN & ctsconfig); -} - -/*! - \brief data is transmitted/received with the LSB/MSB first - \param[in] usart_periph: USARTx(x=0,1,2) - \param[in] msbf: LSB/MSB - only one parameter can be selected which is shown as below: - \arg USART_MSBF_LSB: LSB first - \arg USART_MSBF_MSB: MSB first - \param[out] none - \retval none -*/ -void usart_data_first_config(uint32_t usart_periph, uint32_t msbf) -{ - uint32_t ctl = 0U; - - ctl = USART_CTL3(usart_periph); - ctl &= ~(USART_CTL3_MSBF); - ctl |= (USART_CTL3_MSBF & msbf); - /* configure data transmitted/received mode */ - USART_CTL3(usart_periph) = ctl; -} - -/*! - \brief configure USART inversion - \param[in] usart_periph: USARTx(x=0,1,2) - \param[in] invertpara: refer to enum USART_INVERT_CONFIG - only one parameter can be selected which is shown as below: - \arg USART_DINV_ENABLE: data bit level inversion - \arg USART_DINV_DISABLE: data bit level not inversion - \arg USART_TXPIN_ENABLE: TX pin level inversion - \arg USART_TXPIN_DISABLE: TX pin level not inversion - \arg USART_RXPIN_ENABLE: RX pin level inversion - \arg USART_RXPIN_DISABLE: RX pin level not inversion - \param[out] none - \retval none -*/ -void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara) -{ - /* inverted or not the specified siginal */ - switch(invertpara){ - case USART_DINV_ENABLE: - USART_CTL3(usart_periph) |= USART_CTL3_DINV; - break; - case USART_DINV_DISABLE: - USART_CTL3(usart_periph) &= ~(USART_CTL3_DINV); - break; - case USART_TXPIN_ENABLE: - USART_CTL3(usart_periph) |= USART_CTL3_TINV; - break; - case USART_TXPIN_DISABLE: - USART_CTL3(usart_periph) &= ~(USART_CTL3_TINV); - break; - case USART_RXPIN_ENABLE: - USART_CTL3(usart_periph) |= USART_CTL3_RINV; - break; - case USART_RXPIN_DISABLE: - USART_CTL3(usart_periph) &= ~(USART_CTL3_RINV); - break; - default: - break; - } -} - -/*! - \brief configure the address of the USART in wake up by address match mode - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] addr: address of USART/UART, 0x00000000-0x0000000F - \param[out] none - \retval none -*/ -void usart_address_config(uint32_t usart_periph, uint8_t addr) -{ - USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR); - USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & (uint32_t)addr); -} - -/*! - \brief send break frame - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_send_break(uint32_t usart_periph) -{ - USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD; -} - -/*! - \brief enable collision detected interrupt - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_collision_detected_interrupt_enable(uint32_t usart_periph) -{ - USART_GDCTL(usart_periph) |= USART_GDCTL_CDIE; -} - -/*! - \brief disable collision detected interrupt - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_collision_detected_interrupt_disable(uint32_t usart_periph) -{ - USART_GDCTL(usart_periph) &= ~(USART_GDCTL_CDIE); -} - -/*! - \brief enable collision detection - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_collision_detection_enable(uint32_t usart_periph) -{ - USART_GDCTL(usart_periph) |= USART_GDCTL_CDEN; -} - -/*! - \brief disable collision detection - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[out] none - \retval none -*/ -void usart_collision_detection_disable(uint32_t usart_periph) -{ - USART_GDCTL(usart_periph) &= ~(USART_GDCTL_CDEN); -} - -/*! - \brief get flag in STAT0/STAT1/GDCTL register - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] flag: USART flags, refer to usart_flag_enum - only one parameter can be selected which is shown as below: - \arg USART_FLAG_CTS: CTS change flag - \arg USART_FLAG_LBD: LIN break detected flag - \arg USART_FLAG_TBE: transmit data buffer empty - \arg USART_FLAG_TC: transmission complete - \arg USART_FLAG_RBNE: read data buffer not empty - \arg USART_FLAG_IDLE: IDLE frame detected flag - \arg USART_FLAG_ORERR: overrun error flag - \arg USART_FLAG_NERR: noise error flag - \arg USART_FLAG_FERR: frame error flag - \arg USART_FLAG_PERR: parity error flag - \arg USART_FLAG_BSY: busy flag - \arg USART_FLAG_EB: end of block flag - \arg USART_FLAG_RT: receiver timeout flag - \arg USART_FLAG_CD: collision detected flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag) -{ - if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear flag in STAT0/STAT1/GDCTL register - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] flag: USART flags, refer to usart_flag_enum - only one parameter can be selected which is shown as below: - \arg USART_FLAG_CTS: CTS change flag - \arg USART_FLAG_LBD: LIN break detected flag - \arg USART_FLAG_TC: transmission complete - \arg USART_FLAG_RBNE: read data buffer not empty - \arg USART_FLAG_EB: end of block flag - \arg USART_FLAG_RT: receiver timeout flag - \arg USART_FLAG_CD: collision detected flag - \param[out] none - \retval none -*/ -void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag) -{ - if (USART_FLAG_CD == flag) { - USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag)); - } else { - USART_REG_VAL(usart_periph, flag) = ~BIT(USART_BIT_POS(flag)); - } -} - -/*! - \brief enable USART interrupt - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] interrupt: USART interrupts, refer to usart_interrupt_enum - only one parameter can be selected which is shown as below: - \arg USART_INT_PERR: parity error interrupt - \arg USART_INT_TBE: transmitter buffer empty interrupt - \arg USART_INT_TC: transmission complete interrupt - \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt - \arg USART_INT_IDLE: IDLE line detected interrupt - \arg USART_INT_LBD: LIN break detected interrupt - \arg USART_INT_ERR: error interrupt - \arg USART_INT_CTS: CTS interrupt - \arg USART_INT_RT: interrupt enable bit of receive timeout event - \arg USART_INT_EB: interrupt enable bit of end of block event - \arg USART_INT_CD: collision detected interrupt - \param[out] none - \retval none -*/ -void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt) -{ - USART_REG_VAL(usart_periph, interrupt) |= BIT(USART_BIT_POS(interrupt)); -} - -/*! - \brief disable USART interrupt - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] interrupt: USART interrupts, refer to usart_interrupt_enum - only one parameter can be selected which is shown as below: - \arg USART_INT_PERR: parity error interrupt - \arg USART_INT_TBE: transmitter buffer empty interrupt - \arg USART_INT_TC: transmission complete interrupt - \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt - \arg USART_INT_IDLE: IDLE line detected interrupt - \arg USART_INT_LBD: LIN break detected interrupt - \arg USART_INT_ERR: error interrupt - \arg USART_INT_CTS: CTS interrupt - \arg USART_INT_RT: interrupt enable bit of receive timeout event - \arg USART_INT_EB: interrupt enable bit of end of block event - \arg USART_INT_CD: collision detected interrupt - \param[out] none - \retval none -*/ -void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt) -{ - USART_REG_VAL(usart_periph, interrupt) &= ~BIT(USART_BIT_POS(interrupt)); -} - -/*! - \brief get USART interrupt and flag status - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] int_flag: USART interrupt flags, refer to usart_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg USART_INT_FLAG_PERR: parity error interrupt and flag - \arg USART_INT_FLAG_TBE: transmitter buffer empty interrupt and flag - \arg USART_INT_FLAG_TC: transmission complete interrupt and flag - \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag - \arg USART_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag - \arg USART_INT_FLAG_IDLE: IDLE line detected interrupt and flag - \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag - \arg USART_INT_FLAG_CTS: CTS interrupt and flag - \arg USART_INT_FLAG_ERR_ORERR: error interrupt and overrun error - \arg USART_INT_FLAG_ERR_NERR: error interrupt and noise error flag - \arg USART_INT_FLAG_ERR_FERR: error interrupt and frame error flag - \arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag - \arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag - \arg USART_INT_FLAG_CD: collision detected interrupt and flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag) -{ - uint32_t intenable = 0U, flagstatus = 0U; - /* get the interrupt enable bit status */ - intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag))); - /* get the corresponding flag bit status */ - flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag))); - - if((0U != flagstatus) && (0U != intenable)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear USART interrupt flag in STAT0/STAT1 register - \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) - \param[in] int_flag: USART interrupt flags, refer to usart_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg USART_INT_FLAG_CTS: CTS interrupt and flag - \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag - \arg USART_INT_FLAG_TC: transmission complete interrupt and flag - \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag - \arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag - \arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag - \arg USART_INT_FLAG_CD: collision detected interrupt and flag - \param[out] none - \retval none -*/ -void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag) -{ - USART_REG_VAL2(usart_periph, int_flag) = ~BIT(USART_BIT_POS2(int_flag)); -} - -/*! - \brief data is transmitted/received with the LSB/MSB first - \param[in] usart_periph: USART5 - \param[in] msbf: LSB/MSB - only one parameter can be selected which is shown as below: - \arg USART5_MSBF_LSB: LSB first - \arg USART5_MSBF_MSB: MSB first - \param[out] none - \retval none -*/ -void usart5_data_first_config(uint32_t usart_periph, uint32_t msbf) -{ - uint32_t ctl = 0U; - - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - ctl = USART5_CTL1(usart_periph); - ctl &= ~(USART5_CTL1_MSBF); - ctl |= (USART5_CTL1_MSBF & msbf); - /* configure data transmitted/received mode */ - USART5_CTL1(usart_periph) = ctl; -} - -/*! - \brief configure USART5 inversion - \param[in] usart_periph: USART5 - \param[in] invertpara: refer to enum USART5_INVERT_CONFIG - only one parameter can be selected which is shown as below: - \arg USART5_DINV_ENABLE: data bit level inversion - \arg USART5_DINV_DISABLE: data bit level not inversion - \arg USART5_TXPIN_ENABLE: TX pin level inversion - \arg USART5_TXPIN_DISABLE: TX pin level not inversion - \arg USART5_RXPIN_ENABLE: RX pin level inversion - \arg USART5_RXPIN_DISABLE: RX pin level not inversion - \arg USART5_SWAP_ENABLE: swap TX/RX pins - \arg USART5_SWAP_DISABLE: not swap TX/RX pins - \param[out] none - \retval none -*/ -void usart5_invert_config(uint32_t usart_periph, usart5_invert_enum invertpara) -{ - /* inverted or not the specified siginal */ - switch(invertpara){ - case USART5_DINV_ENABLE: - USART5_CTL1(usart_periph) |= USART5_CTL1_DINV; - break; - case USART5_DINV_DISABLE: - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_DINV); - break; - case USART5_TXPIN_ENABLE: - USART5_CTL1(usart_periph) |= USART5_CTL1_TINV; - break; - case USART5_TXPIN_DISABLE: - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_TINV); - break; - case USART5_RXPIN_ENABLE: - USART5_CTL1(usart_periph) |= USART5_CTL1_RINV; - break; - case USART5_RXPIN_DISABLE: - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_RINV); - break; - case USART5_SWAP_ENABLE: - USART5_CTL1(usart_periph) |= USART5_CTL1_STRP; - break; - case USART5_SWAP_DISABLE: - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_STRP); - break; - default: - break; - } -} - -/*! - \brief enable the USART5 overrun function - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_overrun_enable(uint32_t usart_periph) -{ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* enable overrun function */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_OVRD); -} - -/*! - \brief disable the USART5 overrun function - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_overrun_disable(uint32_t usart_periph) -{ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* disable overrun function */ - USART5_CTL2(usart_periph) |= USART5_CTL2_OVRD; -} - -/*! - \brief address of the USART terminal - \param[in] usart_periph: USART5 - \param[in] addr: address of USART terminal, 0x00000000-0x000000FF - \param[out] none - \retval none -*/ -void usart5_address_config(uint32_t usart_periph, uint8_t addr) -{ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_ADDR); - USART5_CTL1(usart_periph) |= (USART5_CTL1_ADDR & (((uint32_t)addr) << 24)); -} - -/*! - \brief configure address detection mode - \param[in] usart_periph: USART5 - \param[in] addmod: address detection mode - only one parameter can be selected which is shown as below: - \arg USART5_ADDM_4BIT: 4 bits - \arg USART5_ADDM_FULLBIT: full bits - \param[out] none - \retval none -*/ -void usart5_address_detection_mode_config(uint32_t usart_periph, uint32_t addmod) -{ - /* disable USART */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL1(usart_periph) &= ~(USART5_CTL1_ADDM); - USART5_CTL1(usart_periph) |= (USART5_CTL1_ADDM & addmod); -} - -/*! - \brief enable early NACK in smartcard mode - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_smartcard_mode_early_nack_enable(uint32_t usart_periph) -{ - USART5_RFCS(usart_periph) |= USART5_RFCS_ELNACK; -} - -/*! - \brief disable early NACK in smartcard mode - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_smartcard_mode_early_nack_disable(uint32_t usart_periph) -{ - USART5_RFCS(usart_periph) &= ~USART5_RFCS_ELNACK; -} - -/*! - \brief enable DMA on reception error - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_reception_error_dma_enable(uint32_t usart_periph) -{ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_DDRE); -} - -/*! - \brief disable DMA on reception error - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_reception_error_dma_disable(uint32_t usart_periph) -{ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - - USART5_CTL2(usart_periph) |= USART5_CTL2_DDRE; -} - -/*! - \brief enable USART to wakeup the mcu from deep-sleep mode - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_wakeup_enable(uint32_t usart_periph) -{ - USART5_CTL0(usart_periph) |= USART5_CTL0_UESM; -} - -/*! - \brief disable USART to wakeup the mcu from deep-sleep mode - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_wakeup_disable(uint32_t usart_periph) -{ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UESM); -} - -/*! - \brief configure the USART wakeup mode from deep-sleep mode - \param[in] usart_periph: USART5 - \param[in] wum: wakeup mode - only one parameter can be selected which is shown as below: - \arg USART5_WUM_ADDR: WUF active on address match - \arg USART5_WUM_STARTB: WUF active on start bit - \arg USART5_WUM_RBNE: WUF active on RBNE - \param[out] none - \retval none -*/ -void usart5_wakeup_mode_config(uint32_t usart_periph, uint32_t wum) -{ - /* disable USART5 */ - USART5_CTL0(usart_periph) &= ~(USART5_CTL0_UEN); - /* reset WUM bit */ - USART5_CTL2(usart_periph) &= ~(USART5_CTL2_WUM); - USART5_CTL2(usart_periph) |= (USART5_CTL2_WUM & wum); -} - -/*! - \brief enable receive FIFO - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_receive_fifo_enable(uint32_t usart_periph) -{ - USART5_RFCS(usart_periph) |= USART5_RFCS_RFEN; -} - -/*! - \brief disable receive FIFO - \param[in] usart_periph: USART5 - \param[out] none - \retval none -*/ -void usart5_receive_fifo_disable(uint32_t usart_periph) -{ - USART5_RFCS(usart_periph) &= ~(USART5_RFCS_RFEN); -} - -/*! - \brief read receive FIFO counter number - \param[in] usart_periph: USART5 - \param[out] none - \retval receive FIFO counter number -*/ -uint8_t usart5_receive_fifo_counter_number(uint32_t usart_periph) -{ - return (uint8_t)(GET_BITS(USART5_RFCS(usart_periph), 12U, 14U)); -} - -/*! - \brief get flag in STAT/CHC/RFCS register - \param[in] usart_periph: USART5 - \param[in] flag: flag type - only one parameter can be selected which is shown as below: - \arg USART5_FLAG_PERR: parity error flag - \arg USART5_FLAG_FERR: frame error flag - \arg USART5_FLAG_NERR: noise error flag - \arg USART5_FLAG_ORERR: overrun error - \arg USART5_FLAG_IDLE: idle line detected flag - \arg USART5_FLAG_RBNE: read data buffer not empty - \arg USART5_FLAG_TC: transmission completed - \arg USART5_FLAG_TBE: transmit data register empty - \arg USART5_FLAG_LBD: LIN break detected flag - \arg USART5_FLAG_RT: receiver timeout flag - \arg USART5_FLAG_EB: end of block flag - \arg USART5_FLAG_BSY: busy flag - \arg USART5_FLAG_AM: address match flag - \arg USART5_FLAG_SB: send break flag - \arg USART5_FLAG_RWU: receiver wakeup from mute mode. - \arg USART5_FLAG_WU: wakeup from deep-sleep mode flag - \arg USART5_FLAG_TEA: transmit enable acknowledge flag - \arg USART5_FLAG_REA: receive enable acknowledge flag - \arg USART5_FLAG_EPERR: early parity error flag - \arg USART5_FLAG_RFE: receive FIFO empty flag - \arg USART5_FLAG_RFF: receive FIFO full flag - \arg USART5_FLAG_RFFINT: receive FIFO full interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus usart5_flag_get(uint32_t usart_periph, usart5_flag_enum flag) -{ - if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear USART status - \param[in] usart_periph: USART5 - \param[in] flag: flag type - only one parameter can be selected which is shown as below: - \arg USART5_FLAG_PERR: parity error flag - \arg USART5_FLAG_FERR: frame error flag - \arg USART5_FLAG_NERR: noise detected flag - \arg USART5_FLAG_ORERR: overrun error flag - \arg USART5_FLAG_IDLE: idle line detected flag - \arg USART5_FLAG_TC: transmission complete flag - \arg USART5_FLAG_LBD: LIN break detected flag - \arg USART5_FLAG_RT: receiver timeout flag - \arg USART5_FLAG_EB: end of block flag - \arg USART5_FLAG_AM: address match flag - \arg USART5_FLAG_WU: wakeup from deep-sleep mode flag - \arg USART5_FLAG_EPERR: early parity error flag - \param[out] none - \retval none -*/ -void usart5_flag_clear(uint32_t usart_periph, usart5_flag_enum flag) -{ - USART5_INTC(usart_periph) |= BIT(USART_BIT_POS(flag)); -} - -/*! - \brief enable USART interrupt - \param[in] usart_periph: USART5 - \param[in] interrupt: USART5 interrupts, refer to usart5_interrupt_enum - only one parameter can be selected which is shown as below: - \arg USART5_INT_IDLE: idle interrupt - \arg USART5_INT_RBNE: read data buffer not empty interrupt and - overrun error interrupt enable interrupt - \arg USART5_INT_TC: transmission complete interrupt - \arg USART5_INT_TBE: transmit data register empty interrupt - \arg USART5_INT_PERR: parity error interrupt - \arg USART5_INT_AM: address match interrupt - \arg USART5_INT_RT: receiver timeout interrupt - \arg USART5_INT_EB: end of block interrupt - \arg USART5_INT_LBD: LIN break detection interrupt - \arg USART5_INT_ERR: error interrupt enable in multibuffer communication - \arg USART5_INT_WU: wakeup from deep-sleep mode interrupt - \arg USART5_INT_RFF: receive FIFO full interrupt enable - \param[out] none - \retval none -*/ -void usart5_interrupt_enable(uint32_t usart_periph, usart5_interrupt_enum interrupt) -{ - USART_REG_VAL(usart_periph, interrupt) |= BIT(USART_BIT_POS(interrupt)); -} - -/*! - \brief disable USART interrupt - \param[in] usart_periph: USART5 - \param[in] interrupt: USART5 interrupts, refer to usart5_interrupt_enum - only one parameter can be selected which is shown as below: - \arg USART5_INT_IDLE: idle interrupt - \arg USART5_INT_RBNE: read data buffer not empty interrupt and - overrun error interrupt - \arg USART5_INT_TC: transmission complete interrupt - \arg USART5_INT_TBE: transmit data register empty interrupt - \arg USART5_INT_PERR: parity error interrupt - \arg USART5_INT_AM: address match interrupt - \arg USART5_INT_RT: receiver timeout interrupt - \arg USART5_INT_EB: end of block interrupt - \arg USART5_INT_LBD: LIN break detection interrupt - \arg USART5_INT_ERR: error interrupt enable in multibuffer communication - \arg USART5_INT_WU: wakeup from deep-sleep mode interrupt - \arg USART5_INT_RFF: receive FIFO full interrupt enable - \param[out] none - \retval none -*/ -void usart5_interrupt_disable(uint32_t usart_periph, usart5_interrupt_enum interrupt) -{ - USART_REG_VAL(usart_periph, interrupt) &= ~BIT(USART_BIT_POS(interrupt)); -} - -/*! - \brief enable USART command - \param[in] usart_periph: USART5 - \param[in] cmdtype: command type - only one parameter can be selected which is shown as below: - \arg USART5_CMD_SBKCMD: send break command - \arg USART5_CMD_MMCMD: mute mode command - \arg USART5_CMD_RXFCMD: receive data flush command - \arg USART5_CMD_TXFCMD: transmit data flush request - \param[out] none - \retval none -*/ -void usart5_command_enable(uint32_t usart_periph, uint32_t cmdtype) -{ - USART5_CMD(usart_periph) |= (cmdtype); -} - -/*! - \brief get USART interrupt and flag status - \param[in] usart_periph: USART5 - \param[in] int_flag: interrupt and flag type, refer to usart5_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg USART5_INT_FLAG_EB: end of block interrupt and flag - \arg USART5_INT_FLAG_RT: receiver timeout interrupt and flag - \arg USART5_INT_FLAG_AM: address match interrupt and flag - \arg USART5_INT_FLAG_PERR: parity error interrupt and flag - \arg USART5_INT_FLAG_TBE: transmitter buffer empty interrupt and flag - \arg USART5_INT_FLAG_TC: transmission complete interrupt and flag - \arg USART5_INT_FLAG_RBNE: read data buffer not empty interrupt and flag - \arg USART5_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag - \arg USART5_INT_FLAG_IDLE: IDLE line detected interrupt and flag - \arg USART5_INT_FLAG_LBD: LIN break detected interrupt and flag - \arg USART5_INT_FLAG_WU: wakeup from deep-sleep mode interrupt and flag - \arg USART5_INT_FLAG_ERR_NERR: error interrupt and noise error flag - \arg USART5_INT_FLAG_ERR_ORERR: error interrupt and overrun error - \arg USART5_INT_FLAG_ERR_FERR: error interrupt and frame error flag - \arg USART5_INT_FLAG_RFF: receive FIFO full interrupt and flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus usart5_interrupt_flag_get(uint32_t usart_periph, usart5_interrupt_flag_enum int_flag) -{ - uint32_t intenable = 0U, flagstatus = 0U; - /* get the interrupt enable bit status */ - intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag))); - /* get the corresponding flag bit status */ - flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag))); - - if(flagstatus && intenable){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear USART interrupt flag - \param[in] usart_periph: USART5 - \param[in] int_flag: interrupt and flag type, refer to usart5_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg USART5_INT_FLAG_PERR: parity error interrupt and flag - \arg USART5_INT_FLAG_ERR_FERR: error interrupt and frame error flag - \arg USART5_INT_FLAG_ERR_NERR: error interrupt and noise error flag - \arg USART5_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag - \arg USART5_INT_FLAG_ERR_ORERR: error interrupt and overrun error - \arg USART5_INT_FLAG_IDLE: IDLE line detected interrupt and flag - \arg USART5_INT_FLAG_TC: transmission complete interrupt and flag - \arg USART5_INT_FLAG_LBD: LIN break detected interrupt and flag - \arg USART5_INT_FLAG_RT: receiver timeout interrupt and flag - \arg USART5_INT_FLAG_EB: end of block interrupt and flag - \arg USART5_INT_FLAG_AM: address match interrupt and flag - \arg USART5_INT_FLAG_WU: wakeup from deep-sleep mode interrupt and flag - \arg USART5_INT_FLAG_RFF: receive FIFO full interrupt and flag - \param[out] none - \retval none -*/ -void usart5_interrupt_flag_clear(uint32_t usart_periph, usart5_interrupt_flag_enum int_flag) -{ - if(USART5_INT_FLAG_RFF == int_flag){ - USART5_RFCS(usart_periph) &= (uint32_t)(~USART5_RFCS_RFFINT); - }else{ - USART5_INTC(usart_periph) |= BIT(USART_BIT_POS2(int_flag)); - } -} diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/regions_GD32E508VE.h b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/regions_GD32E508VE.h deleted file mode 100644 index 68d0696..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/regions_GD32E508VE.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef REGIONS_GD32E508VE_H -#define REGIONS_GD32E508VE_H - - -//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- -//------ With VS Code: Open Preview for Configuration Wizard ------------------- - -// Auto-generated using information from packs -// Device Family Pack (DFP): GigaDevice::GD32E50x_DFP@1.9.0 - -// ROM Configuration -// ======================= -// __ROM0 (is rx memory: IROM1 from DFP) -// Base address <0x0-0xFFFFFFFF:8> -// Defines base address of memory region. Default: 0x08000000 -// Contains Startup and Vector Table -#define __ROM0_BASE 0x08000000 -// Region size [bytes] <0x0-0xFFFFFFFF:8> -// Defines size of memory region. Default: 0x00080000 -#define __ROM0_SIZE 0x00080000 -// - -// __ROM1 (unused) -// Base address <0x0-0xFFFFFFFF:8> -// Defines base address of memory region. -#define __ROM1_BASE 0x0 -// Region size [bytes] <0x0-0xFFFFFFFF:8> -// Defines size of memory region. -#define __ROM1_SIZE 0x0 -// - -// __ROM2 (unused) -// Base address <0x0-0xFFFFFFFF:8> -// Defines base address of memory region. -#define __ROM2_BASE 0x0 -// Region size [bytes] <0x0-0xFFFFFFFF:8> -// Defines size of memory region. -#define __ROM2_SIZE 0x0 -// - -// __ROM3 (unused) -// Base address <0x0-0xFFFFFFFF:8> -// Defines base address of memory region. -#define __ROM3_BASE 0x0 -// Region size [bytes] <0x0-0xFFFFFFFF:8> -// Defines size of memory region. -#define __ROM3_SIZE 0x0 -// - -// - -// RAM Configuration -// ======================= -// __RAM0 (is rwx memory: IRAM1 from DFP) -// Base address <0x0-0xFFFFFFFF:8> -// Defines base address of memory region. Default: 0x20000000 -// Contains uninitialized RAM, Stack, and Heap -#define __RAM0_BASE 0x20000000 -// Region size [bytes] <0x0-0xFFFFFFFF:8> -// Defines size of memory region. Default: 0x00020000 -#define __RAM0_SIZE 0x00020000 -// - -// __RAM1 (unused) -// Base address <0x0-0xFFFFFFFF:8> -// Defines base address of memory region. -#define __RAM1_BASE 0x0 -// Region size [bytes] <0x0-0xFFFFFFFF:8> -// Defines size of memory region. -#define __RAM1_SIZE 0x0 -// - -// __RAM2 (unused) -// Base address <0x0-0xFFFFFFFF:8> -// Defines base address of memory region. -#define __RAM2_BASE 0x0 -// Region size [bytes] <0x0-0xFFFFFFFF:8> -// Defines size of memory region. -#define __RAM2_SIZE 0x0 -// - -// __RAM3 (unused) -// Base address <0x0-0xFFFFFFFF:8> -// Defines base address of memory region. -#define __RAM3_BASE 0x0 -// Region size [bytes] <0x0-0xFFFFFFFF:8> -// Defines size of memory region. -#define __RAM3_SIZE 0x0 -// - -// - -// Stack / Heap Configuration -// Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> -// Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> -#define __STACK_SIZE 0x00000200 -#define __HEAP_SIZE 0x00000C00 -// - - -#endif /* REGIONS_GD32E508VE_H */ diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/startup_gd32e50x_cl.s b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/startup_gd32e50x_cl.s deleted file mode 100644 index 42956e4..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/startup_gd32e50x_cl.s +++ /dev/null @@ -1,434 +0,0 @@ -;/*! -; \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 */ - - -; Stack Configuration -; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - -Stack_Size EQU 0x00000800 - - AREA STACK, NOINIT, READWRITE, ALIGN=3 -Stack_Mem SPACE Stack_Size -__initial_sp - - -; Heap Configuration -; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - -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 diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/startup_gd32e50x_cl.s.base@1.5.0 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/startup_gd32e50x_cl.s.base@1.5.0 deleted file mode 100644 index 42956e4..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/startup_gd32e50x_cl.s.base@1.5.0 +++ /dev/null @@ -1,434 +0,0 @@ -;/*! -; \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 */ - - -; Stack Configuration -; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - -Stack_Size EQU 0x00000800 - - AREA STACK, NOINIT, READWRITE, ALIGN=3 -Stack_Mem SPACE Stack_Size -__initial_sp - - -; Heap Configuration -; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - -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 diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/system_gd32e50x.c b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/system_gd32e50x.c deleted file mode 100644 index 62360fe..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/system_gd32e50x.c +++ /dev/null @@ -1,1175 +0,0 @@ -/*! - \file system_gd32e50x.c - \brief CMSIS Cortex-M33 Device Peripheral Access Layer Source File for - GD32E50x Device Series -*/ - -/* - * 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 */ - -#include "gd32e50x.h" - -/* system frequency define */ -#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ -#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ - -#define VECT_TAB_OFFSET (uint32_t)0x00 /* vector table base offset */ - -/* select a system clock by uncommenting the following line */ -/* use IRC8M */ -//#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M) -//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000) -//#define __SYSTEM_CLOCK_120M_PLL_IRC8M (uint32_t)(120000000) -//#define __SYSTEM_CLOCK_168M_PLL_IRC8M (uint32_t)(168000000) -//#define __SYSTEM_CLOCK_180M_PLL_IRC8M (uint32_t)(180000000) - -/* use HXTAL(EPRT/HD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */ -//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL) -//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) -//#define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000) -//#define __SYSTEM_CLOCK_168M_PLL_HXTAL (uint32_t)(168000000) -#define __SYSTEM_CLOCK_180M_PLL_HXTAL (uint32_t)(180000000) - -/* The following is to prevent Vcore fluctuations caused by frequency switching. - It is strongly recommended to include it to avoid issues caused by self-removal. */ -#define RCU_MODIFY(__delay) do{ \ - volatile uint32_t i,reg;; \ - if(0 != __delay){ \ - /* Insert a software delay */ \ - for(i=0; i<__delay; i++){ \ - } \ - reg = RCU_CFG0; \ - reg &= ~(RCU_CFG0_AHBPSC); \ - reg |= RCU_AHB_CKSYS_DIV2; \ - /* AHB = SYSCLK/2 */ \ - RCU_CFG0 = reg; \ - /* Insert a software delay */ \ - for(i=0; i<__delay; i++){ \ - } \ - reg = RCU_CFG0; \ - reg &= ~(RCU_CFG0_AHBPSC); \ - reg |= RCU_AHB_CKSYS_DIV4; \ - /* AHB = SYSCLK/4 */ \ - RCU_CFG0 = reg; \ - /* Insert a software delay */ \ - for(i=0; i<__delay; i++){ \ - } \ - } \ - }while(0) - - -/* The following is to prevent Vcore fluctuations caused by frequency switching. - It is strongly recommended to include it to avoid issues caused by self-removal. */ -#define RCU_MODIFY_UP(__delay) do{ \ - volatile uint32_t i,reg; \ - if(0 != __delay){ \ - for(i=0; i<__delay; i++){ \ - } \ - reg = RCU_CFG0; \ - reg &= ~(RCU_CFG0_AHBPSC); \ - reg |= RCU_AHB_CKSYS_DIV2; \ - RCU_CFG0 = reg; \ - for(i=0; i<__delay; i++){ \ - } \ - reg = RCU_CFG0; \ - reg &= ~(RCU_CFG0_AHBPSC); \ - reg |= RCU_AHB_CKSYS_DIV1; \ - RCU_CFG0 = reg; \ - } \ - }while(0) - -#define HXTALSTB_DELAY { \ - volatile uint32_t i; \ - for(i=0; i<0x1000; i++){ \ - } \ - } - -#define SEL_IRC8M 0x00 -#define SEL_HXTAL 0x01 -#define SEL_PLL 0x02 - -/* set the system clock frequency and declare the system clock configuration function */ -#ifdef __SYSTEM_CLOCK_IRC8M -uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC8M; -static void system_clock_8m_irc8m(void); -#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M; -static void system_clock_72m_irc8m(void); -#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_IRC8M; -static void system_clock_120m_irc8m(void); -#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC8M) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_168M_PLL_IRC8M; -static void system_clock_168m_irc8m(void); -#elif defined (__SYSTEM_CLOCK_180M_PLL_IRC8M) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_180M_PLL_IRC8M; -static void system_clock_180m_irc8m(void); - -#elif defined (__SYSTEM_CLOCK_HXTAL) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL; -static void system_clock_hxtal(void); -#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; -static void system_clock_72m_hxtal(void); -#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_HXTAL; -static void system_clock_120m_hxtal(void); -#elif defined (__SYSTEM_CLOCK_168M_PLL_HXTAL) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_168M_PLL_HXTAL; -static void system_clock_168m_hxtal(void); -#elif defined (__SYSTEM_CLOCK_180M_PLL_HXTAL) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_180M_PLL_HXTAL; -static void system_clock_180m_hxtal(void); -#endif /* __SYSTEM_CLOCK_IRC8M */ - -/* configure the system clock */ -static void system_clock_config(void); -/* software delay to prevent the impact of Vcore fluctuations. - It is strongly recommended to include it to avoid issues caused by self-removal. */ -static void _soft_delay_(uint32_t time) -{ - __IO uint32_t i; - for(i=0; iCPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ -#endif - /* reset the RCU clock configuration to the default reset state */ - /* Set IRC8MEN bit */ - RCU_CTL |= RCU_CTL_IRC8MEN; - while(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - } - if(((RCU_CFG0 & RCU_CFG0_SCSS) == RCU_SCSS_PLL)){ - RCU_MODIFY(0x100); - } - RCU_CFG0 &= ~RCU_CFG0_SCS; - _soft_delay_(100); -#if (defined(GD32EPRT) || defined(GD32E50X_HD)) - /* reset HXTALEN, CKMEN and PLLEN bits */ - RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); - /* disable all interrupts */ - RCU_INT = 0x009f0000U; -#elif (defined(GD32E50X_CL) || defined(GD32E508)) - /* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */ - RCU_CTL &= ~(RCU_CTL_PLLEN |RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); - /* disable all interrupts */ - RCU_INT = 0x00ff0000U; -#endif /* GD32E50X_EPRT and GD32E50X_HD */ - - /* Reset CFG0 and CFG1 registers */ - RCU_CFG0 = 0x00000000U; - RCU_CFG1 = 0x00000000U; - /* reset HXTALBPS bit */ - RCU_CTL &= ~(RCU_CTL_HXTALBPS); - - /* configure the system clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ - system_clock_config(); - -#ifdef VECT_TAB_SRAM - nvic_vector_table_set(NVIC_VECTTAB_RAM,VECT_TAB_OFFSET); -#else - nvic_vector_table_set(NVIC_VECTTAB_FLASH,VECT_TAB_OFFSET); -#endif -} - -/*! - \brief configure the system clock - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_config(void) -{ -#ifdef __SYSTEM_CLOCK_IRC8M - system_clock_8m_irc8m(); -#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) - system_clock_72m_irc8m(); -#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) - system_clock_120m_irc8m(); -#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC8M) - system_clock_168m_irc8m(); -#elif defined (__SYSTEM_CLOCK_180M_PLL_IRC8M) - system_clock_180m_irc8m(); - -#elif defined (__SYSTEM_CLOCK_HXTAL) - system_clock_hxtal(); -#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) - system_clock_72m_hxtal(); -#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) - system_clock_120m_hxtal(); -#elif defined (__SYSTEM_CLOCK_168M_PLL_HXTAL) - system_clock_168m_hxtal(); -#elif defined (__SYSTEM_CLOCK_180M_PLL_HXTAL) - system_clock_180m_hxtal(); -#endif /* __SYSTEM_CLOCK_IRC8M */ -} - -#ifdef __SYSTEM_CLOCK_IRC8M -/*! - \brief configure the system clock to 8M by IRC8M - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_8m_irc8m(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - - /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - } - while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ - } - } - - /* AHB = SYSCLK */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - reg_temp = RCU_CFG0; - /* select IRC8M as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_IRC8M; - RCU_CFG0 = reg_temp; - - /* wait until IRC8M is selected as system clock */ - while(RCU_SCSS_IRC8M != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } -} - -#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) -/*! - \brief configure the system clock to 72M by PLL which selects IRC8M as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_72m_irc8m(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - - /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - } - while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(1); - - /* LDO output voltage high mode */ - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* IRC8M is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL18; - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 120 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) -/*! - \brief configure the system clock to 120M by PLL which selects IRC8M as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_120m_irc8m(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - - /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(3); - - /* LDO output voltage high mode */ - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* IRC8M is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - /* CK_PLL = (CK_IRC8M/2) * 30 = 120 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL30; - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 120 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC8M) -/*! - \brief configure the system clock to 168M by PLL which selects IRC8M as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_168m_irc8m(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - - /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4); - - /* LDO output voltage high mode */ - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* IRC8M is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - /* CK_PLL = (CK_IRC8M/2) * 42 = 168 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL42; - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 120 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_180M_PLL_IRC8M) -/*! - \brief configure the system clock to 180M by PLL which selects IRC8M as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_180m_irc8m(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - - /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4); - - /* LDO output voltage high mode */ - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* IRC8M is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - /* CK_PLL = (CK_IRC8M/2) * 45 = 180 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL45; - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 120 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_HXTAL) -/*! - \brief configure the system clock to HXTAL - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - HXTALSTB_DELAY - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - /* AHB = SYSCLK */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - reg_temp = RCU_CFG0; - /* select HXTAL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_HXTAL; - RCU_CFG0 = reg_temp; - - /* wait until HXTAL is selected as system clock */ - while(RCU_SCSS_HXTAL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } -} - -#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) -/*! - \brief configure the system clock to 72M by PLL which selects HXTAL as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_72m_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - HXTALSTB_DELAY - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(1); - - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* HXTAL is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - -#if defined(GD32E50X_HD) - /* select HXTAL/2 as clock source */ - RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); - - /* CK_PLL = (CK_HXTAL/2) * 18 = 72 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL18; - -#elif (defined(GD32E50X_CL) || defined(GD32E508)) - /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL18); - - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } - -#elif defined(GD32EPRT) - /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL18); - - /* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } -#endif /* GD32E50X_HD */ - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 180 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} -#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) -/*! - \brief configure the system clock to 72M by PLL which selects HXTAL as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_120m_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - HXTALSTB_DELAY - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(3); - - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* HXTAL is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - -#if defined(GD32E50X_HD) - /* select HXTAL/2 as clock source */ - RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); - - /* CK_PLL = (CK_HXTAL/2) * 30 = 120 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL30; - -#elif (defined(GD32E50X_CL) || defined(GD32E508)) - /* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30); - - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } - -#elif defined(GD32EPRT) - /* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30); - - /* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } -#endif /* GD32F50X_HD */ - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 180 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_168M_PLL_HXTAL) -/*! - \brief configure the system clock to 108M by PLL which selects HXTAL as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_168m_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - HXTALSTB_DELAY - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4); - - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* HXTAL is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - -#if defined(GD32E50X_HD) - /* select HXTAL/2 as clock source */ - RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); - - /* CK_PLL = (CK_HXTAL/2) * 42 = 168 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL42; - -#elif (defined(GD32E50X_CL) || defined(GD32E508)) - /* CK_PLL = (CK_PREDIV0) * 42 = 168 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL42); - - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } - -#elif defined(GD32EPRT) - /* CK_PLL = (CK_PREDIV0) * 42 = 168 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL42); - - /* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } -#endif /* GD32F50X_HD */ - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 180 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_180M_PLL_HXTAL) -/*! - \brief configure the system clock to 180M by PLL which selects HXTAL as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_180m_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - HXTALSTB_DELAY - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4); - - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* HXTAL is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - -#if defined(GD32E50X_HD) - /* select HXTAL/2 as clock source */ - RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); - - /* CK_PLL = (CK_HXTAL/2) * 45 = 180 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL45; - -#elif (defined(GD32E50X_CL) || defined(GD32E508)) - /* CK_PLL = (CK_PREDIV0) * 45 = 180 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL45); - - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10) ; - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } - -#elif defined(GD32EPRT) - /* CK_PLL = (CK_PREDIV0) * 45 = 180 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL45); - - /* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } -#endif /* GD32F50X_HD */ - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 180 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} -#endif /* __SYSTEM_CLOCK_IRC8M */ - -/*! - \brief update the SystemCoreClock with current core clock retrieved from CPU registers - \param[in] none - \param[out] none - \retval none -*/ -void SystemCoreClockUpdate (void) -{ - uint32_t sws; - uint32_t pllsel, pllpresel, predv0sel, pllmf, ck_src, idx, clk_exp; -#if (defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)) - uint32_t predv0, predv1, pll1mf; -#endif /* GD32E50X_CL and GD32EPRT*/ - - /* exponent of AHB, APB1 and APB2 clock divider */ - uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; - - sws = GET_BITS(RCU_CFG0, 2, 3); - switch(sws){ - /* IRC8M is selected as CK_SYS */ - case SEL_IRC8M: - SystemCoreClock = IRC8M_VALUE; - break; - /* HXTAL is selected as CK_SYS */ - case SEL_HXTAL: - SystemCoreClock = HXTAL_VALUE; - break; - /* PLL is selected as CK_SYS */ - case SEL_PLL: - /* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */ - pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); - - if(RCU_PLLSRC_HXTAL_IRC48M == pllsel) { - /* PLL clock source is HXTAL or IRC48M */ - pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL); - - if(RCU_PLLPRESRC_HXTAL == pllpresel){ - /* PLL clock source is HXTAL */ - ck_src = HXTAL_VALUE; - }else{ - /* PLL clock source is IRC48 */ - ck_src = IRC48M_VALUE; - } - -#if defined(GD32E50X_HD) - predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); - /* PREDV0 input source clock divided by 2 */ - if(RCU_CFG0_PREDV0 == predv0sel){ - ck_src = ck_src/2U; - } -#elif (defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)) - predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); - /* source clock use PLL1 */ - if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ - predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> ((uint32_t)4U)) + 1U; - pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> ((uint32_t)8U)) + 2U; - if(17U == pll1mf){ - pll1mf = 20U; - } - ck_src = (ck_src/predv1)*pll1mf; - } - predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; - ck_src /= predv0; -#endif /* GD32E50X_HD */ - }else{ - /* PLL clock source is IRC8M/2 */ - ck_src = IRC8M_VALUE/2U; - } - - /* PLL multiplication factor */ - pllmf = GET_BITS(RCU_CFG0, 18, 21); - if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ - pllmf |= 0x10U; - } - if((RCU_CFG0 & RCU_CFG0_PLLMF_5)){ - pllmf |= 0x20U; - } - if(pllmf < 15U){ - pllmf += 2U; - }else if((pllmf >= 15U) && (pllmf <= 64U)){ - pllmf += 1U; - }else{ - } - SystemCoreClock = ck_src*pllmf; -#if (defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)) - if(15U == pllmf){ - SystemCoreClock = ck_src*6U + ck_src/2U; - } -#endif /* GD32E50X_CL and GD32EPRT and GD32E508 */ - - break; - /* IRC8M is selected as CK_SYS */ - default: - SystemCoreClock = IRC8M_VALUE; - break; - } - - /* calculate AHB clock frequency */ - idx = GET_BITS(RCU_CFG0, 4, 7); - clk_exp = ahb_exp[idx]; - SystemCoreClock >>= clk_exp; -} - -#ifdef __FIRMWARE_VERSION_DEFINE -/*! - \brief get firmware version - \param[in] none - \param[out] none - \retval firmware version -*/ -uint32_t gd32e50x_firmware_version_get(void) -{ - return __GD32E50X_STDPERIPH_VERSION; -} -#endif /* __FIRMWARE_VERSION_DEFINE */ diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/system_gd32e50x.c.base@1.2.4 b/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/system_gd32e50x.c.base@1.2.4 deleted file mode 100644 index 62360fe..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/Device/GD32E508VE/system_gd32e50x.c.base@1.2.4 +++ /dev/null @@ -1,1175 +0,0 @@ -/*! - \file system_gd32e50x.c - \brief CMSIS Cortex-M33 Device Peripheral Access Layer Source File for - GD32E50x Device Series -*/ - -/* - * 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 */ - -#include "gd32e50x.h" - -/* system frequency define */ -#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ -#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ - -#define VECT_TAB_OFFSET (uint32_t)0x00 /* vector table base offset */ - -/* select a system clock by uncommenting the following line */ -/* use IRC8M */ -//#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M) -//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000) -//#define __SYSTEM_CLOCK_120M_PLL_IRC8M (uint32_t)(120000000) -//#define __SYSTEM_CLOCK_168M_PLL_IRC8M (uint32_t)(168000000) -//#define __SYSTEM_CLOCK_180M_PLL_IRC8M (uint32_t)(180000000) - -/* use HXTAL(EPRT/HD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */ -//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL) -//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) -//#define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000) -//#define __SYSTEM_CLOCK_168M_PLL_HXTAL (uint32_t)(168000000) -#define __SYSTEM_CLOCK_180M_PLL_HXTAL (uint32_t)(180000000) - -/* The following is to prevent Vcore fluctuations caused by frequency switching. - It is strongly recommended to include it to avoid issues caused by self-removal. */ -#define RCU_MODIFY(__delay) do{ \ - volatile uint32_t i,reg;; \ - if(0 != __delay){ \ - /* Insert a software delay */ \ - for(i=0; i<__delay; i++){ \ - } \ - reg = RCU_CFG0; \ - reg &= ~(RCU_CFG0_AHBPSC); \ - reg |= RCU_AHB_CKSYS_DIV2; \ - /* AHB = SYSCLK/2 */ \ - RCU_CFG0 = reg; \ - /* Insert a software delay */ \ - for(i=0; i<__delay; i++){ \ - } \ - reg = RCU_CFG0; \ - reg &= ~(RCU_CFG0_AHBPSC); \ - reg |= RCU_AHB_CKSYS_DIV4; \ - /* AHB = SYSCLK/4 */ \ - RCU_CFG0 = reg; \ - /* Insert a software delay */ \ - for(i=0; i<__delay; i++){ \ - } \ - } \ - }while(0) - - -/* The following is to prevent Vcore fluctuations caused by frequency switching. - It is strongly recommended to include it to avoid issues caused by self-removal. */ -#define RCU_MODIFY_UP(__delay) do{ \ - volatile uint32_t i,reg; \ - if(0 != __delay){ \ - for(i=0; i<__delay; i++){ \ - } \ - reg = RCU_CFG0; \ - reg &= ~(RCU_CFG0_AHBPSC); \ - reg |= RCU_AHB_CKSYS_DIV2; \ - RCU_CFG0 = reg; \ - for(i=0; i<__delay; i++){ \ - } \ - reg = RCU_CFG0; \ - reg &= ~(RCU_CFG0_AHBPSC); \ - reg |= RCU_AHB_CKSYS_DIV1; \ - RCU_CFG0 = reg; \ - } \ - }while(0) - -#define HXTALSTB_DELAY { \ - volatile uint32_t i; \ - for(i=0; i<0x1000; i++){ \ - } \ - } - -#define SEL_IRC8M 0x00 -#define SEL_HXTAL 0x01 -#define SEL_PLL 0x02 - -/* set the system clock frequency and declare the system clock configuration function */ -#ifdef __SYSTEM_CLOCK_IRC8M -uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC8M; -static void system_clock_8m_irc8m(void); -#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M; -static void system_clock_72m_irc8m(void); -#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_IRC8M; -static void system_clock_120m_irc8m(void); -#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC8M) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_168M_PLL_IRC8M; -static void system_clock_168m_irc8m(void); -#elif defined (__SYSTEM_CLOCK_180M_PLL_IRC8M) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_180M_PLL_IRC8M; -static void system_clock_180m_irc8m(void); - -#elif defined (__SYSTEM_CLOCK_HXTAL) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL; -static void system_clock_hxtal(void); -#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; -static void system_clock_72m_hxtal(void); -#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_HXTAL; -static void system_clock_120m_hxtal(void); -#elif defined (__SYSTEM_CLOCK_168M_PLL_HXTAL) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_168M_PLL_HXTAL; -static void system_clock_168m_hxtal(void); -#elif defined (__SYSTEM_CLOCK_180M_PLL_HXTAL) -uint32_t SystemCoreClock = __SYSTEM_CLOCK_180M_PLL_HXTAL; -static void system_clock_180m_hxtal(void); -#endif /* __SYSTEM_CLOCK_IRC8M */ - -/* configure the system clock */ -static void system_clock_config(void); -/* software delay to prevent the impact of Vcore fluctuations. - It is strongly recommended to include it to avoid issues caused by self-removal. */ -static void _soft_delay_(uint32_t time) -{ - __IO uint32_t i; - for(i=0; iCPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ -#endif - /* reset the RCU clock configuration to the default reset state */ - /* Set IRC8MEN bit */ - RCU_CTL |= RCU_CTL_IRC8MEN; - while(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - } - if(((RCU_CFG0 & RCU_CFG0_SCSS) == RCU_SCSS_PLL)){ - RCU_MODIFY(0x100); - } - RCU_CFG0 &= ~RCU_CFG0_SCS; - _soft_delay_(100); -#if (defined(GD32EPRT) || defined(GD32E50X_HD)) - /* reset HXTALEN, CKMEN and PLLEN bits */ - RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); - /* disable all interrupts */ - RCU_INT = 0x009f0000U; -#elif (defined(GD32E50X_CL) || defined(GD32E508)) - /* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */ - RCU_CTL &= ~(RCU_CTL_PLLEN |RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); - /* disable all interrupts */ - RCU_INT = 0x00ff0000U; -#endif /* GD32E50X_EPRT and GD32E50X_HD */ - - /* Reset CFG0 and CFG1 registers */ - RCU_CFG0 = 0x00000000U; - RCU_CFG1 = 0x00000000U; - /* reset HXTALBPS bit */ - RCU_CTL &= ~(RCU_CTL_HXTALBPS); - - /* configure the system clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ - system_clock_config(); - -#ifdef VECT_TAB_SRAM - nvic_vector_table_set(NVIC_VECTTAB_RAM,VECT_TAB_OFFSET); -#else - nvic_vector_table_set(NVIC_VECTTAB_FLASH,VECT_TAB_OFFSET); -#endif -} - -/*! - \brief configure the system clock - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_config(void) -{ -#ifdef __SYSTEM_CLOCK_IRC8M - system_clock_8m_irc8m(); -#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) - system_clock_72m_irc8m(); -#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) - system_clock_120m_irc8m(); -#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC8M) - system_clock_168m_irc8m(); -#elif defined (__SYSTEM_CLOCK_180M_PLL_IRC8M) - system_clock_180m_irc8m(); - -#elif defined (__SYSTEM_CLOCK_HXTAL) - system_clock_hxtal(); -#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) - system_clock_72m_hxtal(); -#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) - system_clock_120m_hxtal(); -#elif defined (__SYSTEM_CLOCK_168M_PLL_HXTAL) - system_clock_168m_hxtal(); -#elif defined (__SYSTEM_CLOCK_180M_PLL_HXTAL) - system_clock_180m_hxtal(); -#endif /* __SYSTEM_CLOCK_IRC8M */ -} - -#ifdef __SYSTEM_CLOCK_IRC8M -/*! - \brief configure the system clock to 8M by IRC8M - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_8m_irc8m(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - - /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - } - while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ - } - } - - /* AHB = SYSCLK */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - reg_temp = RCU_CFG0; - /* select IRC8M as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_IRC8M; - RCU_CFG0 = reg_temp; - - /* wait until IRC8M is selected as system clock */ - while(RCU_SCSS_IRC8M != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } -} - -#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) -/*! - \brief configure the system clock to 72M by PLL which selects IRC8M as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_72m_irc8m(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - - /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - } - while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(1); - - /* LDO output voltage high mode */ - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* IRC8M is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL18; - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 120 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) -/*! - \brief configure the system clock to 120M by PLL which selects IRC8M as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_120m_irc8m(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - - /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(3); - - /* LDO output voltage high mode */ - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* IRC8M is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - /* CK_PLL = (CK_IRC8M/2) * 30 = 120 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL30; - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 120 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC8M) -/*! - \brief configure the system clock to 168M by PLL which selects IRC8M as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_168m_irc8m(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - - /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4); - - /* LDO output voltage high mode */ - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* IRC8M is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - /* CK_PLL = (CK_IRC8M/2) * 42 = 168 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL42; - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 120 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_180M_PLL_IRC8M) -/*! - \brief configure the system clock to 180M by PLL which selects IRC8M as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_180m_irc8m(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - - /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4); - - /* LDO output voltage high mode */ - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* IRC8M is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - /* CK_PLL = (CK_IRC8M/2) * 45 = 180 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL45; - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 120 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_HXTAL) -/*! - \brief configure the system clock to HXTAL - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - HXTALSTB_DELAY - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - /* AHB = SYSCLK */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - reg_temp = RCU_CFG0; - /* select HXTAL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_HXTAL; - RCU_CFG0 = reg_temp; - - /* wait until HXTAL is selected as system clock */ - while(RCU_SCSS_HXTAL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } -} - -#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) -/*! - \brief configure the system clock to 72M by PLL which selects HXTAL as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_72m_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - HXTALSTB_DELAY - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(1); - - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* HXTAL is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - -#if defined(GD32E50X_HD) - /* select HXTAL/2 as clock source */ - RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); - - /* CK_PLL = (CK_HXTAL/2) * 18 = 72 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL18; - -#elif (defined(GD32E50X_CL) || defined(GD32E508)) - /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL18); - - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } - -#elif defined(GD32EPRT) - /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL18); - - /* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } -#endif /* GD32E50X_HD */ - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 180 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} -#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) -/*! - \brief configure the system clock to 72M by PLL which selects HXTAL as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_120m_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - HXTALSTB_DELAY - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(3); - - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* HXTAL is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - -#if defined(GD32E50X_HD) - /* select HXTAL/2 as clock source */ - RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); - - /* CK_PLL = (CK_HXTAL/2) * 30 = 120 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL30; - -#elif (defined(GD32E50X_CL) || defined(GD32E508)) - /* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30); - - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } - -#elif defined(GD32EPRT) - /* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30); - - /* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } -#endif /* GD32F50X_HD */ - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 180 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_168M_PLL_HXTAL) -/*! - \brief configure the system clock to 108M by PLL which selects HXTAL as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_168m_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - HXTALSTB_DELAY - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4); - - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* HXTAL is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - -#if defined(GD32E50X_HD) - /* select HXTAL/2 as clock source */ - RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); - - /* CK_PLL = (CK_HXTAL/2) * 42 = 168 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL42; - -#elif (defined(GD32E50X_CL) || defined(GD32E508)) - /* CK_PLL = (CK_PREDIV0) * 42 = 168 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL42); - - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } - -#elif defined(GD32EPRT) - /* CK_PLL = (CK_PREDIV0) * 42 = 168 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL42); - - /* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } -#endif /* GD32F50X_HD */ - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 180 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} - -#elif defined (__SYSTEM_CLOCK_180M_PLL_HXTAL) -/*! - \brief configure the system clock to 180M by PLL which selects HXTAL as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_180m_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - __IO uint32_t reg_temp; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - HXTALSTB_DELAY - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(4); - - RCU_APB1EN |= RCU_APB1EN_PMUEN; - - /* HXTAL is stable */ - /* AHB = SYSCLK/4 */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - -#if defined(GD32E50X_HD) - /* select HXTAL/2 as clock source */ - RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); - - /* CK_PLL = (CK_HXTAL/2) * 45 = 180 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= RCU_PLL_MUL45; - -#elif (defined(GD32E50X_CL) || defined(GD32E508)) - /* CK_PLL = (CK_PREDIV0) * 45 = 180 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL45); - - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10) ; - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } - -#elif defined(GD32EPRT) - /* CK_PLL = (CK_PREDIV0) * 45 = 180 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL45); - - /* CK_PREDIV0 = (CK_HXTAL)/2 *8 /8 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV8); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ - } -#endif /* GD32F50X_HD */ - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* enable the high-drive to extend the clock frequency to 180 MHz */ - PMU_CTL0 |= PMU_CTL0_HDEN; - while(0U == (PMU_CS0 & PMU_CS0_HDRF)){ - } - - /* select the high-drive mode */ - PMU_CTL0 |= PMU_CTL0_HDS; - while(0U == (PMU_CS0 & PMU_CS0_HDSRF)){ - } - - reg_temp = RCU_CFG0; - /* select PLL as system clock */ - reg_temp &= ~RCU_CFG0_SCS; - reg_temp |= RCU_CKSYSSRC_PLL; - RCU_CFG0 = reg_temp; - - /* wait until PLL is selected as system clock */ - while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)){ - } - RCU_MODIFY_UP(0x50); -} -#endif /* __SYSTEM_CLOCK_IRC8M */ - -/*! - \brief update the SystemCoreClock with current core clock retrieved from CPU registers - \param[in] none - \param[out] none - \retval none -*/ -void SystemCoreClockUpdate (void) -{ - uint32_t sws; - uint32_t pllsel, pllpresel, predv0sel, pllmf, ck_src, idx, clk_exp; -#if (defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)) - uint32_t predv0, predv1, pll1mf; -#endif /* GD32E50X_CL and GD32EPRT*/ - - /* exponent of AHB, APB1 and APB2 clock divider */ - uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; - - sws = GET_BITS(RCU_CFG0, 2, 3); - switch(sws){ - /* IRC8M is selected as CK_SYS */ - case SEL_IRC8M: - SystemCoreClock = IRC8M_VALUE; - break; - /* HXTAL is selected as CK_SYS */ - case SEL_HXTAL: - SystemCoreClock = HXTAL_VALUE; - break; - /* PLL is selected as CK_SYS */ - case SEL_PLL: - /* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */ - pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); - - if(RCU_PLLSRC_HXTAL_IRC48M == pllsel) { - /* PLL clock source is HXTAL or IRC48M */ - pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL); - - if(RCU_PLLPRESRC_HXTAL == pllpresel){ - /* PLL clock source is HXTAL */ - ck_src = HXTAL_VALUE; - }else{ - /* PLL clock source is IRC48 */ - ck_src = IRC48M_VALUE; - } - -#if defined(GD32E50X_HD) - predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); - /* PREDV0 input source clock divided by 2 */ - if(RCU_CFG0_PREDV0 == predv0sel){ - ck_src = ck_src/2U; - } -#elif (defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)) - predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); - /* source clock use PLL1 */ - if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ - predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> ((uint32_t)4U)) + 1U; - pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> ((uint32_t)8U)) + 2U; - if(17U == pll1mf){ - pll1mf = 20U; - } - ck_src = (ck_src/predv1)*pll1mf; - } - predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; - ck_src /= predv0; -#endif /* GD32E50X_HD */ - }else{ - /* PLL clock source is IRC8M/2 */ - ck_src = IRC8M_VALUE/2U; - } - - /* PLL multiplication factor */ - pllmf = GET_BITS(RCU_CFG0, 18, 21); - if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ - pllmf |= 0x10U; - } - if((RCU_CFG0 & RCU_CFG0_PLLMF_5)){ - pllmf |= 0x20U; - } - if(pllmf < 15U){ - pllmf += 2U; - }else if((pllmf >= 15U) && (pllmf <= 64U)){ - pllmf += 1U; - }else{ - } - SystemCoreClock = ck_src*pllmf; -#if (defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)) - if(15U == pllmf){ - SystemCoreClock = ck_src*6U + ck_src/2U; - } -#endif /* GD32E50X_CL and GD32EPRT and GD32E508 */ - - break; - /* IRC8M is selected as CK_SYS */ - default: - SystemCoreClock = IRC8M_VALUE; - break; - } - - /* calculate AHB clock frequency */ - idx = GET_BITS(RCU_CFG0, 4, 7); - clk_exp = ahb_exp[idx]; - SystemCoreClock >>= clk_exp; -} - -#ifdef __FIRMWARE_VERSION_DEFINE -/*! - \brief get firmware version - \param[in] none - \param[out] none - \retval firmware version -*/ -uint32_t gd32e50x_firmware_version_get(void) -{ - return __GD32E50X_STDPERIPH_VERSION; -} -#endif /* __FIRMWARE_VERSION_DEFINE */ diff --git a/_backup_20260506_0053/GD32E50X_BOOT/RTE/_Debug_GD32E508VE/RTE_Components(CBB-003的冲突副本1_2026-05-06 00-26-28).h b/_backup_20260506_0053/GD32E50X_BOOT/RTE/_Debug_GD32E508VE/RTE_Components(CBB-003的冲突副本1_2026-05-06 00-26-28).h deleted file mode 100644 index 295dafd..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/RTE/_Debug_GD32E508VE/RTE_Components(CBB-003的冲突副本1_2026-05-06 00-26-28).h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * CSOLUTION generated file: DO NOT EDIT! - * Generated by: csolution version 2.13.0+p3-g40b6564e - * - * Project: 'GD32E50X_BOOT.Debug+GD32E508VE' - * Target: 'Debug+GD32E508VE' - */ - -#ifndef RTE_COMPONENTS_H -#define RTE_COMPONENTS_H - - -/* - * Define the Device Header File: - */ -#define CMSIS_device_header "gd32e50x.h" - -/* GigaDevice::Device:GD32E50x_StdPeripherals:ADC@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_ADC -/* GigaDevice::Device:GD32E50x_StdPeripherals:CAN@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_CAN -/* GigaDevice::Device:GD32E50x_StdPeripherals:CRC@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_CRC -/* GigaDevice::Device:GD32E50x_StdPeripherals:DBG@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_DBG -/* GigaDevice::Device:GD32E50x_StdPeripherals:DMA@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_DMA -/* GigaDevice::Device:GD32E50x_StdPeripherals:EXTI@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_EXTI -/* GigaDevice::Device:GD32E50x_StdPeripherals:FMC@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_FMC -/* GigaDevice::Device:GD32E50x_StdPeripherals:FWDGT@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_FWDGT -/* GigaDevice::Device:GD32E50x_StdPeripherals:GPIO@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_GPIO -/* GigaDevice::Device:GD32E50x_StdPeripherals:MISC@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_MISC -/* GigaDevice::Device:GD32E50x_StdPeripherals:PMU@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_PMU -/* GigaDevice::Device:GD32E50x_StdPeripherals:RCU@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_RCU -/* GigaDevice::Device:GD32E50x_StdPeripherals:TIMER@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_TIMER -/* GigaDevice::Device:GD32E50x_StdPeripherals:USART@1.6.0 */ -#define RTE_DEVICE_STDPERIPHERALS_USART - - -#endif /* RTE_COMPONENTS_H */ diff --git a/_backup_20260506_0053/GD32E50X_BOOT/main.c b/_backup_20260506_0053/GD32E50X_BOOT/main.c deleted file mode 100644 index 30e2ba5..0000000 --- a/_backup_20260506_0053/GD32E50X_BOOT/main.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "RTE_Components.h" -#include CMSIS_device_header - -int main() { - for (;;) { - } -}