diff --git a/bsp/gd32/libraries/gd32_drivers/SConscript b/bsp/gd32/libraries/gd32_drivers/SConscript index 16a76e2b0bac69a7c294007f7a879ac363f9ff96..7917476aaa1d2cce31ba3e3488404f8e0477765d 100644 --- a/bsp/gd32/libraries/gd32_drivers/SConscript +++ b/bsp/gd32/libraries/gd32_drivers/SConscript @@ -6,42 +6,39 @@ cwd = GetCurrentDir() # add the general drivers. src = Split(""" +drv_common.c """) # add pin drivers. if GetDepend('RT_USING_PIN'): src += ['drv_gpio.c'] - -# add usart drivers. + if GetDepend(['RT_USING_SERIAL']): - src += ['drv_usart.c'] - -# add i2c drivers. -if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']): - if GetDepend('BSP_USING_I2C0') or GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2') or GetDepend('BSP_USING_I2C3'): - src += ['drv_soft_i2c.c'] + if GetDepend(['RT_USING_SERIAL_V2']): + src += ['drv_usart_v2.c'] + else: + src += ['drv_usart.c'] -# add spi drivers. -if GetDepend('RT_USING_SPI'): - src += ['drv_spi.c'] +if GetDepend(['BSP_USING_ON_CHIP_FLASH']): + src += ['drv_flash.c'] -# add spi flash drivers. -if GetDepend('RT_USING_SFUD'): - src += ['drv_spi_flash.c', 'drv_spi.c'] +if GetDepend('RT_USING_ADC'): + src += ['drv_adc.c'] -if GetDepend('RT_USING_WDT'): - src += ['drv_wdt.c'] +if GetDepend('RT_USING_DAC'): + src += ['drv_dac.c'] if GetDepend('RT_USING_RTC'): src += ['drv_rtc.c'] -if GetDepend('RT_USING_HWTIMER'): - src += ['drv_hwtimer.c'] +if GetDepend('RT_USING_CAN'): + src += ['drv_can.c'] -if GetDepend('RT_USING_ADC'): - src += ['drv_adc.c'] +if GetDepend('RT_USING_PWM'): + src += ['drv_pwm.c'] -path = [cwd] +path = [cwd] +path += [cwd + '/config'] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) diff --git a/bsp/gd32/libraries/gd32_drivers/config/can_config.h b/bsp/gd32/libraries/gd32_drivers/config/can_config.h new file mode 100644 index 0000000000000000000000000000000000000000..fa0b1a8e59308d0ea51ecc9f637a5ca06a91c46f --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/config/can_config.h @@ -0,0 +1,43 @@ +/** + * @file can_config.h + * @brief CAN引脚配置 + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2022-03-23 + * @copyright Copyright (c) 2022 烽火通信 + */ +#ifndef __CAN_CONFIG_H +#define __CAN_CONFIG_H +#include + +#if defined(BSP_USING_CAN0) +#ifndef CAN0_CONFIG +#define CAN0_CONFIG \ + { \ + .name = "can0", \ + .can_periph = CAN0, \ + .per_clk = RCU_CAN0, \ + .tx_pin = GET_PIN(A, 12), \ + .rx_pin = GET_PIN(A, 11), \ + .remap = 0, \ + } +#endif +#endif /* CAN0_CONFIG */ + +#if defined(BSP_USING_CAN1) +#ifndef CAN1_CONFIG +#define CAN1_CONFIG \ + { \ + .name = "can1", \ + .can_periph = CAN1, \ + .per_clk = RCU_CAN1, \ + .tx_pin = GET_PIN(D, 6), \ + .rx_pin = GET_PIN(D, 5), \ + .remap = GPIO_CAN1_REMAP, \ + } +#endif +#endif /* CAN0_CONFIG */ + +#endif // __CAN_CONFIG_H + +/*********** (C) COPYRIGHT 2022 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/config/pwm_config.h b/bsp/gd32/libraries/gd32_drivers/config/pwm_config.h new file mode 100644 index 0000000000000000000000000000000000000000..b196f2d1019b27ce9f3178ccc5c80f130ffb803c --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/config/pwm_config.h @@ -0,0 +1,82 @@ +/** + * @file pwm_config.h + * @brief PWM引脚配置 + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2022-03-24 + * @copyright Copyright (c) 2022 烽火通信 + */ +#ifndef __PWM_CONFIG_H +#define __PWM_CONFIG_H + +#include + +#ifdef BSP_USING_PWM0 +#ifndef PWM0_CONFIG +#define PWM0_CONFIG \ + { \ + .timer_periph = TIMER0, \ + .name = "pwm0", \ + .channel = 0 \ + } +#endif /* PWM1_CONFIG */ +#endif /* BSP_USING_PWM1 */ + +#ifdef BSP_USING_PWM1 +#ifndef PWM1_CONFIG +#define PWM1_CONFIG \ + { \ + .timer_periph = TIMER1, \ + .name = "pwm1", \ + .channel = 0 \ + } +#endif /* PWM1_CONFIG */ +#endif /* BSP_USING_PWM1 */ + +#ifdef BSP_USING_PWM2 +#ifndef PWM2_CONFIG +#define PWM2_CONFIG \ + { \ + .timer_periph = TIMER2, \ + .name = "pwm2", \ + .channel = 0 \ + } +#endif /* PWM2_CONFIG */ +#endif /* BSP_USING_PWM2 */ + +#ifdef BSP_USING_PWM3 +#ifndef PWM3_CONFIG +#define PWM3_CONFIG \ + { \ + .timer_periph = TIMER3, \ + .name = "pwm3", \ + .channel = 0 \ + } +#endif /* PWM3_CONFIG */ +#endif /* BSP_USING_PWM3 */ + +#ifdef BSP_USING_PWM4 +#ifndef PWM4_CONFIG +#define PWM4_CONFIG \ + { \ + .timer_periph = TIMER4, \ + .name = "pwm4", \ + .channel = 0 \ + } +#endif /* PWM4_CONFIG */ +#endif /* BSP_USING_PWM4 */ + +#ifdef BSP_USING_PWM5 +#ifndef PWM5_CONFIG +#define PWM5_CONFIG \ + { \ + .timer_periph = TIMER5, \ + .name = "pwm5", \ + .channel = 0 \ + } +#endif /* PWM5_CONFIG */ +#endif /* BSP_USING_PWM5 */ + +#endif // __PWM_CONFIG_H + +/*********** (C) COPYRIGHT 2022 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/config/uart_config.h b/bsp/gd32/libraries/gd32_drivers/config/uart_config.h new file mode 100644 index 0000000000000000000000000000000000000000..23a24272e1aea7600fdd3ecfea5e1743c7617f25 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/config/uart_config.h @@ -0,0 +1,376 @@ +/** + * @file drv_uart_config.h + * @brief 串口配置 + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2021-12-20 + * @copyright Copyright (c) 2021 烽火通信 + */ +#ifndef __DRV_UART_CONFIG_H +#define __DRV_UART_CONFIG_H +#include + +#if defined(BSP_USING_UART0) +#ifndef UART0_CONFIG +#define UART0_CONFIG \ + { \ + .name = "uart0", \ + .uart_periph = USART0, \ + .irqn = USART0_IRQn, \ + .per_clk = RCU_USART0, \ + .tx_gpio_clk = RCU_GPIOA, \ + .rx_gpio_clk = RCU_GPIOA, \ + .tx_port = GPIOA, \ + .tx_pin = GPIO_PIN_9, \ + .rx_port = GPIOA, \ + .rx_pin = GPIO_PIN_10, \ + } +#endif /* UART0_CONFIG */ + +#if defined(BSP_UART0_RX_USING_DMA) +#ifndef UART0_DMA_RX_CONFIG +#define UART0_DMA_RX_IRQHandler DMA0_Channel4_IRQHandler +#define UART0_DMA_RX_CONFIG \ + { \ + .dma_periph = DMA0, \ + .channelx = DMA_CH4, \ + .dma_clk = RCU_DMA0, \ + .dma_irq = DMA0_Channel4_IRQn, \ + } +#endif /* UART0_DMA_RX_CONFIG */ +#endif /* BSP_UART0_RX_USING_DMA */ + +#if defined(BSP_UART0_TX_USING_DMA) +#ifndef UART0_DMA_TX_CONFIG +#define UART0_DMA_TX_IRQHandler DMA0_Channel3_IRQHandler +#define UART0_DMA_TX_CONFIG \ + { \ + .dma_periph = DMA0, \ + .channelx = DMA_CH3, \ + .dma_clk = RCU_DMA0, \ + .dma_irq = DMA0_Channel3_IRQn, \ + } +#endif /* UART0_DMA_TX_CONFIG */ +#endif /* BSP_UART0_TX_USING_DMA */ +#endif /* BSP_USING_UART0 */ + + +#if defined(BSP_USING_UART1) +#ifndef UART1_CONFIG +#define UART1_CONFIG \ + { \ + .name = "uart1", \ + .uart_periph = USART1, \ + .irqn = USART1_IRQn, \ + .per_clk = RCU_USART1, \ + .tx_gpio_clk = RCU_GPIOA, \ + .rx_gpio_clk = RCU_GPIOA, \ + .tx_port = GPIOA, \ + .tx_pin = GPIO_PIN_2, \ + .rx_port = GPIOA, \ + .rx_pin = GPIO_PIN_3, \ + } +#endif /* UART1_CONFIG */ + +#if defined(BSP_UART1_RX_USING_DMA) +#ifndef UART1_DMA_RX_CONFIG +#define UART1_DMA_RX_IRQHandler DMA0_Channel5_IRQHandler +#define UART1_DMA_RX_CONFIG \ + { \ + .dma_periph = DMA0, \ + .channelx = DMA_CH5, \ + .dma_clk = RCU_DMA0, \ + .dma_irq = DMA0_Channel5_IRQn, \ + } +#endif /* UART1_DMA_RX_CONFIG */ +#endif /* BSP_UART1_RX_USING_DMA */ + +#if defined(BSP_UART1_TX_USING_DMA) +#ifndef UART1_DMA_TX_CONFIG +#define UART1_DMA_TX_IRQHandler DMA0_Channel6_IRQHandler +#define UART1_DMA_TX_CONFIG \ + { \ + .dma_periph = DMA0, \ + .channelx = DMA_CH6, \ + .dma_clk = RCU_DMA0, \ + .dma_irq = DMA0_Channel6_IRQn, \ + } +#endif /* UART1_DMA_TX_CONFIG */ +#endif /* BSP_UART1_TX_USING_DMA */ +#endif /* BSP_USING_UART1 */ + + +#if defined(BSP_USING_UART2) +#ifndef UART2_CONFIG +#define UART2_CONFIG \ + { \ + .name = "uart2", \ + .uart_periph = USART2, \ + .irqn = USART2_IRQn, \ + .per_clk = RCU_USART2, \ + .tx_gpio_clk = RCU_GPIOB, \ + .rx_gpio_clk = RCU_GPIOB, \ + .tx_port = GPIOB, \ + .tx_pin = GPIO_PIN_10, \ + .rx_port = GPIOB, \ + .rx_pin = GPIO_PIN_11, \ + } +#endif /* UART2_CONFIG */ + +#if defined(BSP_UART2_RX_USING_DMA) +#ifndef UART2_DMA_RX_CONFIG +#define UART2_DMA_RX_IRQHandler DMA0_Channel2_IRQHandler +#define UART2_DMA_RX_CONFIG \ + { \ + .dma_periph = DMA0, \ + .channelx = DMA_CH2, \ + .dma_clk = RCU_DMA0, \ + .dma_irq = DMA0_Channel2_IRQn, \ + } +#endif /* UART2_DMA_RX_CONFIG */ +#endif /* BSP_UART2_RX_USING_DMA */ + +#if defined(BSP_UART2_TX_USING_DMA) +#ifndef UART2_DMA_TX_CONFIG +#define UART2_DMA_TX_IRQHandler DMA0_Channel1_IRQHandler +#define UART2_DMA_TX_CONFIG \ + { \ + .dma_periph = DMA0, \ + .channelx = DMA_CH1, \ + .dma_clk = RCU_DMA0, \ + .dma_irq = DMA0_Channel1_IRQn, \ + } +#endif /* UART2_DMA_TX_CONFIG */ +#endif /* BSP_UART2_TX_USING_DMA */ +#endif /* BSP_USING_UART2 */ + + +#if defined(BSP_USING_UART3) +#ifndef UART3_CONFIG +#define UART3_CONFIG \ + { \ + .name = "uart3", \ + .uart_periph = UART3, \ + .irqn = UART3_IRQn, \ + .per_clk = RCU_UART3, \ + .tx_gpio_clk = RCU_GPIOC, \ + .rx_gpio_clk = RCU_GPIOC, \ + .tx_port = GPIOC, \ + .tx_pin = GPIO_PIN_10, \ + .rx_port = GPIOC, \ + .rx_pin = GPIO_PIN_11, \ + } +#endif /* UART3_CONFIG */ + +#if defined(BSP_UART3_RX_USING_DMA) +#ifndef UART3_DMA_RX_CONFIG +#define UART3_DMA_RX_IRQHandler DMA1_Channel2_IRQHandler +#define UART3_DMA_RX_CONFIG \ + { \ + .dma_periph = DMA1, \ + .channelx = DMA_CH2, \ + .dma_clk = RCU_DMA1, \ + .dma_irq = DMA1_Channel2_IRQn, \ + } +#endif /* UART3_DMA_RX_CONFIG */ +#endif /* BSP_UART3_RX_USING_DMA */ + +#if defined(BSP_UART3_TX_USING_DMA) +#ifndef UART3_DMA_TX_CONFIG +#define UART3_DMA_TX_IRQHandler DMA1_Channel4_IRQHandler +#define UART3_DMA_TX_CONFIG \ + { \ + .dma_periph = DMA1, \ + .channelx = DMA_CH4, \ + .dma_clk = RCU_DMA1, \ + .dma_irq = DMA1_Channel4_IRQn, \ + } +#endif /* UART3_DMA_TX_CONFIG */ +#endif /* BSP_UART3_TX_USING_DMA */ +#endif /* BSP_USING_UART3 */ + + +#if defined(BSP_USING_UART4) +#ifndef UART4_CONFIG +#define UART4_CONFIG \ + { \ + .name = "uart4", \ + .uart_periph = UART4, \ + .irqn = UART4_IRQn, \ + .per_clk = RCU_UART4, \ + .tx_gpio_clk = RCU_GPIOC, \ + .rx_gpio_clk = RCU_GPIOD, \ + .tx_port = GPIOC, \ + .tx_pin = GPIO_PIN_12, \ + .rx_port = GPIOD, \ + .rx_pin = GPIO_PIN_2, \ + } +#endif /* UART4_CONFIG */ + +#if defined(BSP_UART4_RX_USING_DMA) +#ifndef UART4_DMA_RX_CONFIG +#define UART4_DMA_RX_IRQHandler DMA1_Channel1_IRQHandler +#define UART4_DMA_RX_CONFIG \ + { \ + .dma_periph = DMA1, \ + .channelx = DMA_CH1, \ + .dma_clk = RCU_DMA1, \ + .dma_irq = DMA1_Channel1_IRQn, \ + } +#endif /* UART4_DMA_RX_CONFIG */ +#endif /* BSP_UART4_RX_USING_DMA */ + +#if defined(BSP_UART4_TX_USING_DMA) +#ifndef UART4_DMA_TX_CONFIG +#define UART4_DMA_TX_IRQHandler DMA1_Channel3_IRQHandler +#define UART4_DMA_TX_CONFIG \ + { \ + .dma_periph = DMA1, \ + .channelx = DMA_CH3, \ + .dma_clk = RCU_DMA1, \ + .dma_irq = DMA1_Channel3_IRQn, \ + } +#endif /* UART4_DMA_TX_CONFIG */ +#endif /* BSP_UART4_TX_USING_DMA */ +#endif /* BSP_USING_UART4 */ + + +#if defined(BSP_USING_UART5) +#ifndef UART5_CONFIG +#define UART5_CONFIG \ + { \ + .name = "uart5", \ + .uart_periph = USART5, \ + .irqn = USART5_IRQn, \ + .per_clk = RCU_USART5, \ + .tx_gpio_clk = RCU_GPIOC, \ + .rx_gpio_clk = RCU_GPIOC, \ + .tx_port = GPIOC, \ + .tx_pin = GPIO_PIN_6, \ + .rx_port = GPIOC, \ + .rx_pin = GPIO_PIN_7, \ + } +#endif /* UART5_CONFIG */ + +#if defined(BSP_UART5_RX_USING_DMA) +#ifndef UART5_DMA_RX_CONFIG +#define UART5_DMA_RX_IRQHandler DMA1_Channel5_IRQHandler +#define UART5_DMA_RX_CONFIG \ + { \ + .dma_periph = DMA1, \ + .channelx = DMA_CH5, \ + .dma_clk = RCU_DMA1, \ + .dma_irq = DMA1_Channel5_IRQn, \ + } +#endif /* UART5_DMA_RX_CONFIG */ +#endif /* BSP_UART5_RX_USING_DMA */ + +#if defined(BSP_UART5_TX_USING_DMA) +#ifndef UART5_DMA_TX_CONFIG +#define UART5_DMA_TX_IRQHandler DMA1_Channel6_IRQHandler +#define UART5_DMA_TX_CONFIG \ + { \ + .dma_periph = DMA1, \ + .channelx = DMA_CH6, \ + .dma_clk = RCU_DMA1, \ + .dma_irq = DMA1_Channel6_IRQn, \ + } +#endif /* UART5_DMA_TX_CONFIG */ +#endif /* BSP_UART5_TX_USING_DMA */ +#endif /* BSP_USING_UART5 */ + + +#if defined(BSP_USING_UART6) +#ifndef UART6_CONFIG +#define UART6_CONFIG \ + { \ + .name = "uart6", \ + .uart_periph = UART6, \ + .irqn = UART6_IRQn, \ + .per_clk = RCU_UART6, \ + .tx_gpio_clk = RCU_GPIOE, \ + .rx_gpio_clk = RCU_GPIOE, \ + .tx_port = GPIOE, \ + .tx_pin = GPIO_PIN_7, \ + .rx_port = GPIOE, \ + .rx_pin = GPIO_PIN_8, \ + } +#endif /* UART6_CONFIG */ + +#if defined(BSP_UART6_RX_USING_DMA) +#ifndef UART6_DMA_RX_CONFIG +#define UART6_DMA_RX_IRQHandler DMA1_Channel2_IRQHandler +#define UART6_DMA_RX_CONFIG \ + { \ + .dma_periph = DMA1, \ + .channelx = DMA_CH2, \ + .dma_clk = RCU_DMA1, \ + .dma_irq = DMA1_Channel2_IRQn, \ + } +#endif /* UART6_DMA_RX_CONFIG */ +#endif /* BSP_UART6_RX_USING_DMA */ + +#if defined(BSP_UART6_TX_USING_DMA) +#ifndef UART6_DMA_TX_CONFIG +#define UART6_DMA_TX_IRQHandler DMA1_Channel4_IRQHandler +#define UART6_DMA_TX_CONFIG \ + { \ + .dma_periph = DMA1, \ + .channelx = DMA_CH4, \ + .dma_clk = RCU_DMA1, \ + .dma_irq = DMA1_Channel4_IRQn, \ + } +#endif /* UART6_DMA_TX_CONFIG */ +#endif /* BSP_UART6_TX_USING_DMA */ +#endif /* BSP_USING_UART6 */ + + +#if defined(BSP_USING_UART7) +#ifndef UART7_CONFIG +#define UART7_CONFIG \ + { \ + .name = "uart7", \ + .uart_periph = UART7, \ + .irqn = UART7_IRQn, \ + .per_clk = RCU_UART7, \ + .tx_gpio_clk = RCU_GPIOE, \ + .rx_gpio_clk = RCU_GPIOE, \ + .tx_port = GPIOE, \ + .tx_pin = GPIO_PIN_0, \ + .rx_port = GPIOE, \ + .rx_pin = GPIO_PIN_1, \ + } +#endif /* UART7_CONFIG */ + +#if defined(BSP_UART7_RX_USING_DMA) +#ifndef UART7_DMA_RX_CONFIG +#define UART7_DMA_RX_IRQHandler DMA1_Channel1_IRQHandler +#define UART7_DMA_RX_CONFIG \ + { \ + .dma_periph = DMA1, \ + .channelx = DMA_CH1, \ + .dma_clk = RCU_DMA1, \ + .dma_irq = DMA1_Channel1_IRQn, \ + } +#endif /* UART7_DMA_RX_CONFIG */ +#endif /* BSP_UART7_RX_USING_DMA */ + +#if defined(BSP_UART7_TX_USING_DMA) +#ifndef UART7_DMA_TX_CONFIG +#define UART7_DMA_TX_IRQHandler DMA1_Channel3_IRQHandler +#define UART7_DMA_TX_CONFIG \ + { \ + .dma_periph = DMA1, \ + .channelx = DMA_CH3, \ + .dma_clk = RCU_DMA1, \ + .dma_irq = DMA1_Channel3_IRQn, \ + } +#endif /* UART7_DMA_TX_CONFIG */ +#endif /* BSP_UART7_TX_USING_DMA */ +#endif /* BSP_USING_UART7 */ + + + +#endif // __DRV_UART_CONFIG_H + +/*********** (C) COPYRIGHT 2021 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_adc.c b/bsp/gd32/libraries/gd32_drivers/drv_adc.c index bd3b2d6b63fdbf539a703b760e4d36c648ea985b..14279a5eb8fd10080c80dd757f5a5825e576faca 100644 --- a/bsp/gd32/libraries/gd32_drivers/drv_adc.c +++ b/bsp/gd32/libraries/gd32_drivers/drv_adc.c @@ -1,26 +1,23 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-02-25 iysheng first version +/** + * @file drv_adc.c + * @brief GD32 ADC-RTT适配驱动 + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2022-02-23 + * @copyright Copyright (c) 2022 烽火通信 */ - #include -#include -#define DBG_TAG "drv.adc" -#define DBG_LVL DBG_INFO +#ifdef RT_USING_ADC +#define DBG_TAG "drv.adc" +#define DBG_LVL DBG_INFO #include -#ifdef RT_USING_ADC +#define MAX_EXTERN_ADC_CHANNEL 16 -#define MAX_EXTERN_ADC_CHANNEL 16 - -typedef struct { +typedef struct +{ struct rt_adc_device adc_dev; char name[8]; rt_base_t adc_pins[16]; @@ -30,66 +27,70 @@ typedef struct { static gd32_adc_device g_gd32_devs[] = { #ifdef BSP_USING_ADC0 { - {}, - "adc0", - { + .name = "adc0", + .adc_pins = { GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3), GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7), GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1), GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5), }, - (void *)ADC0, + .private_data = (void *)ADC0, }, #endif #ifdef BSP_USING_ADC1 { - {}, - "adc1", - { + .name = "adc1", + .adc_pins = { GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3), GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7), GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1), GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5), }, - (void *)ADC1, + .private_data = (void *)ADC1, }, #endif }; -/* - * static void init_pin4adc - * - * @ rt_uint32_t pin: pin information - * return: N/A +/** + * @brief 初始化ADC引脚 + * @param[in] pin 引脚编号 */ -static void init_pin4adc(rt_base_t pin) +static void gd32_adc_gpio_init(rt_base_t pin) { + rcu_periph_clock_enable((rcu_periph_enum)PIN_GDRCU(pin)); gpio_init(PIN_GDPORT(pin), GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, PIN_GDPIN(pin)); } +/** + * @brief adc通道使能 + * @param[in] device adc设备 + * @param[in] channel adc通道 + * @param[in] enabled 0:禁止,非0:使能 + * @return rt_err_t 0:成功,非0:失败 + */ static rt_err_t gd32_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) { - uint32_t adc_periph; - gd32_adc_device * gd32_adc = (gd32_adc_device *)device; - - if (channel >= MAX_EXTERN_ADC_CHANNEL) + if ((device == NULL) || (channel >= MAX_EXTERN_ADC_CHANNEL)) { - LOG_E("invalid channel"); + LOG_E("invalid channel\r\n"); return -RT_EINVAL; } - adc_periph = (uint32_t )(device->parent.user_data); + gd32_adc_device *gd32_adc = (gd32_adc_device *)device; + uint32_t adc_periph = (uint32_t )(device->parent.user_data); if (enabled == ENABLE) { - init_pin4adc(gd32_adc->adc_pins[channel]); + gd32_adc_gpio_init(gd32_adc->adc_pins[channel]); adc_deinit(adc_periph); adc_channel_length_config(adc_periph, ADC_REGULAR_CHANNEL, 1); adc_data_alignment_config(adc_periph, ADC_DATAALIGN_RIGHT); adc_external_trigger_source_config(adc_periph, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_INSERTED_NONE); adc_external_trigger_config(adc_periph, ADC_REGULAR_CHANNEL, ENABLE); - adc_regular_channel_config(adc_periph, 0, channel, ADC_SAMPLETIME_13POINT5); + adc_special_function_config(adc_periph, ADC_SCAN_MODE, DISABLE); /* 模数转换工作在单通道模式 */ + adc_special_function_config(adc_periph, ADC_CONTINUOUS_MODE, DISABLE); /* 模数转换工作在单次转换模式 */ + adc_discontinuous_mode_config(adc_periph, ADC_REGULAR_CHANNEL, 1); /* 顺序进行规则转换的ADC通道的数目 */ adc_enable(adc_periph); } else @@ -100,30 +101,37 @@ static rt_err_t gd32_adc_enabled(struct rt_adc_device *device, rt_uint32_t chann return 0; } +/** + * @brief adc转换 + */ static rt_err_t gd32_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) { - uint32_t adc_periph; - - if (!value) + if ((device == NULL) || (channel >= MAX_EXTERN_ADC_CHANNEL) || (value == NULL)) { - LOG_E("invalid param"); + LOG_E("invalid param\r\n"); return -RT_EINVAL; } - adc_periph = (uint32_t )(device->parent.user_data); + uint32_t timeout = 50000; + uint32_t adc_periph = (uint32_t )(device->parent.user_data); + + adc_flag_clear(adc_periph, ADC_FLAG_EOC); + adc_regular_channel_config(adc_periph, 0, channel, ADC_SAMPLETIME_239POINT5); adc_software_trigger_enable(adc_periph, ADC_REGULAR_CHANNEL); + while (adc_flag_get(adc_periph, ADC_FLAG_EOC) != SET) + { + if ((timeout--) == 0) break; + } /* 等待转换结束 */ *value = adc_regular_data_read(adc_periph); return 0; } static struct rt_adc_ops g_gd32_adc_ops = { - gd32_adc_enabled, - gd32_adc_convert, + .enabled = gd32_adc_enabled, + .convert = gd32_adc_convert, }; - - static int rt_hw_adc_init(void) { int ret, i = 0; @@ -136,15 +144,18 @@ static int rt_hw_adc_init(void) rcu_periph_clock_enable(RCU_ADC1); #endif - for (; i < sizeof(g_gd32_devs) / sizeof(g_gd32_devs[0]); i++) + rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6); /* 72/6 = 12MHz need < 14MHZ */ + adc_mode_config(ADC_MODE_FREE); + + for (; i < sizeof(g_gd32_devs) / sizeof(gd32_adc_device); i++) { - ret = rt_hw_adc_register(&g_gd32_devs[i].adc_dev, \ - (const char *)g_gd32_devs[i].name, \ - &g_gd32_adc_ops, (void *)g_gd32_devs[i].private_data); + ret = rt_hw_adc_register(&g_gd32_devs[i].adc_dev, + (const char *)g_gd32_devs[i].name, + &g_gd32_adc_ops, (void *)g_gd32_devs[i].private_data); if (ret != RT_EOK) { /* TODO err handler */ - LOG_E("failed register %s, err=%d", g_gd32_devs[i].name, ret); + LOG_E("failed register %s, err=%d\r\n", g_gd32_devs[i].name, ret); } } @@ -152,3 +163,5 @@ static int rt_hw_adc_init(void) } INIT_BOARD_EXPORT(rt_hw_adc_init); #endif + +/*********** (C) COPYRIGHT 2022 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_can.c b/bsp/gd32/libraries/gd32_drivers/drv_can.c new file mode 100644 index 0000000000000000000000000000000000000000..97552a291c73d7820fdd35a97b4a01d57683f1da --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_can.c @@ -0,0 +1,708 @@ +/** + * @file drv_can.c + * @brief GD32 CAN-RTT适配驱动 \n + * @note 该版仅适配了GD32F10X + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2022-03-23 + * @copyright Copyright (c) 2022 烽火通信 + */ +#include "drv_can.h" + +#ifdef RT_USING_CAN + +#define DBG_TAG "drv.adc" +#define DBG_LVL DBG_INFO +#include + +struct gd32_baud_rate_tab +{ + uint32_t baud_rate; + uint32_t bt_swj; + uint32_t bt_bs2; + uint32_t bt_bs1; + uint32_t bt_psc; +}; + +/* baud = APB1 / (1 + BS1 + BS2) / PSC */ +#if defined (SOC_SERIES_GD32F1) /* APB1 36MHz */ +static const struct gd32_baud_rate_tab can_baud_rate_tab[] = +{ + {CAN1MBaud, CAN_BT_SJW_2TQ, CAN_BT_BS1_8TQ, CAN_BT_BS2_3TQ, 3}, + {CAN800kBaud, CAN_BT_SJW_2TQ, CAN_BT_BS1_5TQ, CAN_BT_BS2_3TQ, 5}, + {CAN500kBaud, CAN_BT_SJW_2TQ, CAN_BT_BS1_8TQ, CAN_BT_BS2_3TQ, 6}, + {CAN250kBaud, CAN_BT_SJW_2TQ, CAN_BT_BS1_8TQ, CAN_BT_BS2_3TQ, 12}, + {CAN125kBaud, CAN_BT_SJW_2TQ, CAN_BT_BS1_8TQ, CAN_BT_BS2_3TQ, 24}, + {CAN100kBaud, CAN_BT_SJW_2TQ, CAN_BT_BS1_8TQ, CAN_BT_BS2_3TQ, 30}, + {CAN50kBaud, CAN_BT_SJW_2TQ, CAN_BT_BS1_8TQ, CAN_BT_BS2_3TQ, 60}, + {CAN20kBaud, CAN_BT_SJW_2TQ, CAN_BT_BS1_8TQ, CAN_BT_BS2_3TQ, 150}, + {CAN10kBaud, CAN_BT_SJW_2TQ, CAN_BT_BS1_8TQ, CAN_BT_BS2_3TQ, 300}, +}; +#elif defined (SOC_SERIES_GD32F2) /* APB1 42MHz(max) */ + +#endif + + +static gd32_can_config can_dev_config[] = +{ +#ifdef BSP_USING_CAN0 + CAN0_CONFIG, +#endif + +#ifdef BSP_USING_CAN1 + CAN1_CONFIG, +#endif +}; + +static gd32_can_device can_devs[sizeof(can_dev_config) / sizeof(can_dev_config[0])] = {0}; + +/** + * @brief 获取速率对应编号 + * @param[in] baud 速率 + */ +static rt_uint32_t get_can_baud_index(rt_uint32_t baud) +{ + rt_uint32_t len, index; + + len = sizeof(can_baud_rate_tab) / sizeof(can_baud_rate_tab[0]); + for (index = 0; index < len; index++) + { + if (can_baud_rate_tab[index].baud_rate == baud) + return index; + } + + return 0; /* default baud is CAN1MBaud */ +} + +/** + * @brief can引脚初始化 + * @param[in] config 外设配置 + */ +RT_WEAK void gd32_can_gpio_init(gd32_can_config *config) +{ + rcu_periph_clock_enable(config->per_clk); + rcu_periph_clock_enable((rcu_periph_enum)PIN_GDRCU(config->tx_pin)); + rcu_periph_clock_enable((rcu_periph_enum)PIN_GDRCU(config->rx_pin)); + gpio_init(PIN_GDPORT(config->tx_pin), GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PIN_GDPIN(config->tx_pin)); + gpio_init(PIN_GDPORT(config->rx_pin), GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, PIN_GDPIN(config->rx_pin)); + + if (config->remap > 0) + { + rcu_periph_clock_enable(RCU_AF); + gpio_pin_remap_config(config->remap, ENABLE); + } +} + + +static rt_err_t _can_config(struct rt_can_device *can, struct can_configure *cfg) +{ + RT_ASSERT(can != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + gd32_can_device *can_dev = rt_container_of(can, gd32_can_device, device); + rt_uint32_t baud_index = get_can_baud_index(cfg->baud_rate); + + can_parameter_struct can_parameter; + can_filter_parameter_struct can_filter; + + can_struct_para_init(CAN_INIT_STRUCT, &can_parameter); + can_struct_para_init(CAN_FILTER_STRUCT, &can_filter); + + can_deinit(can_dev->config->can_periph); + can_parameter.time_triggered = DISABLE; + can_parameter.auto_bus_off_recovery = DISABLE; + can_parameter.auto_wake_up = DISABLE; + can_parameter.no_auto_retrans = DISABLE; + can_parameter.rec_fifo_overwrite = DISABLE; + can_parameter.trans_fifo_order = DISABLE; + + switch (cfg->mode) + { + case RT_CAN_MODE_NORMAL: + can_parameter.working_mode = CAN_NORMAL_MODE; + break; + case RT_CAN_MODE_LISEN: + can_parameter.working_mode = CAN_SILENT_MODE; + break; + case RT_CAN_MODE_LOOPBACK: + can_parameter.working_mode = CAN_LOOPBACK_MODE; + break; + case RT_CAN_MODE_LOOPBACKANLISEN: + can_parameter.working_mode = CAN_SILENT_LOOPBACK_MODE; + break; + } + can_parameter.working_mode = CAN_NORMAL_MODE; + + /* baud计算 */ + can_parameter.resync_jump_width = can_baud_rate_tab[baud_index].bt_swj; + can_parameter.time_segment_1 = can_baud_rate_tab[baud_index].bt_bs1; + can_parameter.time_segment_2 = can_baud_rate_tab[baud_index].bt_bs2; + can_parameter.prescaler = can_baud_rate_tab[baud_index].bt_psc; + can_init(can_dev->config->can_periph, &can_parameter); + + + /* initialize filter */ + can_filter.filter_number = 0; + can_filter.filter_mode = CAN_FILTERMODE_MASK; + can_filter.filter_bits = CAN_FILTERBITS_32BIT; + can_filter.filter_list_high = 0x0000; + can_filter.filter_list_low = 0x0000; + can_filter.filter_mask_high = 0x0000; + can_filter.filter_mask_low = 0x0000; + can_filter.filter_fifo_number = CAN_FIFO0; + can_filter.filter_enable = ENABLE; + can_filter_init(&can_filter); + + return RT_EOK; +} + +static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg) +{ + rt_uint32_t argval; + RT_ASSERT(can != RT_NULL); + RT_ASSERT(arg != RT_NULL); + + gd32_can_device *can_dev = rt_container_of(can, gd32_can_device, device); + uint32_t can_periph = can_dev->config->can_periph; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + { + argval = (rt_uint32_t)arg; + if (argval == RT_DEVICE_FLAG_INT_RX) + { + if (can_periph == CAN0) + { + nvic_irq_disable(USBD_LP_CAN0_RX0_IRQn); + nvic_irq_disable(CAN0_RX1_IRQn); + } +#ifdef GD32F10X_CL + else if (can_periph == CAN1) + { + nvic_irq_disable(CAN1_RX0_IRQn); + nvic_irq_disable(CAN1_RX1_IRQn); + } +#endif + can_interrupt_disable(can_periph, CAN_INT_RFNE0); + can_interrupt_disable(can_periph, CAN_INT_RFF0); + can_interrupt_disable(can_periph, CAN_INT_RFO0); + can_interrupt_disable(can_periph, CAN_INT_RFNE1); + can_interrupt_disable(can_periph, CAN_INT_RFF1); + can_interrupt_disable(can_periph, CAN_INT_RFO1); + } + else if (argval == RT_DEVICE_FLAG_INT_TX) + { + if (can_periph == CAN0) + { + nvic_irq_disable(USBD_HP_CAN0_TX_IRQn); + } +#ifdef GD32F10X_CL + else if (can_periph == CAN1) + { + nvic_irq_disable(CAN1_TX_IRQn); + } +#endif + can_interrupt_disable(can_periph, CAN_INT_TME); + } + else if (argval == RT_DEVICE_CAN_INT_ERR) + { + if (can_periph == CAN0) + { + nvic_irq_disable(CAN0_EWMC_IRQn); + } +#ifdef GD32F10X_CL + else if (can_periph == CAN1) + { + nvic_irq_disable(CAN1_EWMC_IRQn); + } +#endif + can_interrupt_disable(can_periph, CAN_INT_WERR); + can_interrupt_disable(can_periph, CAN_INT_PERR); + can_interrupt_disable(can_periph, CAN_INT_BO); + can_interrupt_disable(can_periph, CAN_INT_ERRN); + can_interrupt_disable(can_periph, CAN_INT_ERR); + } + } break; + + case RT_DEVICE_CTRL_SET_INT: + { + argval = (rt_uint32_t)arg; + if (argval == RT_DEVICE_FLAG_INT_RX) + { + if (can_periph == CAN0) + { + nvic_irq_enable(USBD_LP_CAN0_RX0_IRQn, 4, 0); + nvic_irq_enable(CAN0_RX1_IRQn, 4, 0); + } +#ifdef GD32F10X_CL + else if (can_periph == CAN1) + { + nvic_irq_enable(CAN1_RX0_IRQn, 4, 0); + nvic_irq_enable(CAN1_RX1_IRQn, 4, 0); + } +#endif + can_interrupt_enable(can_periph, CAN_INT_RFNE0); + can_interrupt_enable(can_periph, CAN_INT_RFF0); + can_interrupt_enable(can_periph, CAN_INT_RFO0); + can_interrupt_enable(can_periph, CAN_INT_RFNE1); + can_interrupt_enable(can_periph, CAN_INT_RFF1); + can_interrupt_enable(can_periph, CAN_INT_RFO1); + } + else if (argval == RT_DEVICE_FLAG_INT_TX) + { + if (can_periph == CAN0) + { + nvic_irq_enable(USBD_HP_CAN0_TX_IRQn, 4, 0); + } +#ifdef GD32F10X_CL + else if (can_periph == CAN1) + { + nvic_irq_enable(CAN1_TX_IRQn, 4, 0); + } +#endif + can_interrupt_enable(can_periph, CAN_INT_TME); + } + else if (argval == RT_DEVICE_CAN_INT_ERR) + { + if (can_periph == CAN0) + { + nvic_irq_enable(CAN0_EWMC_IRQn, 4, 0); + } +#ifdef GD32F10X_CL + else if (can_periph == CAN1) + { + nvic_irq_enable(CAN1_EWMC_IRQn, 4, 0); + } +#endif + can_interrupt_enable(can_periph, CAN_INT_WERR); + can_interrupt_enable(can_periph, CAN_INT_PERR); + can_interrupt_enable(can_periph, CAN_INT_BO); + can_interrupt_enable(can_periph, CAN_INT_ERRN); + can_interrupt_enable(can_periph, CAN_INT_ERR); + } + } break; + + case RT_CAN_CMD_SET_FILTER: + { + struct rt_can_filter_config *filter_cfg = (struct rt_can_filter_config *)arg; + can_filter_parameter_struct can_filter; + + for (size_t i = 0; i < filter_cfg->count; i++) + { + can_filter.filter_number = filter_cfg->items[i].hdr; + can_filter.filter_mode = filter_cfg->items[i].mode; + can_filter.filter_bits = CAN_FILTERBITS_32BIT; + + can_filter.filter_list_high = (filter_cfg->items[i].id >> 13) & 0xFFFF; + can_filter.filter_list_low = ((filter_cfg->items[i].id << 3) | + (filter_cfg->items[i].ide << 2) | + (filter_cfg->items[i].rtr << 1)) & 0xFFFF; + can_filter.filter_mask_high = (filter_cfg->items[i].mask >> 16) & 0xFFFF; + can_filter.filter_mask_low = filter_cfg->items[i].mask & 0xFFFF; + can_filter.filter_fifo_number = CAN_FIFO0; + can_filter.filter_enable = (ControlStatus)filter_cfg->actived; + + can_filter_init(&can_filter); + } + } break; + + case RT_CAN_CMD_SET_MODE: + { + argval = (rt_uint32_t)arg; + if (argval != RT_CAN_MODE_NORMAL && + argval != RT_CAN_MODE_LISEN && + argval != RT_CAN_MODE_LOOPBACK && + argval != RT_CAN_MODE_LOOPBACKANLISEN) + { + return -RT_ERROR; + } + if (argval != can->config.mode) + { + can->config.mode = argval; + return _can_config(can, &can->config); + } + } break; + + case RT_CAN_CMD_SET_BAUD: + { + argval = (rt_uint32_t)arg; + if (argval != CAN1MBaud && + argval != CAN800kBaud && + argval != CAN500kBaud && + argval != CAN250kBaud && + argval != CAN125kBaud && + argval != CAN100kBaud && + argval != CAN50kBaud && + argval != CAN20kBaud && + argval != CAN10kBaud) + { + return -RT_ERROR; + } + if (argval != can->config.baud_rate) + { + can->config.baud_rate = argval; + return _can_config(can, &can->config); + } + } break; + + case RT_CAN_CMD_SET_PRIV: + { + argval = (rt_uint32_t)arg; + if (argval != RT_CAN_MODE_PRIV && argval != RT_CAN_MODE_NOPRIV) + { + return -RT_ERROR; + } + if (argval != can->config.privmode) + { + can->config.privmode = argval; + return _can_config(can, &can->config); + } + } break; + + case RT_CAN_CMD_GET_STATUS: + { + rt_uint32_t errtype = CAN_ERR(can_periph); + can->status.rcverrcnt = GET_BITS(errtype, 24, 31); + can->status.snderrcnt = GET_BITS(errtype, 16, 23);; + can->status.lasterrtype = GET_BITS(errtype, 4, 6);; + can->status.errcode = GET_BITS(errtype, 0, 2); + + rt_memcpy(arg, &can->status, sizeof(can->status)); + } break; + + default: + break; + } + + return RT_EOK; +} + +static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num) +{ + can_trasnmit_message_struct transmit_message = {0}; + + RT_ASSERT(can != RT_NULL); + RT_ASSERT(can != buf); + + gd32_can_device *can_dev = rt_container_of(can, gd32_can_device, device); + uint32_t can_periph = can_dev->config->can_periph; + + struct rt_can_msg *pmsg = (struct rt_can_msg *)buf; + RT_ASSERT(pmsg->len <= 8); + + if (pmsg->ide == RT_CAN_STDID) + { + transmit_message.tx_ff = CAN_FF_STANDARD; /* format of frame, standard or extended format */ + transmit_message.tx_sfid = pmsg->id; + } + else + { + transmit_message.tx_ff = CAN_FF_EXTENDED; + transmit_message.tx_efid = pmsg->id; + } + + /* type of frame, data or remote */ + transmit_message.tx_ft = (pmsg->rtr == RT_CAN_DTR) ? CAN_FT_DATA : CAN_FT_REMOTE; + transmit_message.tx_dlen = pmsg->len & 0x0F; + + if (can_message_transmit(can_periph, &transmit_message) == CAN_NOMAILBOX) + return -RT_ERROR; + + return RT_EOK; +} + +static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo) +{ + can_receive_message_struct receive_message = {0}; + + RT_ASSERT(can != RT_NULL); + RT_ASSERT(buf != RT_NULL); + + gd32_can_device *can_dev = rt_container_of(can, gd32_can_device, device); + uint32_t can_periph = can_dev->config->can_periph; + struct rt_can_msg *pmsg = (struct rt_can_msg *)buf; + + can_message_receive(can_periph, fifo, &receive_message); + + if (receive_message.rx_ff == CAN_FF_STANDARD) + { + pmsg->ide = RT_CAN_STDID; + pmsg->id = receive_message.rx_sfid; + } + else + { + pmsg->ide = RT_CAN_EXTID; + pmsg->id = receive_message.rx_efid; + } + + pmsg->rtr = (receive_message.rx_ft == CAN_FT_DATA) ? RT_CAN_DTR : RT_CAN_RTR; + pmsg->len = receive_message.rx_dlen; + pmsg->hdr = (receive_message.rx_fi + 1) >> 1; + + rt_memcpy(pmsg->data, receive_message.rx_data, 8); + + return RT_EOK; +} + +/** + * @brief can接收中断处理 + * @param[in] can can设备 + * @param[in] fifo 接收FIFO(0/1) + */ +static void _can_rx_isr(struct rt_can_device *can, rt_uint32_t fifo) +{ + RT_ASSERT(can); + + gd32_can_device *can_dev = rt_container_of(can, gd32_can_device, device); + uint32_t can_periph = can_dev->config->can_periph; + + switch (fifo) + { + case CAN_FIFO0: + { + if (can_receive_message_length_get(can_periph, fifo) && can_interrupt_flag_get(can_periph, CAN_INT_FLAG_RFL0)) + { + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_RFL0); + rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8); + } + + /* Check FULL flag for FIFO0 */ + if (can_flag_get(can_periph, CAN_FLAG_RFF0) && can_interrupt_flag_get(can_periph, CAN_INT_FLAG_RFF0)) + { + can_flag_clear(can_periph, CAN_FLAG_RFF0); + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_RFF0); + } + + /* Check Overrun flag for FIFO0 */ + if (can_flag_get(can_periph, CAN_FLAG_RFO0) && can_interrupt_flag_get(can_periph, CAN_INT_FLAG_RFO0)) + { + can_flag_clear(can_periph, CAN_FLAG_RFO0); + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_RFO0); + rt_hw_can_isr(can, RT_CAN_EVENT_RXOF_IND | fifo << 8); + } + } break; + + case CAN_FIFO1: + { + if (can_receive_message_length_get(can_periph, fifo) && can_interrupt_flag_get(can_periph, CAN_INT_FLAG_RFL1)) + { + rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8); + } + + /* Check FULL flag for FIFO1 */ + if (can_flag_get(can_periph, CAN_FLAG_RFF1) && can_interrupt_flag_get(can_periph, CAN_INT_FLAG_RFF1)) + { + can_flag_clear(can_periph, CAN_FLAG_RFF1); + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_RFF1); + } + + /* Check Overrun flag for FIFO1 */ + if (can_flag_get(can_periph, CAN_FLAG_RFO1) && can_interrupt_flag_get(can_periph, CAN_INT_FLAG_RFO1)) + { + can_flag_clear(can_periph, CAN_FLAG_RFO1); + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_RFO1); + rt_hw_can_isr(can, RT_CAN_EVENT_RXOF_IND | fifo << 8); + } + } break; + + default: + break; + } +} + +/** + * @brief can发送中断处理 + * @param[in] can can设备 + */ +static void _can_tx_isr(struct rt_can_device *can) +{ + RT_ASSERT(can); + + gd32_can_device *can_dev = rt_container_of(can, gd32_can_device, device); + uint32_t can_periph = can_dev->config->can_periph; + + /* mailbox 0 transmit finished interrupt flag */ + if (can_interrupt_flag_get(can_periph, CAN_INT_FLAG_MTF0)) + { + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_MTF0); + if (can_flag_get(can_periph, CAN_FLAG_MTFNERR0)) /* finished with no error */ + { + can_flag_clear(can_periph, CAN_FLAG_MTFNERR0); + rt_hw_can_isr(can, RT_CAN_EVENT_TX_DONE | 0 << 8); + } + else + { + rt_hw_can_isr(can, RT_CAN_EVENT_TX_FAIL | 0 << 8); + } + } + else if (can_interrupt_flag_get(can_periph, CAN_INT_FLAG_MTF1)) + { + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_MTF1); + if (can_flag_get(can_periph, CAN_FLAG_MTFNERR1)) /* finished with no error */ + { + can_flag_clear(can_periph, CAN_FLAG_MTFNERR1); + rt_hw_can_isr(can, RT_CAN_EVENT_TX_DONE | 0 << 8); + } + else + { + rt_hw_can_isr(can, RT_CAN_EVENT_TX_FAIL | 0 << 8); + } + } + else if (can_interrupt_flag_get(can_periph, CAN_INT_FLAG_MTF2)) + { + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_MTF2); + if (can_flag_get(can_periph, CAN_FLAG_MTFNERR2)) /* finished with no error */ + { + can_flag_clear(can_periph, CAN_FLAG_MTFNERR2); + rt_hw_can_isr(can, RT_CAN_EVENT_TX_DONE | 0 << 8); + } + else + { + rt_hw_can_isr(can, RT_CAN_EVENT_TX_FAIL | 0 << 8); + } + } + else + { + rt_hw_can_isr(can, RT_CAN_EVENT_TX_FAIL | 0 << 8); + } +} + +/** + * @brief can错误中断处理 + * @param[in] can can设备 + */ +static void _can_err_isr(struct rt_can_device *can) +{ + RT_ASSERT(can); + + gd32_can_device *can_dev = rt_container_of(can, gd32_can_device, device); + uint32_t can_periph = can_dev->config->can_periph; + + can_error_enum errtype = can_error_get(can_periph); + switch (errtype) + { + case CAN_ERROR_ACK: + { + if (can_flag_get(can_periph, CAN_FLAG_MTE0)) + rt_hw_can_isr(can, RT_CAN_EVENT_TX_FAIL | 0 << 8); + else if (can_flag_get(can_periph, CAN_FLAG_MTE1)) + rt_hw_can_isr(can, RT_CAN_EVENT_TX_FAIL | 1 << 8); + else if (can_flag_get(can_periph, CAN_FLAG_MTE2)) + rt_hw_can_isr(can, RT_CAN_EVENT_TX_FAIL | 2 << 8); + } break; + + case CAN_ERROR_FILL: + /* code */ + break; + + case CAN_ERROR_FORMATE: + can->status.formaterrcnt++; + break; + + case CAN_ERROR_BITRECESSIVE: + case CAN_ERROR_BITDOMINANTER: + can->status.biterrcnt++; + break; + + case CAN_ERROR_CRC: + can->status.crcerrcnt++; + break; + + default: + break; + } + + if (can_interrupt_flag_get(can_periph, CAN_INT_FLAG_ERRIF)) + { + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_ERRIF); + } + if (can_interrupt_flag_get(can_periph, CAN_INT_FLAG_ERRN)) + { + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_ERRN); + } + if (can_interrupt_flag_get(can_periph, CAN_INT_FLAG_BOERR)) + { + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_BOERR); + } + if (can_interrupt_flag_get(can_periph, CAN_INT_FLAG_PERR)) + { + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_PERR); + } + if (can_interrupt_flag_get(can_periph, CAN_INT_FLAG_WERR)) + { + can_interrupt_flag_clear(can_periph, CAN_INT_FLAG_WERR); + } +} + +#ifdef BSP_USING_CAN0 +void USBD_HP_CAN0_TX_IRQHandler(void) +{ + rt_interrupt_enter(); + _can_tx_isr(&can_devs[0].device); + rt_interrupt_leave(); +} + +void USBD_LP_CAN0_RX0_IRQHandler(void) +{ + rt_interrupt_enter(); + _can_rx_isr(&can_devs[0].device, CAN_FIFO0); + rt_interrupt_leave(); +} + +void CAN0_RX1_IRQHandler(void) +{ + rt_interrupt_enter(); + _can_rx_isr(&can_devs[0].device, CAN_FIFO1); + rt_interrupt_leave(); +} + +void CAN0_EWMC_IRQHandler(void) +{ + rt_interrupt_enter(); + _can_err_isr(&can_devs[0].device); + rt_interrupt_leave(); +} +#endif + + +static const struct rt_can_ops _can_ops = +{ + _can_config, + _can_control, + _can_sendmsg, + _can_recvmsg, +}; + +int rt_hw_can_init(void) +{ + rt_err_t result = 0; + rt_size_t dev_num = sizeof(can_devs) / sizeof(gd32_can_device); + + struct can_configure config = CANDEFAULTCONFIG; + config.privmode = RT_CAN_MODE_NOPRIV; + config.ticks = 50; +#ifdef RT_CAN_USING_HDR /* 硬件过滤 */ + config.maxhdr = 14; +#ifdef BSP_USING_CAN1 + config.maxhdr = 28; +#endif +#endif + + for (int i = 0; i < dev_num; i++) + { + can_devs[i].config = &can_dev_config[i]; + can_devs[i].device.config = config; + + gd32_can_gpio_init(&can_dev_config[i]); + + result = rt_hw_can_register(&can_devs[i].device, can_dev_config[i].name, &_can_ops, NULL); + RT_ASSERT(result == RT_EOK); + } + + return result; +} +INIT_BOARD_EXPORT(rt_hw_can_init); +#endif + +/*********** (C) COPYRIGHT 2022 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_can.h b/bsp/gd32/libraries/gd32_drivers/drv_can.h new file mode 100644 index 0000000000000000000000000000000000000000..661ba8c168f09ff50af954bd1e92203d633c1411 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_can.h @@ -0,0 +1,36 @@ +/** + * @file drv_can.h + * @brief GD32 CAN-RTT适配驱动 + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2022-03-23 + * @copyright Copyright (c) 2022 烽火通信 + */ +#ifndef __DRV_CAN_H +#define __DRV_CAN_H +#include +#include "can_config.h" + +typedef struct +{ + const char *name; + uint32_t can_periph; + rcu_periph_enum per_clk; + uint32_t tx_pin; + uint32_t rx_pin; + uint32_t remap; +} gd32_can_config; + + +typedef struct +{ + gd32_can_config *config; + struct rt_can_device device; +} gd32_can_device; + + + + +#endif // __DRV_CAN_H + +/*********** (C) COPYRIGHT 2022 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_common.c b/bsp/gd32/libraries/gd32_drivers/drv_common.c new file mode 100644 index 0000000000000000000000000000000000000000..58220094a1022171b1f15baa04f8dfaacff945a1 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_common.c @@ -0,0 +1,116 @@ +/** + * @file drv_common.c + * @brief gd32适配rtthread驱动 + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2021-12-13 + * @copyright Copyright (c) 2021 烽火通信 + */ +#include "drv_common.h" +#include + +#ifdef RT_USING_FINSH +#include +static void reboot(uint8_t argc, char **argv) +{ + rt_hw_cpu_reset(); +} +FINSH_FUNCTION_EXPORT_ALIAS(reboot, __cmd_reboot, Reboot System); +#endif /* RT_USING_FINSH */ + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void _Error_Handler(char *s, int num) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void rt_hw_systick_init(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + +#if 0 + /* enable interrupt */ + __set_PRIMASK(0); + /* System clock initialization */ + SystemClock_Config(); + /* disable interrupt */ + __set_PRIMASK(1); +#endif + + rt_hw_systick_init(); + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif + + rcu_periph_clock_enable(RCU_AF); /* 使能复用时钟 */ + nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0); + + /* USART driver initialization is open by default */ +#ifdef RT_USING_SERIAL +extern int rt_hw_usart_init(void); + rt_hw_usart_init(); +#endif + + /* SEGGER_RTT debug support */ +#ifdef SEGGER_RTT_ENABLE +extern int rt_hw_jlink_rtt_init(void); + rt_hw_jlink_rtt_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif +} + + +/*********** (C) COPYRIGHT 2021 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_common.h b/bsp/gd32/libraries/gd32_drivers/drv_common.h new file mode 100644 index 0000000000000000000000000000000000000000..e607c693ef3afc54c8f91de57738dced5dd4b83c --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_common.h @@ -0,0 +1,25 @@ +/** + * @file drv_common.h + * @brief gd32适配rtthread驱动 + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2021-12-13 + * @copyright Copyright (c) 2021 烽火通信 + */ +#ifndef __DRV_COMMON_H +#define __DRV_COMMON_H + +#include +#include +#include + +void _Error_Handler(char *s, int num); + +#ifndef Error_Handler +#define Error_Handler() _Error_Handler(__FILE__, __LINE__) +#endif + + +#endif // __DRV_COMMON_H + +/*********** (C) COPYRIGHT 2021 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_dac.c b/bsp/gd32/libraries/gd32_drivers/drv_dac.c new file mode 100644 index 0000000000000000000000000000000000000000..a797427c902ed29a2f130621141edb6dd9029eb8 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_dac.c @@ -0,0 +1,126 @@ +/** + * @file drv_dac.c + * @brief GD32 DAC-RTT适配驱动 + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2022-03-17 + * @copyright Copyright (c) 2022 烽火通信 + */ +#include + +#ifdef RT_USING_DAC + +#define DBG_TAG "drv.dac" +#define DBG_LVL DBG_INFO +#include + +typedef struct +{ + struct rt_dac_device device; + char name[8]; + rt_base_t dac_pins[2]; +} gd32_dac_device; + +static gd32_dac_device dac_devs[] = { +#ifdef BSP_USING_DAC0 + { + .name = "dac0", + .dac_pins = {GET_PIN(A, 4), GET_PIN(A, 5)}, + }, +#endif + +#ifdef BSP_USING_DAC1 + { + .name = "dac1", + .dac_pins = {GET_PIN(A, 4), GET_PIN(A, 5)}, + }, +#endif +}; + +/** + * @brief 初始化ADC引脚 + * @param[in] pin 引脚编号 + */ +static void gd32_dac_gpio_init(rt_base_t pin) +{ + rcu_periph_clock_enable((rcu_periph_enum)PIN_GDRCU(pin)); + gpio_init(PIN_GDPORT(pin), GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, PIN_GDPIN(pin)); +} + + +static rt_err_t gd32_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel) +{ + if (channel > 1) + { + LOG_E("invalid param.\r\n"); + return -RT_EINVAL; + } + + gd32_dac_device *gd32_dac = rt_container_of(device, gd32_dac_device, device); + gd32_dac_gpio_init(gd32_dac->dac_pins[channel]); + + dac_trigger_source_config(channel, DAC_TRIGGER_SOFTWARE); + dac_trigger_enable(channel); + dac_wave_mode_config(channel, DAC_WAVE_DISABLE); + dac_output_buffer_disable(channel); + dac_enable(channel); + + return RT_EOK; +} + +static rt_err_t gd32_dac_disabled(struct rt_dac_device *device, rt_uint32_t channel) +{ + if (channel > 1) + { + LOG_E("invalid param.\r\n"); + return -RT_EINVAL; + } + + dac_disable(channel); + + return RT_EOK; +} + +static rt_err_t gd32_set_dac_value(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value) +{ + if ((channel > 1) || (value == NULL)) + { + LOG_E("invalid param.\r\n"); + return -RT_EINVAL; + } + + dac_data_set(channel, DAC_ALIGN_12B_R, *value); + dac_software_trigger_enable(channel); + + return RT_EOK; +} + +static const struct rt_dac_ops dac_ops = +{ + .disabled = gd32_dac_disabled, + .enabled = gd32_dac_enabled, + .convert = gd32_set_dac_value, +}; + +static int rt_hw_dac_init(void) +{ + int ret, i; + + rcu_periph_clock_enable(RCU_DAC); + + for (i = 0; i < sizeof(dac_devs) / sizeof(gd32_dac_device); i++) + { + ret = rt_hw_dac_register(&dac_devs[i].device, (const char *)dac_devs[i].name, &dac_ops, NULL); + if (ret != RT_EOK) + { + LOG_E("failed register %s, err=%d\r\n", g_gd32_devs[i].name, ret); + } + } + + return ret; +} +INIT_DEVICE_EXPORT(rt_hw_dac_init); +#endif /* RT_USING_DAC */ + + +/*********** (C) COPYRIGHT 2022 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_flash.c b/bsp/gd32/libraries/gd32_drivers/drv_flash.c new file mode 100644 index 0000000000000000000000000000000000000000..ed2038b91c1ccc9d1b7aef17d20fc657700d306d --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_flash.c @@ -0,0 +1,208 @@ +/** + * @file drv_flash.c + * @brief + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2021-12-20 + * @copyright Copyright (c) 2021 烽火通信 + */ +#include "board.h" + +#ifdef BSP_USING_ON_CHIP_FLASH +#include "drv_flash.h" + +#if defined(PKG_USING_FAL) +#include "fal.h" +#endif + +#define DBG_LEVEL DBG_INFO +#define LOG_TAG "drv.flash" +#include + +/** + * @brief 获取指定地址的flash页边界 + * @param[in] addr 地址 + * @return uint32_t 页边界地址 + */ +static uint32_t GetPage(uint32_t addr) +{ + uint32_t page = 0; + page = RT_ALIGN_DOWN(addr, GD32_FLASH_PAGE_SIZE); + return page; +} + + +/** + * @brief Read data from flash. + * @note This operation's units is word. + * @param[in] addr flash address + * @param[out] buf buffer to store read data + * @param[in] size read bytes size + * @return int + */ +int gd32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size) +{ + size_t i; + + if ((addr + size) > GD32_FLASH_END_ADDRESS) + { + LOG_E("read outrange flash size! addr is (0x%p)\r\n", (void *)(addr + size)); + return -RT_EINVAL; + } + + for (i = 0; i < size; i++, buf++, addr++) + { + *buf = *(rt_uint8_t *) addr; + } + + return size; +} + +/** + * Write data to flash. + * @note This operation's units is word. + * @note This operation must after erase. @see flash_erase. + * + * @param addr flash address + * @param buf the write data buffer + * @param size write bytes size + * + * @return result + */ +int gd32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size) +{ + rt_err_t result = RT_EOK; + rt_uint32_t end_addr = addr + size; + + if (addr % 4 != 0) + { + LOG_E("write addr must be 4-byte alignment\r\n"); + return -RT_EINVAL; + } + + if ((end_addr) > GD32_FLASH_END_ADDRESS) + { + LOG_E("write outrange flash size! addr is (0x%p)\r\n", (void *)(addr + size)); + return -RT_EINVAL; + } + + /* unlock the internal flash */ + fmc_unlock(); + + while (addr < end_addr) + { + if (fmc_word_program(addr, *((rt_uint32_t *)buf)) == FMC_READY) + { + if (*(rt_uint32_t *)addr != *(rt_uint32_t *)buf) + { + result = -RT_ERROR; + break; + } + addr += 4; + buf += 4; + } + else + { + result = -RT_ERROR; + break; + } + } + + fmc_lock(); + + if (result != RT_EOK) + { + return result; + } + + return size; +} + +/** + * @brief flash 擦除 \n + * 会计算起始地址到所需擦除长度占用的所有扇区 + * @param[in] addr 起始地址(4字节边界) + * @param[in] size 擦除长度(4字节倍数) + * @return int 0:成功,-1:失败 + */ +int gd32_flash_erase(rt_uint32_t addr, size_t size) +{ + rt_err_t result = RT_EOK; + uint32_t page_addr; + + + if ((addr + size) > GD32_FLASH_END_ADDRESS) + { + LOG_E("ERROR: erase outrange flash size! addr is (0x%p)\n", (void *)(addr + size)); + return -RT_EINVAL; + } + + fmc_unlock(); + page_addr = GetPage(addr); + + while ( page_addr < (addr + size) ) + { + if ( page_addr < FMC_BANK0_END_ADDRESS ) + { + fmc_flag_clear(FMC_FLAG_BANK0_END); + fmc_flag_clear(FMC_FLAG_BANK0_WPERR); + fmc_flag_clear(FMC_FLAG_BANK0_PGERR); + } + else + { + fmc_flag_clear(FMC_FLAG_BANK1_END); + fmc_flag_clear(FMC_FLAG_BANK1_WPERR); + fmc_flag_clear(FMC_FLAG_BANK1_PGERR); + } + + if ( FMC_READY != fmc_page_erase(page_addr) ) + { + result = -RT_ERROR; + goto __exit; + } + + page_addr += GD32_FLASH_PAGE_SIZE; + } + +__exit: + fmc_lock(); + + if (result != RT_EOK) + { + return result; + } + + LOG_D("erase done: addr (0x%p), size %d\r\n", (void *)addr, size); + return size; +} + + + +#if defined(PKG_USING_FAL) + +static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size); +static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size); +static int fal_flash_erase(long offset, size_t size); + +const struct fal_flash_dev gd32_onchip_flash = { "onchip_flash", GD32_FLASH_START_ADRESS, GD32_FLASH_SIZE, GD32_FLASH_PAGE_SIZE, {NULL, fal_flash_read, fal_flash_write, fal_flash_erase} }; + +static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size) +{ + return gd32_flash_read(gd32_onchip_flash.addr + offset, buf, size); +} + +static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size) +{ + return gd32_flash_write(gd32_onchip_flash.addr + offset, buf, size); +} + +static int fal_flash_erase(long offset, size_t size) +{ + return gd32_flash_erase(gd32_onchip_flash.addr + offset, size); +} + +#endif +#endif /* BSP_USING_ON_CHIP_FLASH */ + + +/*********** (C) COPYRIGHT 2021 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_flash.h b/bsp/gd32/libraries/gd32_drivers/drv_flash.h new file mode 100644 index 0000000000000000000000000000000000000000..bca22e9d96ae3e593ec054bdbc9e8c9927f0e1e1 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_flash.h @@ -0,0 +1,32 @@ +/** + * @file drv_flash.h + * @brief + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2021-12-20 + * @copyright Copyright (c) 2021 烽火通信 + */ +#ifndef __DRV_FLASH_H +#define __DRV_FLASH_H + +#include +#include "rtdevice.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int gd32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size); +int gd32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size); +int gd32_flash_erase(rt_uint32_t addr, size_t size); + +#ifdef __cplusplus +} +#endif + + +#endif // __DRV_FLASH_H + +/*********** (C) COPYRIGHT 2021 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_pwm.c b/bsp/gd32/libraries/gd32_drivers/drv_pwm.c new file mode 100644 index 0000000000000000000000000000000000000000..5dd7b37a8cbf0aa9b6df2a73a4d0ca0dd6d45dc3 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_pwm.c @@ -0,0 +1,449 @@ +/** + * @file drv_pwm.c + * @brief GD32 PWM-RTT适配驱动 + * @note 仅适配特定时钟配置 + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2022-03-24 + * @copyright Copyright (c) 2022 烽火通信 + */ +#include +#ifdef RT_USING_PWM +#include "pwm_config.h" + +#define DBG_TAG "drv.pwm" +#define DBG_LVL DBG_INFO +#include + +#define MAX_PERIOD 65535 +#define MIN_PERIOD 3 +#define MIN_PULSE 2 + +enum +{ +#ifdef BSP_USING_PWM0 + PWM0_INDEX, +#endif +#ifdef BSP_USING_PWM1 + PWM1_INDEX, +#endif +#ifdef BSP_USING_PWM2 + PWM2_INDEX, +#endif +#ifdef BSP_USING_PWM3 + PWM3_INDEX, +#endif +#ifdef BSP_USING_PWM4 + PWM4_INDEX, +#endif +#ifdef BSP_USING_PWM5 + PWM5_INDEX, +#endif +#ifdef BSP_USING_PWM6 + PWM6_INDEX, +#endif +#ifdef BSP_USING_PWM7 + PWM7_INDEX, +#endif +#ifdef BSP_USING_PWM8 + PWM8_INDEX, +#endif +#ifdef BSP_USING_PWM9 + PWM9_INDEX, +#endif +#ifdef BSP_USING_PWM10 + PWM10_INDEX, +#endif +#ifdef BSP_USING_PWM11 + PWM11_INDEX, +#endif +#ifdef BSP_USING_PWM12 + PWM12_INDEX, +#endif +#ifdef BSP_USING_PWM13 + PWM13_INDEX, +#endif +}; + +/** @brief gd32 pwm设备结构体 */ +typedef struct +{ + struct rt_device_pwm device; + uint32_t timer_periph; + rt_uint8_t channel; + char *name; +} gd32_pwm_device; + +static gd32_pwm_device pwm_obj[] = +{ +#ifdef BSP_USING_PWM0 + PWM0_CONFIG, +#endif + +#ifdef BSP_USING_PWM1 + PWM1_CONFIG, +#endif + +#ifdef BSP_USING_PWM2 + PWM2_CONFIG, +#endif + +#ifdef BSP_USING_PWM3 + PWM3_CONFIG, +#endif + +#ifdef BSP_USING_PWM4 + PWM4_CONFIG, +#endif + +#ifdef BSP_USING_PWM5 + PWM5_CONFIG, +#endif + +#ifdef BSP_USING_PWM6 + PWM6_CONFIG, +#endif + +#ifdef BSP_USING_PWM7 + PWM7_CONFIG, +#endif + +#ifdef BSP_USING_PWM8 + PWM8_CONFIG, +#endif + +#ifdef BSP_USING_PWM9 + PWM9_CONFIG, +#endif + +#ifdef BSP_USING_PWM10 + PWM10_CONFIG, +#endif + +#ifdef BSP_USING_PWM11 + PWM11_CONFIG, +#endif + +#ifdef BSP_USING_PWM12 + PWM12_CONFIG, +#endif + +#ifdef BSP_USING_PWM13 + PWM13_CONFIG, +#endif +}; + +static void pwm_get_channel(void) +{ +#ifdef BSP_USING_PWM0_CH1 + pwm_obj[PWM0_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM0_CH2 + pwm_obj[PWM0_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_PWM0_CH3 + pwm_obj[PWM0_INDEX].channel |= 1 << 2; +#endif +#ifdef BSP_USING_PWM0_CH4 + pwm_obj[PWM0_INDEX].channel |= 1 << 3; +#endif +#ifdef BSP_USING_PWM1_CH1 + pwm_obj[PWM1_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM1_CH2 + pwm_obj[PWM1_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_PWM1_CH3 + pwm_obj[PWM1_INDEX].channel |= 1 << 2; +#endif +#ifdef BSP_USING_PWM1_CH4 + pwm_obj[PWM1_INDEX].channel |= 1 << 3; +#endif +#ifdef BSP_USING_PWM2_CH1 + pwm_obj[PWM2_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM2_CH2 + pwm_obj[PWM2_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_PWM2_CH3 + pwm_obj[PWM2_INDEX].channel |= 1 << 2; +#endif +#ifdef BSP_USING_PWM2_CH4 + pwm_obj[PWM2_INDEX].channel |= 1 << 3; +#endif +#ifdef BSP_USING_PWM3_CH1 + pwm_obj[PWM3_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM3_CH2 + pwm_obj[PWM3_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_PWM3_CH3 + pwm_obj[PWM3_INDEX].channel |= 1 << 2; +#endif +#ifdef BSP_USING_PWM3_CH4 + pwm_obj[PWM3_INDEX].channel |= 1 << 3; +#endif +#ifdef BSP_USING_PWM4_CH1 + pwm_obj[PWM4_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM4_CH2 + pwm_obj[PWM4_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_PWM4_CH3 + pwm_obj[PWM4_INDEX].channel |= 1 << 2; +#endif +#ifdef BSP_USING_PWM4_CH4 + pwm_obj[PWM4_INDEX].channel |= 1 << 3; +#endif +#ifdef BSP_USING_PWM5_CH1 + pwm_obj[PWM5_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM5_CH2 + pwm_obj[PWM5_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_PWM5_CH3 + pwm_obj[PWM5_INDEX].channel |= 1 << 2; +#endif +#ifdef BSP_USING_PWM5_CH4 + pwm_obj[PWM5_INDEX].channel |= 1 << 3; +#endif +#ifdef BSP_USING_PWM6_CH1 + pwm_obj[PWM6_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM6_CH2 + pwm_obj[PWM6_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_PWM6_CH3 + pwm_obj[PWM6_INDEX].channel |= 1 << 2; +#endif +#ifdef BSP_USING_PWM6_CH4 + pwm_obj[PWM6_INDEX].channel |= 1 << 3; +#endif +#ifdef BSP_USING_PWM7_CH1 + pwm_obj[PWM7_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM7_CH2 + pwm_obj[PWM7_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_PWM7_CH3 + pwm_obj[PWM7_INDEX].channel |= 1 << 2; +#endif +#ifdef BSP_USING_PWM7_CH4 + pwm_obj[PWM7_INDEX].channel |= 1 << 3; +#endif +#ifdef BSP_USING_PWM8_CH1 + pwm_obj[PWM8_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM8_CH2 + pwm_obj[PWM8_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_PWM8_CH3 + pwm_obj[PWM8_INDEX].channel |= 1 << 2; +#endif +#ifdef BSP_USING_PWM8_CH4 + pwm_obj[PWM8_INDEX].channel |= 1 << 3; +#endif +#ifdef BSP_USING_PWM9_CH1 + pwm_obj[PWM9_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM9_CH2 + pwm_obj[PWM9_INDEX].channel |= 1 << 1; +#endif +#ifdef BSP_USING_PWM9_CH3 + pwm_obj[PWM9_INDEX].channel |= 1 << 2; +#endif +#ifdef BSP_USING_PWM9_CH4 + pwm_obj[PWM9_INDEX].channel |= 1 << 3; +#endif +#ifdef BSP_USING_PWM12_CH1 + pwm_obj[PWM12_INDEX].channel |= 1 << 0; +#endif +#ifdef BSP_USING_PWM12_CH2 + pwm_obj[PWM12_INDEX].channel |= 1 << 1; +#endif +} + +RT_WEAK void gd32_pwm_pin_init(uint32_t timer_periph) +{ + /* PWM 引脚初始化 */ +} + +static rt_err_t drv_pwm_init(gd32_pwm_device *device) +{ + timer_oc_parameter_struct timer_ocintpara; + timer_parameter_struct timer_initpara; + + gd32_pwm_pin_init(device->timer_periph); + + timer_deinit(device->timer_periph); + /* TIMER1 configuration */ + timer_initpara.prescaler = 0; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = 0; + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_initpara.repetitioncounter = 0; + timer_init(device->timer_periph, &timer_initpara); + + /* OC_CH configuration in PWM mode1 */ + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE; + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; + timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; + timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; + + if (device->channel & 0x01) + { + timer_channel_output_config(device->timer_periph, TIMER_CH_0, &timer_ocintpara); + timer_channel_output_pulse_value_config(device->timer_periph, TIMER_CH_0, 0); + timer_channel_output_mode_config(device->timer_periph, TIMER_CH_0, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(device->timer_periph, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE); + } + + if (device->channel & 0x02) + { + timer_channel_output_config(device->timer_periph, TIMER_CH_1, &timer_ocintpara); + timer_channel_output_pulse_value_config(device->timer_periph, TIMER_CH_1, 0); + timer_channel_output_mode_config(device->timer_periph, TIMER_CH_1, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(device->timer_periph, TIMER_CH_1, TIMER_OC_SHADOW_DISABLE); + } + + if (device->channel & 0x04) + { + timer_channel_output_config(device->timer_periph, TIMER_CH_2, &timer_ocintpara); + timer_channel_output_pulse_value_config(device->timer_periph, TIMER_CH_2, 0); + timer_channel_output_mode_config(device->timer_periph, TIMER_CH_2, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(device->timer_periph, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE); + } + + if (device->channel & 0x08) + { + timer_channel_output_config(device->timer_periph, TIMER_CH_3, &timer_ocintpara); + timer_channel_output_pulse_value_config(device->timer_periph, TIMER_CH_3, 0); + timer_channel_output_mode_config(device->timer_periph, TIMER_CH_3, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(device->timer_periph, TIMER_CH_3, TIMER_OC_SHADOW_DISABLE); + } + + timer_auto_reload_shadow_enable(device->timer_periph); + timer_enable(device->timer_periph); + + return RT_EOK; +} + +static rt_err_t drv_pwm_enable(uint32_t timer_periph, struct rt_pwm_configuration *configuration, rt_bool_t enable) +{ + uint16_t channel = configuration->channel - 1; /* TIMER_CH_0 ~ TIMER_CH_3 */ + timer_channel_output_state_config(timer_periph, channel, (enable) ? TIMER_CCX_ENABLE : TIMER_CCX_DISABLE); + + return RT_EOK; +} + +static rt_err_t drv_pwm_get(uint32_t timer_periph, struct rt_pwm_configuration *configuration) +{ + uint32_t tim_clock = SystemCoreClock; /* 适用于 APB1=AHB/2 APB2=AHB/1 */ + + /* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */ + tim_clock /= 1000000UL; + configuration->period = (TIMER_CAR(timer_periph) + 1) * (TIMER_PSC(timer_periph) + 1) * 1000UL / tim_clock; + configuration->pulse = (REG32((timer_periph) + 0x34U + (configuration->channel - 1) * 4) + 1) * (TIMER_PSC(timer_periph) + 1) * 1000UL / tim_clock; + + return RT_EOK; +} + +static rt_err_t drv_pwm_set(uint32_t timer_periph, struct rt_pwm_configuration *configuration) +{ + uint32_t tim_clock = SystemCoreClock; /* 适用于 APB1=AHB/2 APB2=AHB/1 */ + uint32_t period, pulse, psc; + + /* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */ + tim_clock /= 1000000UL; + period = (unsigned long long)configuration->period * tim_clock / 1000ULL; + psc = period / MAX_PERIOD + 1; /* 计算最小分频 */ + period = period / psc; + timer_prescaler_config(timer_periph, psc - 1, TIMER_PSC_RELOAD_UPDATE); + + if (period < MIN_PERIOD) + period = MIN_PERIOD; + timer_autoreload_value_config(timer_periph, period - 1); + + pulse = (unsigned long long)configuration->pulse * tim_clock / psc / 1000ULL; + if (pulse < MIN_PULSE) + { + pulse = MIN_PULSE; + } + else if (pulse > period) + { + pulse = period; + } + timer_channel_output_pulse_value_config(timer_periph, configuration->channel - 1, pulse - 1); + timer_counter_value_config(timer_periph, 0); + + timer_event_software_generate(timer_periph, TIMER_EVENT_SRC_UPG); + + return RT_EOK; +} + +static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(arg != RT_NULL); + + struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg; + gd32_pwm_device *pwm_dev = rt_container_of(device, gd32_pwm_device, device); + + switch (cmd) + { + case PWM_CMD_ENABLE: + return drv_pwm_enable(pwm_dev->timer_periph, configuration, RT_TRUE); + case PWM_CMD_DISABLE: + return drv_pwm_enable(pwm_dev->timer_periph, configuration, RT_FALSE); + case PWM_CMD_SET: + return drv_pwm_set(pwm_dev->timer_periph, configuration); + case PWM_CMD_GET: + return drv_pwm_get(pwm_dev->timer_periph, configuration); + default: + return RT_EINVAL; + } +} + +static struct rt_pwm_ops drv_ops = +{ + .control = drv_pwm_control +}; + +static int rt_hw_pwm_init(void) +{ + pwm_get_channel(); + + for (uint8_t i = 0; i < sizeof(pwm_obj) / sizeof(pwm_obj[0]); i++) + { + /* pwm init */ + if (drv_pwm_init(&pwm_obj[i]) != RT_EOK) + { + LOG_E("%s init failed", pwm_obj[i].name); + return -RT_ERROR; + } + else + { + LOG_D("%s init success", pwm_obj[i].name); + + /* register pwm device */ + if (rt_device_pwm_register(&pwm_obj[i].device, pwm_obj[i].name, &drv_ops, NULL) == RT_EOK) + { + LOG_D("%s register success", pwm_obj[i].name); + } + else + { + LOG_E("%s register failed", pwm_obj[i].name); + return -RT_ERROR; + } + } + } + + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_pwm_init); +#endif /* RT_USING_PWM */ + +/*********** (C) COPYRIGHT 2022 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_rtc.c b/bsp/gd32/libraries/gd32_drivers/drv_rtc.c index 4ed2a31f384d2862c5ae2966b2d886ca93078bd5..367a11e6e665a6f77787ccdfe114e0f964023c9f 100644 --- a/bsp/gd32/libraries/gd32_drivers/drv_rtc.c +++ b/bsp/gd32/libraries/gd32_drivers/drv_rtc.c @@ -1,28 +1,29 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-01-25 iysheng first version +/** + * @file drv_rtc.c + * @brief GD32 RTC-RTT适配驱动 + * @note alarm暂不支持 + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2022-03-22 + * @copyright Copyright (c) 2022 烽火通信 */ - #include #include -#define DBG_TAG "drv.rtc" -#define DBG_LVL DBG_INFO +#ifdef RT_USING_RTC +#define DBG_TAG "drv.rtc" +#define DBG_LVL DBG_INFO #include -#ifdef RT_USING_RTC +#define BKUP_REG_DATA 0xA5A5 -typedef struct { - struct rt_device rtc_dev; -} gd32_rtc_device; +typedef struct +{ + struct rt_device device; +} rt_rtc_device; -static gd32_rtc_device g_gd32_rtc_dev; +static rt_rtc_device rtc_device; static time_t get_rtc_timestamp(void) { @@ -39,25 +40,62 @@ static rt_err_t set_rtc_timestamp(time_t time_stamp) rtc_counter = (uint32_t)time_stamp; - /* wait until LWOFF bit in RTC_CTL to 1 */ rtc_lwoff_wait(); - /* enter configure mode */ rtc_configuration_mode_enter(); - /* write data to rtc register */ rtc_counter_set(rtc_counter); - /* exit configure mode */ rtc_configuration_mode_exit(); - /* wait until LWOFF bit in RTC_CTL to 1 */ rtc_lwoff_wait(); return RT_EOK; } -static rt_err_t rt_gd32_rtc_control(rt_device_t dev, int cmd, void *args) +/** + * @brief rtc时钟初始化 + */ +static rt_err_t rt_rtc_init(void) { - rt_err_t result = RT_EOK; + rcu_periph_clock_enable(RCU_PMU); + pmu_backup_write_enable(); + rcu_periph_clock_enable(RCU_BKPI); + + /* 在启动时检查备份寄存器BKP_DR1,如果内容不是 BKUP_REG_DATA,则需重新配置RTC */ + if (bkp_data_read(BKP_DATA_0) != BKUP_REG_DATA) + { +#ifdef BSP_RTC_USING_LSI + rcu_osci_on(RCU_IRC40K); /* 使能低速外部时钟 LSE */ + if (rcu_osci_stab_wait(RCU_IRC40K) != SUCCESS) /* 等待 LSE ready */ + return -RT_ERROR; + + rcu_rtc_clock_config(RCU_RTCSRC_IRC40K); + rcu_periph_clock_enable(RCU_RTC); + rtc_register_sync_wait(); + rtc_lwoff_wait(); + rtc_prescaler_set(40000 - 1); + rtc_lwoff_wait(); +#else + rcu_osci_on(RCU_LXTAL); /* 使能低速外部时钟 LSE */ + if (rcu_osci_stab_wait(RCU_LXTAL) != SUCCESS) /* 等待 LSE ready */ + return -RT_ERROR; + + rcu_rtc_clock_config(RCU_RTCSRC_LXTAL); /* 选择LSE作为RTC时钟 */ + rcu_periph_clock_enable(RCU_RTC); /* 使能RTC时钟 */ + rtc_register_sync_wait(); /* 等待RTC寄存器与APB1同步 */ + rtc_lwoff_wait(); /* 等待最近一次对RTC寄存器的写操作完成 */ + rtc_prescaler_set(32767); + rtc_lwoff_wait(); +#endif + bkp_data_write(BKP_DATA_0, BKUP_REG_DATA); + } + + return RT_EOK; +} + +static rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void *args) +{ + rt_err_t result = RT_EOK; RT_ASSERT(dev != RT_NULL); + switch (cmd) { case RT_DEVICE_CTRL_RTC_GET_TIME: @@ -76,63 +114,47 @@ static rt_err_t rt_gd32_rtc_control(rt_device_t dev, int cmd, void *args) } #ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops g_gd32_rtc_ops = -{ - RT_NULL, - RT_NULL, - RT_NULL, - RT_NULL, - RT_NULL, - rt_gd32_rtc_control -}; +const static struct rt_device_ops rtc_ops = + { + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + rt_rtc_control}; #endif static int rt_hw_rtc_init(void) { rt_err_t ret; - time_t rtc_counter; - - rcu_periph_clock_enable(RCU_PMU); - pmu_backup_write_enable(); - rcu_periph_clock_enable(RCU_BKPI); - - rtc_counter = get_rtc_timestamp(); - /* once the rtc clock source has been selected, if can't be changed - * anymore unless the Backup domain is reset */ - rcu_bkp_reset_enable(); - rcu_bkp_reset_disable(); - rcu_periph_clock_enable(RCU_RTC); - rcu_osci_on(RCU_LXTAL); - if (SUCCESS == rcu_osci_stab_wait(RCU_LXTAL)) - { - /* set lxtal as rtc clock source */ - rcu_rtc_clock_config(RCU_RTCSRC_LXTAL); - } - set_rtc_timestamp(rtc_counter); + + if (rt_rtc_init() != RT_EOK) + LOG_E("failed rt_rtc_init\r\n"); #ifdef RT_USING_DEVICE_OPS - g_gd32_rtc_dev.rtc_dev.ops = &g_gd32_rtc_ops; + rtc_device.rtc_dev.ops = &rtc_ops; #else - g_gd32_rtc_dev.rtc_dev.init = RT_NULL; - g_gd32_rtc_dev.rtc_dev.open = RT_NULL; - g_gd32_rtc_dev.rtc_dev.close = RT_NULL; - g_gd32_rtc_dev.rtc_dev.read = RT_NULL; - g_gd32_rtc_dev.rtc_dev.write = RT_NULL; - g_gd32_rtc_dev.rtc_dev.control = rt_gd32_rtc_control; + rtc_device.device.init = RT_NULL; + rtc_device.device.open = RT_NULL; + rtc_device.device.close = RT_NULL; + rtc_device.device.read = RT_NULL; + rtc_device.device.write = RT_NULL; + rtc_device.device.control = rt_rtc_control; #endif - g_gd32_rtc_dev.rtc_dev.type = RT_Device_Class_RTC; - g_gd32_rtc_dev.rtc_dev.rx_indicate = RT_NULL; - g_gd32_rtc_dev.rtc_dev.tx_complete = RT_NULL; - g_gd32_rtc_dev.rtc_dev.user_data = RT_NULL; + rtc_device.device.type = RT_Device_Class_RTC; + rtc_device.device.rx_indicate = RT_NULL; + rtc_device.device.tx_complete = RT_NULL; + rtc_device.device.user_data = RT_NULL; - ret = rt_device_register(&g_gd32_rtc_dev.rtc_dev, "rtc", \ - RT_DEVICE_FLAG_RDWR); + ret = rt_device_register(&rtc_device.device, "rtc", RT_DEVICE_FLAG_RDWR); if (ret != RT_EOK) { - LOG_E("failed register internal rtc device, err=%d", ret); + LOG_E("failed register internal rtc device, err=%d\r\n", ret); } return ret; } INIT_DEVICE_EXPORT(rt_hw_rtc_init); #endif + +/*********** (C) COPYRIGHT 2022 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_usart_v2.c b/bsp/gd32/libraries/gd32_drivers/drv_usart_v2.c new file mode 100644 index 0000000000000000000000000000000000000000..341f6a4f148a3eeec0ff2034d799e9930b0798cd --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_usart_v2.c @@ -0,0 +1,1084 @@ +/** + * @file drv_usart.c + * @brief 适配 UART_V2 + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2021-12-20 + * @copyright Copyright (c) 2021 烽火通信 + */ +#include "drv_usart_v2.h" +#include + +#ifdef RT_USING_SERIAL_V2 + +#define DBG_TAG "drv.usart" +#define DBG_LVL DBG_LOG +#include + +#if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && \ + !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3) && \ + !defined(BSP_USING_UART4) && !defined(BSP_USING_UART5) && \ + !defined(BSP_USING_UART6) && !defined(BSP_USING_UART7) +#error "Please define at least one UARTx" +#endif + +#ifdef RT_SERIAL_USING_DMA + static void _uart_dma_config(struct rt_serial_device *serial, rt_ubase_t flag); +#endif + +enum +{ +#ifdef BSP_USING_UART0 + UART0_INDEX, +#endif + +#ifdef BSP_USING_UART1 + UART1_INDEX, +#endif + +#ifdef BSP_USING_UART2 + UART2_INDEX, +#endif + +#ifdef BSP_USING_UART3 + UART3_INDEX, +#endif + +#ifdef BSP_USING_UART4 + UART4_INDEX, +#endif + +#ifdef BSP_USING_UART5 + UART5_INDEX, +#endif + +#ifdef BSP_USING_UART6 + UART6_INDEX, +#endif + +#ifdef BSP_USING_UART7 + UART7_INDEX, +#endif +}; + +static struct gd32_uart_config uart_config[] = +{ +#ifdef BSP_USING_UART0 + UART0_CONFIG, +#endif + +#ifdef BSP_USING_UART1 + UART1_CONFIG, +#endif + +#ifdef BSP_USING_UART2 + UART2_CONFIG, +#endif + +#ifdef BSP_USING_UART3 + UART3_CONFIG, +#endif + +#ifdef BSP_USING_UART4 + UART4_CONFIG, +#endif + +#ifdef BSP_USING_UART5 + UART5_CONFIG, +#endif + +#ifdef BSP_USING_UART6 + UART6_CONFIG, +#endif + +#ifdef BSP_USING_UART7 + UART7_CONFIG, +#endif +}; + + +static struct gd32_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0}; + +static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct gd32_uart *uart; + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + uart = rt_container_of(serial, struct gd32_uart, serial); + + usart_disable(uart->config->uart_periph); + usart_baudrate_set(uart->config->uart_periph, cfg->baud_rate); + + switch (cfg->data_bits) + { + case DATA_BITS_9: + usart_word_length_set(uart->config->uart_periph, USART_WL_9BIT); + break; + + default: + usart_word_length_set(uart->config->uart_periph, USART_WL_8BIT); + break; + } + + switch (cfg->stop_bits) + { + case STOP_BITS_2: + usart_stop_bit_set(uart->config->uart_periph, USART_STB_2BIT); + break; + default: + usart_stop_bit_set(uart->config->uart_periph, USART_STB_1BIT); + break; + } + + switch (cfg->parity) + { + case PARITY_ODD: + usart_parity_config(uart->config->uart_periph, USART_PM_ODD); + break; + case PARITY_EVEN: + usart_parity_config(uart->config->uart_periph, USART_PM_EVEN); + break; + default: + usart_parity_config(uart->config->uart_periph, USART_PM_NONE); + break; + } + +#ifdef RT_SERIAL_USING_DMA + uart->dma_rx_remaining_cnt = serial->config.rx_bufsz; +#endif + + usart_receive_config(uart->config->uart_periph, USART_RECEIVE_ENABLE); + usart_transmit_config(uart->config->uart_periph, USART_TRANSMIT_ENABLE); + usart_enable(uart->config->uart_periph); + + return RT_EOK; +} + +static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct gd32_uart *uart; + + rt_ubase_t ctrl_arg = (rt_ubase_t)arg; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct gd32_uart, serial); + + if(ctrl_arg & (RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_RX_NON_BLOCKING)) + { + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_RX) + ctrl_arg = RT_DEVICE_FLAG_DMA_RX; + else + ctrl_arg = RT_DEVICE_FLAG_INT_RX; + } + else if(ctrl_arg & (RT_DEVICE_FLAG_TX_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING)) + { + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_TX) + ctrl_arg = RT_DEVICE_FLAG_DMA_TX; + else + ctrl_arg = RT_DEVICE_FLAG_INT_TX; + } + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + /* disable rx irq */ + NVIC_DisableIRQ(uart->config->irqn); + /* disable interrupt */ + usart_interrupt_disable(uart->config->uart_periph, USART_INT_RBNE); + + NVIC_DisableIRQ(uart->config->irqn); + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) + usart_interrupt_disable(uart->config->uart_periph, USART_INT_RBNE); + else if (ctrl_arg == RT_DEVICE_FLAG_INT_TX) + usart_interrupt_disable(uart->config->uart_periph, USART_INT_TBE); +#ifdef RT_SERIAL_USING_DMA + else if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) + { + usart_interrupt_disable(uart->config->uart_periph, USART_INT_RBNE); + NVIC_DisableIRQ(uart->config->dma_rx->dma_irq); + dma_deinit(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx); + } + else if(ctrl_arg == RT_DEVICE_FLAG_DMA_TX) + { + usart_interrupt_disable(uart->config->uart_periph, USART_INT_TC); + NVIC_DisableIRQ(uart->config->dma_tx->dma_irq); + dma_deinit(uart->config->dma_tx->dma_periph, (dma_channel_enum)uart->config->dma_tx->channelx); + } +#endif + break; + + case RT_DEVICE_CTRL_SET_INT: + nvic_irq_enable(uart->config->irqn, 3, 0); + usart_interrupt_enable(uart->config->uart_periph, USART_INT_ERR); + + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) + { + usart_interrupt_enable(uart->config->uart_periph, USART_INT_RBNE); + // usart_interrupt_enable(uart->config->uart_periph, USART_INT_IDLE); + } + else if (ctrl_arg == RT_DEVICE_FLAG_INT_TX) + usart_interrupt_enable(uart->config->uart_periph, USART_INT_TBE); + break; + + case RT_DEVICE_CTRL_CONFIG: + if (ctrl_arg & (RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX)) + { + +#ifdef RT_SERIAL_USING_DMA + _uart_dma_config(serial, ctrl_arg); +#endif + } + else + _uart_control(serial, RT_DEVICE_CTRL_SET_INT, (void *)ctrl_arg); + break; + + case RT_DEVICE_CHECK_OPTMODE: + { + if (ctrl_arg & RT_DEVICE_FLAG_DMA_TX) + return RT_SERIAL_TX_BLOCKING_NO_BUFFER; + else + return RT_SERIAL_TX_BLOCKING_BUFFER; + } + case RT_DEVICE_CTRL_CLOSE: + usart_deinit(uart->config->uart_periph); + break; + } + return RT_EOK; +} + +static int _uart_putc(struct rt_serial_device *serial, char ch) +{ + struct gd32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct gd32_uart, serial); + + usart_data_transmit(uart->config->uart_periph, ch); + while((usart_flag_get(uart->config->uart_periph, USART_FLAG_TC) == RESET)); + + return RT_EOK; +} + +static int _uart_getc(struct rt_serial_device *serial) +{ + int ch; + struct gd32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct gd32_uart, serial); + + ch = -1; + if (usart_flag_get(uart->config->uart_periph, USART_FLAG_RBNE) != RESET) + ch = usart_data_receive(uart->config->uart_periph); + return ch; +} + +static rt_size_t _uart_transmit(struct rt_serial_device *serial, + rt_uint8_t *buf, + rt_size_t size, + rt_uint32_t tx_flag) +{ + struct gd32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(buf != RT_NULL); + uart = rt_container_of(serial, struct gd32_uart, serial); + + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_TX) + { + /* TODO:UART DMA发送 */ + // HAL_UART_Transmit_DMA(&uart->handle, buf, size); + return size; + } + // LOG_D("RT_DEVICE_CTRL_SET_INT\r\n"); + _uart_control(serial, RT_DEVICE_CTRL_SET_INT, (void *)tx_flag); + + return size; +} + +#ifdef RT_SERIAL_USING_DMA +static void dma_recv_isr(struct rt_serial_device *serial, rt_uint8_t isr_flag) +{ + struct gd32_uart *uart; + rt_base_t level; + rt_size_t recv_len, counter; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct gd32_uart, serial); + + level = rt_hw_interrupt_disable(); + recv_len = 0; + counter = dma_transfer_number_get( uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx ); + + switch (isr_flag) + { + case UART_RX_DMA_IT_IDLE_FLAG: + if (counter <= uart->dma_rx_remaining_cnt) + recv_len = uart->dma_rx_remaining_cnt - counter; + else + recv_len = serial->config.rx_bufsz + uart->dma_rx_remaining_cnt - counter; + break; + + case UART_RX_DMA_IT_HT_FLAG: + if (counter < uart->dma_rx_remaining_cnt) + recv_len = uart->dma_rx_remaining_cnt - counter; + break; + + case UART_RX_DMA_IT_TC_FLAG: + if(counter >= uart->dma_rx_remaining_cnt) + recv_len = serial->config.rx_bufsz + uart->dma_rx_remaining_cnt - counter; + + default: + break; + } + + if (recv_len) + { + uart->dma_rx_remaining_cnt = counter; + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); + } + rt_hw_interrupt_enable(level); + +} +#endif /* RT_SERIAL_USING_DMA */ + + +/** + * Uart common interrupt process. This need add to uart ISR. + * + * @param serial serial device + */ +static void uart_isr(struct rt_serial_device *serial) +{ + struct gd32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct gd32_uart, serial); + + /* If the Read data register is not empty and the RXNE interrupt is enabled (RDR) */ + if ((usart_interrupt_flag_get(uart->config->uart_periph, USART_INT_FLAG_RBNE) != RESET) && + (usart_flag_get(uart->config->uart_periph, USART_FLAG_RBNE) != RESET)) + { + struct rt_serial_rx_fifo *rx_fifo; + rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + + rt_ringbuffer_putchar(&(rx_fifo->rb), (uint8_t)usart_data_receive(uart->config->uart_periph)); + + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + + /* Clear RXNE interrupt flag */ + usart_flag_clear(uart->config->uart_periph, USART_FLAG_RBNE); + usart_interrupt_flag_clear(uart->config->uart_periph, USART_INT_FLAG_RBNE); + } + + /* If the Transmit data register is empty and the TXE interrupt enable is enabled (TDR)*/ + else if ((usart_interrupt_flag_get(uart->config->uart_periph, USART_INT_FLAG_TBE) != RESET) && + (usart_flag_get(uart->config->uart_periph, USART_FLAG_TBE) != RESET)) + { + struct rt_serial_tx_fifo *tx_fifo; + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + rt_uint8_t put_char = 0; + if (rt_ringbuffer_getchar(&(tx_fifo->rb), &put_char)) + { + usart_data_transmit(uart->config->uart_periph, put_char); + } + else + { + usart_interrupt_disable(uart->config->uart_periph, USART_INT_TBE); + usart_interrupt_enable(uart->config->uart_periph, USART_INT_TC); + } + } + else if ((usart_interrupt_flag_get(uart->config->uart_periph, USART_INT_FLAG_TC) != RESET) && + (usart_flag_get(uart->config->uart_periph, USART_FLAG_TC) != RESET)) + { + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_TX) + { + /* TODO:The HAL_UART_TxCpltCallback will be triggered */ + // HAL_UART_IRQHandler(&(uart->handle)); + } + else + { + /* Transmission complete interrupt disable ( CR1 Register) */ + usart_interrupt_disable(uart->config->uart_periph, USART_INT_TC); + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE); + } + /* Clear Transmission complete interrupt flag ( ISR Register ) */ + usart_flag_clear(uart->config->uart_periph, USART_FLAG_TC); + usart_interrupt_flag_clear(uart->config->uart_periph, USART_INT_FLAG_TC); + } + + else if ((uart->uart_dma_flag) && (usart_flag_get(uart->config->uart_periph, USART_FLAG_IDLE) != RESET) + && (usart_interrupt_flag_get(uart->config->uart_periph, USART_INT_FLAG_IDLE) != RESET)) + { + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_RX) + dma_recv_isr(serial, UART_RX_DMA_IT_IDLE_FLAG); + else + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); /* 中断接收,空闲通知 */ + + usart_data_receive(uart->config->uart_periph); /* Clear IDLE interrupt flag bit */ + } + + else + { + if (usart_flag_get(uart->config->uart_periph, USART_FLAG_ORERR) != RESET || + usart_flag_get(uart->config->uart_periph, USART_FLAG_NERR) != RESET || + usart_flag_get(uart->config->uart_periph, USART_FLAG_FERR) != RESET || + usart_flag_get(uart->config->uart_periph, USART_FLAG_PERR) != RESET) + { + LOG_E("(%s) serial device error!\r\n", serial->parent.parent.name); + usart_data_receive(uart->config->uart_periph); /* Clear interrupt flag bit */ + } + if (usart_flag_get(uart->config->uart_periph, USART_FLAG_TC) != RESET) + { + usart_flag_clear(uart->config->uart_periph, USART_FLAG_TC); + } + if (usart_flag_get(uart->config->uart_periph, USART_FLAG_RBNE) != RESET) + { + usart_flag_clear(uart->config->uart_periph, USART_FLAG_RBNE); + } + } +} + +#ifdef RT_SERIAL_USING_DMA +/** + * Uart common interrupt process. This need add to uart ISR. + * + * @param serial serial device + */ +void uart_dma_isr(struct rt_serial_device *serial) +{ + struct gd32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct gd32_uart, serial); + + if ((dma_flag_get(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_FLAG_HTF) != RESET) && + (dma_interrupt_flag_get(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_INT_FLAG_HTF) != RESET)) + { + dma_recv_isr(&(uart->serial), UART_RX_DMA_IT_HT_FLAG); + dma_flag_clear(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_FLAG_HTF); + dma_interrupt_flag_clear(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_INT_FLAG_HTF); + } + else if ((dma_flag_get(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_FLAG_FTF) != RESET) && + (dma_interrupt_flag_get(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_INT_FLAG_FTF) != RESET)) + { + dma_recv_isr(&(uart->serial), UART_RX_DMA_IT_TC_FLAG); + dma_flag_clear(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_FLAG_FTF); + dma_interrupt_flag_clear(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_INT_FLAG_FTF); + } + else + { + if (dma_flag_get(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_FLAG_HTF) != RESET) + { + dma_flag_clear(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_FLAG_HTF); + } + if (dma_flag_get(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_FLAG_FTF) != RESET) + { + dma_flag_clear(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_FLAG_FTF); + } + if (dma_flag_get(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_FLAG_ERR) != RESET) + { + dma_flag_clear(uart->config->dma_rx->dma_periph, (dma_channel_enum)uart->config->dma_rx->channelx, DMA_FLAG_ERR); + } + } +} + +static void _uart_dma_config(struct rt_serial_device *serial, rt_ubase_t flag) +{ + struct rt_serial_rx_fifo *rx_fifo; + struct dma_config *dma_config; + struct gd32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct gd32_uart, serial); + + if (RT_DEVICE_FLAG_DMA_RX == flag) + { + dma_config = uart->config->dma_rx; + } + else if (RT_DEVICE_FLAG_DMA_TX == flag) + { + dma_config = uart->config->dma_tx; + } + LOG_D("%s dma config start\r\n", uart->config->name); + + rcu_periph_clock_enable((rcu_periph_enum)dma_config->dma_clk); + + dma_parameter_struct dma_init_struct; + dma_deinit(dma_config->dma_periph, (dma_channel_enum)dma_config->channelx); + + dma_init_struct.periph_addr = (uint32_t)&USART_DATA(uart->config->uart_periph); + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; + + if (flag == RT_DEVICE_FLAG_DMA_RX) + { + dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; + dma_circulation_enable(dma_config->dma_periph, (dma_channel_enum)dma_config->channelx); + + rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + dma_init_struct.memory_addr = (uint32_t)rx_fifo->buffer; + dma_init_struct.number = serial->config.rx_bufsz; + + usart_dma_receive_config(uart->config->uart_periph, USART_DENR_ENABLE); + usart_interrupt_enable(uart->config->uart_periph, USART_INT_IDLE); + usart_interrupt_enable(uart->config->uart_periph, USART_INT_ERR); + } + else if (flag == RT_DEVICE_FLAG_DMA_TX) + { + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_circulation_disable(dma_config->dma_periph, (dma_channel_enum)dma_config->channelx); + usart_dma_receive_config(uart->config->uart_periph, USART_DENT_ENABLE); + } + + dma_init(dma_config->dma_periph, (dma_channel_enum)dma_config->channelx, &dma_init_struct); + dma_memory_to_memory_disable(dma_config->dma_periph, (dma_channel_enum)dma_config->channelx); + + dma_flag_clear(dma_config->dma_periph, (dma_channel_enum)dma_config->channelx, DMA_FLAG_G); + dma_channel_enable(dma_config->dma_periph, (dma_channel_enum)dma_config->channelx); + + + dma_interrupt_enable(dma_config->dma_periph, (dma_channel_enum)dma_config->channelx, DMA_INT_FLAG_FTF); + dma_interrupt_enable(dma_config->dma_periph, (dma_channel_enum)dma_config->channelx, DMA_INT_FLAG_HTF); + dma_interrupt_enable(dma_config->dma_periph, (dma_channel_enum)dma_config->channelx, DMA_INT_FLAG_ERR); + + nvic_irq_enable(dma_config->dma_irq, 3, 0); + nvic_irq_enable(uart->config->irqn, 3, 0); +} +#endif /* RT_SERIAL_USING_DMA */ + + +#if defined(BSP_USING_UART0) +void USART0_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART0_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART0_RX_USING_DMA) +void UART0_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_dma_isr(&(uart_obj[UART0_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART0_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART0_TX_USING_DMA) +void UART0_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + /* 暂不使用 */ + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART0_TX_USING_DMA) */ +#endif /* BSP_USING_UART0 */ + +#if defined(BSP_USING_UART1) +void USART1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART1_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_RX_USING_DMA) +void UART1_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_dma_isr(&(uart_obj[UART1_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_TX_USING_DMA) +void UART1_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + /* 暂不使用 */ + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_TX_USING_DMA) */ +#endif /* BSP_USING_UART1 */ + +#if defined(BSP_USING_UART2) +void USART2_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART2_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_RX_USING_DMA) +void UART2_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_dma_isr(&(uart_obj[UART2_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_TX_USING_DMA) +void UART2_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + /* 暂不使用 */ + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_TX_USING_DMA) */ +#endif /* BSP_USING_UART2 */ + +#if defined(BSP_USING_UART3) +void UART3_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART3_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART3_RX_USING_DMA) +void UART3_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_dma_isr(&(uart_obj[UART3_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_RX) && defined(BSP_UART3_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART3_TX_USING_DMA) +void UART3_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + /* 暂不使用 */ + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_TX) && defined(BSP_UART3_TX_USING_DMA) */ +#endif /* BSP_USING_UART3 */ + +#if defined(BSP_USING_UART4) +void UART4_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART4_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART4_RX_USING_DMA) +void UART4_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_dma_isr(&(uart_obj[UART4_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_RX) && defined(BSP_UART4_RX_USING_DMA) */ + +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART4_TX_USING_DMA) +void UART4_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + /* 暂不使用 */ + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_TX) && defined(BSP_UART4_TX_USING_DMA) */ +#endif /* BSP_USING_UART4 */ + +#if defined(BSP_USING_UART5) +void USART5_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART5_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_RX_USING_DMA) +void UART5_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_dma_isr(&(uart_obj[UART5_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_TX_USING_DMA) +void UART5_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + /* 暂不使用 */ + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_TX_USING_DMA) */ +#endif /* BSP_USING_UART5 */ + +#if defined(BSP_USING_UART6) +void UART6_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART6_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_RX_USING_DMA) +void UART6_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_dma_isr(&(uart_obj[UART6_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_TX_USING_DMA) +void UART6_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + /* 暂不使用 */ + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_TX_USING_DMA) */ +#endif /* BSP_USING_UART6 */ + +#if defined(BSP_USING_UART7) +void UART7_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART7_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_RX_USING_DMA) +void UART7_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_dma_isr(&(uart_obj[UART7_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_TX_USING_DMA) +void UART7_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + /* 暂不使用 */ + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_TX_USING_DMA) */ +#endif /* BSP_USING_UART7 */ + + +static void _uart_get_config(void) +{ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + +#ifdef BSP_USING_UART0 + uart_obj[UART0_INDEX].serial.config = config; + uart_obj[UART0_INDEX].uart_dma_flag = 0; + + uart_obj[UART0_INDEX].serial.config.rx_bufsz = BSP_UART0_RX_BUFSIZE; + uart_obj[UART0_INDEX].serial.config.tx_bufsz = BSP_UART0_TX_BUFSIZE; + +#ifdef BSP_UART0_RX_USING_DMA + uart_obj[UART0_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart0_dma_rx = UART0_DMA_RX_CONFIG; + uart_config[UART0_INDEX].dma_rx = &uart0_dma_rx; +#endif + +#ifdef BSP_UART0_TX_USING_DMA + uart_obj[UART0_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart0_dma_tx = UART0_DMA_TX_CONFIG; + uart_config[UART0_INDEX].dma_tx = &uart0_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART1 + uart_obj[UART1_INDEX].serial.config = config; + uart_obj[UART1_INDEX].uart_dma_flag = 0; + + uart_obj[UART1_INDEX].serial.config.rx_bufsz = BSP_UART1_RX_BUFSIZE; + uart_obj[UART1_INDEX].serial.config.tx_bufsz = BSP_UART1_TX_BUFSIZE; + +#ifdef BSP_UART1_RX_USING_DMA + uart_obj[UART1_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart1_dma_rx = UART1_DMA_RX_CONFIG; + uart_config[UART1_INDEX].dma_rx = &uart1_dma_rx; +#endif + +#ifdef BSP_UART1_TX_USING_DMA + uart_obj[UART1_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart1_dma_tx = UART1_DMA_TX_CONFIG; + uart_config[UART1_INDEX].dma_tx = &uart1_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART2 + uart_obj[UART2_INDEX].serial.config = config; + uart_obj[UART2_INDEX].uart_dma_flag = 0; + + uart_obj[UART2_INDEX].serial.config.rx_bufsz = BSP_UART2_RX_BUFSIZE; + uart_obj[UART2_INDEX].serial.config.tx_bufsz = BSP_UART2_TX_BUFSIZE; + +#ifdef BSP_UART2_RX_USING_DMA + uart_obj[UART2_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart2_dma_rx = UART2_DMA_RX_CONFIG; + uart_config[UART2_INDEX].dma_rx = &uart2_dma_rx; +#endif + +#ifdef BSP_UART2_TX_USING_DMA + uart_obj[UART2_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart2_dma_tx = UART2_DMA_TX_CONFIG; + uart_config[UART2_INDEX].dma_tx = &uart2_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART3 + uart_obj[UART3_INDEX].serial.config = config; + uart_obj[UART3_INDEX].uart_dma_flag = 0; + + uart_obj[UART3_INDEX].serial.config.rx_bufsz = BSP_UART3_RX_BUFSIZE; + uart_obj[UART3_INDEX].serial.config.tx_bufsz = BSP_UART3_TX_BUFSIZE; + +#ifdef BSP_UART3_RX_USING_DMA + uart_obj[UART3_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart3_dma_rx = UART3_DMA_RX_CONFIG; + uart_config[UART3_INDEX].dma_rx = &uart3_dma_rx; +#endif + +#ifdef BSP_UART3_TX_USING_DMA + uart_obj[UART3_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart3_dma_tx = UART3_DMA_TX_CONFIG; + uart_config[UART3_INDEX].dma_tx = &uart3_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART4 + uart_obj[UART4_INDEX].serial.config = config; + uart_obj[UART4_INDEX].uart_dma_flag = 0; + + uart_obj[UART4_INDEX].serial.config.rx_bufsz = BSP_UART4_RX_BUFSIZE; + uart_obj[UART4_INDEX].serial.config.tx_bufsz = BSP_UART4_TX_BUFSIZE; + +#ifdef BSP_UART4_RX_USING_DMA + uart_obj[UART4_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart4_dma_rx = UART4_DMA_RX_CONFIG; + uart_config[UART4_INDEX].dma_rx = &uart4_dma_rx; +#endif + +#ifdef BSP_UART4_TX_USING_DMA + uart_obj[UART4_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart4_dma_tx = UART4_DMA_TX_CONFIG; + uart_config[UART4_INDEX].dma_tx = &uart4_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART5 + uart_obj[UART5_INDEX].serial.config = config; + uart_obj[UART5_INDEX].uart_dma_flag = 0; + + uart_obj[UART5_INDEX].serial.config.rx_bufsz = BSP_UART5_RX_BUFSIZE; + uart_obj[UART5_INDEX].serial.config.tx_bufsz = BSP_UART5_TX_BUFSIZE; + +#ifdef BSP_UART5_RX_USING_DMA + uart_obj[UART5_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart5_dma_rx = UART5_DMA_RX_CONFIG; + uart_config[UART5_INDEX].dma_rx = &uart5_dma_rx; +#endif + +#ifdef BSP_UART5_TX_USING_DMA + uart_obj[UART5_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart5_dma_tx = UART5_DMA_TX_CONFIG; + uart_config[UART5_INDEX].dma_tx = &uart5_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART6 + uart_obj[UART6_INDEX].serial.config = config; + uart_obj[UART6_INDEX].uart_dma_flag = 0; + + uart_obj[UART6_INDEX].serial.config.rx_bufsz = BSP_UART6_RX_BUFSIZE; + uart_obj[UART6_INDEX].serial.config.tx_bufsz = BSP_UART6_TX_BUFSIZE; + +#ifdef BSP_UART6_RX_USING_DMA + uart_obj[UART6_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart6_dma_rx = UART6_DMA_RX_CONFIG; + uart_config[UART6_INDEX].dma_rx = &uart6_dma_rx; +#endif + +#ifdef BSP_UART6_TX_USING_DMA + uart_obj[UART6_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart6_dma_tx = UART6_DMA_TX_CONFIG; + uart_config[UART6_INDEX].dma_tx = &uart6_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART7 + uart_obj[UART7_INDEX].serial.config = config; + uart_obj[UART7_INDEX].uart_dma_flag = 0; + + uart_obj[UART7_INDEX].serial.config.rx_bufsz = BSP_UART7_RX_BUFSIZE; + uart_obj[UART7_INDEX].serial.config.tx_bufsz = BSP_UART7_TX_BUFSIZE; + +#ifdef BSP_UART7_RX_USING_DMA + uart_obj[UART7_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart7_dma_rx = UART7_DMA_RX_CONFIG; + uart_config[UART7_INDEX].dma_rx = &uart7_dma_rx; +#endif + +#ifdef BSP_UART7_TX_USING_DMA + uart_obj[UART7_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart7_dma_tx = UART7_DMA_TX_CONFIG; + uart_config[UART7_INDEX].dma_tx = &uart7_dma_tx; +#endif +#endif +} + + +/** +* @brief UART MSP Initialization +* This function configures the hardware resources used in this example: +* - Peripheral's clock enable +* - Peripheral's GPIO Configuration +* - NVIC configuration for UART interrupt request enable +* @param uart: UART handle pointer +* @retval None +*/ +static void gd32_uart_gpio_init(struct gd32_uart_config *pconfig) +{ + /* enable USART clock */ + rcu_periph_clock_enable(pconfig->tx_gpio_clk); + rcu_periph_clock_enable(pconfig->rx_gpio_clk); + rcu_periph_clock_enable(pconfig->per_clk); + + /* connect port to USARTx_Tx Rx */ + gpio_init(pconfig->tx_port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, pconfig->tx_pin); + gpio_init(pconfig->rx_port, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, pconfig->rx_pin); + +#ifdef RT_SERIAL_USING_DMA + +#endif +} + +static const struct rt_uart_ops gd32_uart_ops = +{ + .configure = _uart_configure, + .control = _uart_control, + .putc = _uart_putc, + .getc = _uart_getc, + .transmit = _uart_transmit +}; + +int rt_hw_usart_init(void) +{ + rt_err_t result = 0; + rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct gd32_uart); + + _uart_get_config(); + for (int i = 0; i < obj_num; i++) + { + /* init UART object */ + uart_obj[i].config = &uart_config[i]; + uart_obj[i].serial.ops = &gd32_uart_ops; + gd32_uart_gpio_init(&uart_config[i]); + + /* register UART device */ + result = rt_hw_serial_register(&uart_obj[i].serial, + uart_obj[i].config->name, + RT_DEVICE_FLAG_RDWR, + NULL); + RT_ASSERT(result == RT_EOK); + } + + return result; +} + +#endif /* RT_USING_SERIAL_V2 */ + + +/*********** (C) COPYRIGHT 2021 FiberHome *****END OF FILE****/ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_usart_v2.h b/bsp/gd32/libraries/gd32_drivers/drv_usart_v2.h new file mode 100644 index 0000000000000000000000000000000000000000..494904f8f5d4eebad31070b92682990e5ae59b81 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_usart_v2.h @@ -0,0 +1,61 @@ +/** + * @file drv_usart_v2.h + * @brief + * @author wangh (wanghuan3037@fiberhome.com) + * @version 1.0 + * @date 2021-12-20 + * @copyright Copyright (c) 2021 烽火通信 + */ +#ifndef __DRV_USART_V2_H +#define __DRV_USART_V2_H + +#include +#include +#include +#include +#include "uart_config.h" + +#define UART_RX_DMA_IT_IDLE_FLAG 0x00 +#define UART_RX_DMA_IT_HT_FLAG 0x01 +#define UART_RX_DMA_IT_TC_FLAG 0x02 + +/* gd32 config class */ +struct gd32_uart_config +{ + const char *name; + uint32_t uart_periph; ///< UART外设 + IRQn_Type irqn; ///< UART中断编号 + rcu_periph_enum per_clk; ///< UART外设时钟 + rcu_periph_enum tx_gpio_clk; ///< UART-TX引脚gpio时钟 + rcu_periph_enum rx_gpio_clk; ///< UART-RX引脚gpio时钟 + uint32_t tx_port; + uint16_t tx_pin; + uint32_t rx_port; + uint16_t rx_pin; + +#ifdef RT_SERIAL_USING_DMA + struct dma_config *dma_rx; + struct dma_config *dma_tx; +#endif +}; + + +/* gd32 uart dirver class */ +struct gd32_uart +{ + struct gd32_uart_config *config; + +#ifdef RT_SERIAL_USING_DMA + rt_size_t dma_rx_remaining_cnt; +#endif + + rt_uint16_t uart_dma_flag; + struct rt_serial_device serial; +}; + +int rt_hw_usart_init(void); + + +#endif // __DRV_USART_V2_H + +/*********** (C) COPYRIGHT 2021 FiberHome *****END OF FILE****/