From 85c8144afa54b0fb6e45908c93a5ca05edb117a7 Mon Sep 17 00:00:00 2001 From: GD32-MCU Date: Tue, 6 Sep 2022 14:18:48 +0800 Subject: [PATCH] add chip GD32F450 of GD32MCU Modify the file according to the checks update the board config files, and modify the gd32f4xx_progmem.c Add chip GD32F450 of GD32MCU delete the micro FAR, modify code style Add chip GD32F450 of GD32MCU --- arch/arm/Kconfig | 19 + arch/arm/include/gd32f4/chip.h | 113 + arch/arm/include/gd32f4/gd32f4xx_irq.h | 249 ++ arch/arm/include/gd32f4/irq.h | 105 + arch/arm/src/gd32f4/Kconfig | 2501 +++++++++++ arch/arm/src/gd32f4/Make.defs | 57 + arch/arm/src/gd32f4/chip.h | 57 + arch/arm/src/gd32f4/gd32f4xx.h | 50 + arch/arm/src/gd32f4/gd32f4xx_allocateheap.c | 395 ++ arch/arm/src/gd32f4/gd32f4xx_dma.c | 1051 +++++ arch/arm/src/gd32f4/gd32f4xx_dma.h | 262 ++ arch/arm/src/gd32f4/gd32f4xx_enet.c | 3878 +++++++++++++++++ arch/arm/src/gd32f4/gd32f4xx_enet.h | 65 + arch/arm/src/gd32f4/gd32f4xx_exti.c | 621 +++ arch/arm/src/gd32f4/gd32f4xx_exti.h | 235 + arch/arm/src/gd32f4/gd32f4xx_fmc.c | 702 +++ arch/arm/src/gd32f4/gd32f4xx_fmc.h | 253 ++ arch/arm/src/gd32f4/gd32f4xx_gpio.c | 558 +++ arch/arm/src/gd32f4/gd32f4xx_gpio.h | 312 ++ arch/arm/src/gd32f4/gd32f4xx_idle.c | 173 + arch/arm/src/gd32f4/gd32f4xx_irq.c | 556 +++ arch/arm/src/gd32f4/gd32f4xx_lowputc.c | 596 +++ arch/arm/src/gd32f4/gd32f4xx_lowputc.h | 92 + arch/arm/src/gd32f4/gd32f4xx_pmu.c | 666 +++ arch/arm/src/gd32f4/gd32f4xx_pmu.h | 395 ++ arch/arm/src/gd32f4/gd32f4xx_progmem.c | 686 +++ arch/arm/src/gd32f4/gd32f4xx_progmem.h | 44 + arch/arm/src/gd32f4/gd32f4xx_rcu.c | 762 ++++ arch/arm/src/gd32f4/gd32f4xx_rcu.h | 180 + arch/arm/src/gd32f4/gd32f4xx_serial.c | 2984 +++++++++++++ arch/arm/src/gd32f4/gd32f4xx_spi.c | 2433 +++++++++++ arch/arm/src/gd32f4/gd32f4xx_spi.h | 233 + arch/arm/src/gd32f4/gd32f4xx_start.c | 284 ++ arch/arm/src/gd32f4/gd32f4xx_start.h | 47 + arch/arm/src/gd32f4/gd32f4xx_syscfg.c | 248 ++ arch/arm/src/gd32f4/gd32f4xx_syscfg.h | 131 + arch/arm/src/gd32f4/gd32f4xx_timerisr.c | 136 + arch/arm/src/gd32f4/gd32f4xx_usart.h | 594 +++ .../src/gd32f4/hardware/gd32f450_memorymap.h | 138 + .../arm/src/gd32f4/hardware/gd32f450_pinmap.h | 847 ++++ arch/arm/src/gd32f4/hardware/gd32f4xx_dma.h | 480 ++ arch/arm/src/gd32f4/hardware/gd32f4xx_enet.h | 924 ++++ arch/arm/src/gd32f4/hardware/gd32f4xx_exti.h | 143 + arch/arm/src/gd32f4/hardware/gd32f4xx_fmc.h | 297 ++ arch/arm/src/gd32f4/hardware/gd32f4xx_gpio.h | 217 + .../src/gd32f4/hardware/gd32f4xx_memorymap.h | 38 + .../arm/src/gd32f4/hardware/gd32f4xx_pinmap.h | 39 + arch/arm/src/gd32f4/hardware/gd32f4xx_pmu.h | 133 + arch/arm/src/gd32f4/hardware/gd32f4xx_rcu.h | 668 +++ arch/arm/src/gd32f4/hardware/gd32f4xx_spi.h | 222 + .../arm/src/gd32f4/hardware/gd32f4xx_syscfg.h | 170 + arch/arm/src/gd32f4/hardware/gd32f4xx_uart.h | 244 ++ boards/Kconfig | 13 + boards/arm/gd32f4/gd32f450zk-eval/Kconfig | 121 + .../configs/btngpionsh/defconfig | 99 + .../configs/fmcfsnsh/defconfig | 88 + .../gd32f450zk-eval/configs/netnsh/defconfig | 84 + .../gd32f450zk-eval/configs/nsh/defconfig | 49 + .../configs/spifsnsh/defconfig | 92 + .../gd32f4/gd32f450zk-eval/include/board.h | 351 ++ .../gd32f4/gd32f450zk-eval/scripts/Make.defs | 41 + .../gd32f4/gd32f450zk-eval/scripts/gnu-elf.ld | 116 + .../gd32f450zk-eval/scripts/kernel-space.ld | 97 + .../gd32f4/gd32f450zk-eval/scripts/ld.script | 130 + .../gd32f4/gd32f450zk-eval/scripts/memory.ld | 85 + .../gd32f450zk-eval/scripts/user-space.ld | 111 + .../arm/gd32f4/gd32f450zk-eval/src/Makefile | 56 + .../gd32f450zk-eval/src/gd32f450z_eval.h | 190 + .../gd32f450zk-eval/src/gd32f4xx_appinit.c | 200 + .../gd32f450zk-eval/src/gd32f4xx_autoleds.c | 181 + .../gd32f450zk-eval/src/gd32f4xx_boot.c | 90 + .../gd32f450zk-eval/src/gd32f4xx_bringup.c | 184 + .../gd32f450zk-eval/src/gd32f4xx_buttons.c | 188 + .../gd32f450zk-eval/src/gd32f4xx_gd25.c | 137 + .../gd32f450zk-eval/src/gd32f4xx_gpio.c | 395 ++ .../gd32f450zk-eval/src/gd32f4xx_romfs.c | 141 + .../gd32f450zk-eval/src/gd32f4xx_romfs.h | 62 + .../gd32f4/gd32f450zk-eval/src/gd32f4xx_spi.c | 283 ++ .../gd32f450zk-eval/src/gd32f4xx_userleds.c | 153 + 79 files changed, 31020 insertions(+) create mode 100644 arch/arm/include/gd32f4/chip.h create mode 100644 arch/arm/include/gd32f4/gd32f4xx_irq.h create mode 100644 arch/arm/include/gd32f4/irq.h create mode 100644 arch/arm/src/gd32f4/Kconfig create mode 100644 arch/arm/src/gd32f4/Make.defs create mode 100644 arch/arm/src/gd32f4/chip.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_allocateheap.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_dma.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_dma.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_enet.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_enet.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_exti.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_exti.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_fmc.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_fmc.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_gpio.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_gpio.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_idle.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_irq.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_lowputc.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_lowputc.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_pmu.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_pmu.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_progmem.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_progmem.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_rcu.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_rcu.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_serial.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_spi.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_spi.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_start.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_start.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_syscfg.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_syscfg.h create mode 100644 arch/arm/src/gd32f4/gd32f4xx_timerisr.c create mode 100644 arch/arm/src/gd32f4/gd32f4xx_usart.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f450_memorymap.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f450_pinmap.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_dma.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_enet.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_exti.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_fmc.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_gpio.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_memorymap.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_pinmap.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_pmu.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_rcu.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_spi.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_syscfg.h create mode 100644 arch/arm/src/gd32f4/hardware/gd32f4xx_uart.h create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/Kconfig create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/configs/btngpionsh/defconfig create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/configs/fmcfsnsh/defconfig create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/configs/netnsh/defconfig create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/configs/nsh/defconfig create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/configs/spifsnsh/defconfig create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/include/board.h create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/scripts/Make.defs create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/scripts/gnu-elf.ld create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/scripts/kernel-space.ld create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/scripts/ld.script create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/scripts/memory.ld create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/scripts/user-space.ld create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/Makefile create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f450z_eval.h create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_appinit.c create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_autoleds.c create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_boot.c create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_bringup.c create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_buttons.c create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_gd25.c create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_gpio.c create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_romfs.c create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_romfs.h create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_spi.c create mode 100644 boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_userleds.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 870655b2f3..c6474c937f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -69,6 +69,21 @@ config ARCH_CHIP_EOSS3 ---help--- QuickLogic EOS S3 (ARM Cortex-M4) +config ARCH_CHIP_GD32F4 + bool "GD32MCU GD32 F4" + select ARCH_CORTEXM4 + select ARCH_HAVE_MPU + select ARCH_HAVE_FETCHADD + select ARCH_HAVE_I2CRESET + select ARCH_HAVE_HEAPCHECK + select ARCH_HAVE_PROGMEM + select ARCH_HAVE_SPI_BITORDER + select ARCH_HAVE_TICKLESS + select ARM_HAVE_MPU_UNIFIED + select ARMV7M_HAVE_STACKCHECK + ---help--- + GD32MCU GD32 architectures (ARM Cortex-M4). + config ARCH_CHIP_IMX1 bool "NXP/Freescale iMX.1" select ARCH_ARM920T @@ -863,6 +878,7 @@ config ARCH_CHIP default "dm320" if ARCH_CHIP_DM320 default "efm32" if ARCH_CHIP_EFM32 default "eoss3" if ARCH_CHIP_EOSS3 + default "gd32f4" if ARCH_CHIP_GD32F4 default "imx1" if ARCH_CHIP_IMX1 default "imx6" if ARCH_CHIP_IMX6 default "imxrt" if ARCH_CHIP_IMXRT @@ -1188,6 +1204,9 @@ endif if ARCH_CHIP_EOSS3 source "arch/arm/src/eoss3/Kconfig" endif +if ARCH_CHIP_GD32F4 +source "arch/arm/src/gd32f4/Kconfig" +endif if ARCH_CHIP_IMX1 source "arch/arm/src/imx1/Kconfig" endif diff --git a/arch/arm/include/gd32f4/chip.h b/arch/arm/include/gd32f4/chip.h new file mode 100644 index 0000000000..a2b45d8bf0 --- /dev/null +++ b/arch/arm/include/gd32f4/chip.h @@ -0,0 +1,113 @@ +/**************************************************************************** + * arch/arm/include/gd32f4/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_GD32F4_CHIP_H +#define __ARCH_ARM_INCLUDE_GD32F4_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +/* Check the GD32F4 family configuration. + * It must be done in arch/arm/src/gd32f4/Kconfig ! + */ + +#if defined(CONFIG_ARCH_CHIP_GD32F450IK) +# define GD32_NGPIO_PORTS 9 /* GPIOA-I */ +# define GD32_NCRC 1 /* CRC calculation unit */ +# define GD32_NTRNG 1 /* True random number generator (RNG) */ +# define GD32_NDMA 2 /* DMA0,1 */ +# define GD32_NIPA 1 /* Image processing accelerator */ +# define GD32_NIREF 1 /* Programmable current reference */ +# define GD32_NADC 3 /* 12-bit ADC0-2, 19 channels */ +# define GD32_NDAC 2 /* 12-bit DAC0,1 */ +# define GD32_NATIMER 2 /* Two advanced timers TIMER0 and 7 that support DMA */ +# define GD32_NGTIMER 4 /* 16-bit general timers TIMER2 and 3 + * 32-bit general timers TIMER1 and 4 that support DMA */ +# define GD32_NGTIMNDMA 6 /* 16-bit general timers TIMER8-13 that not support DMA */ +# define GD32_NBTIMER 2 /* Two basic timers, TIMER5,6 that support DMA */ +# define GD32_NUSART 8 /* USART0-2 and 5, UART 3,4 and 6,7 */ +# define GD32_NI2C 3 /* I2C0-2 */ +# define GD32_NSPI 6 /* SPI0-5 */ +# define GD32_NI2S 2 /* I2S1-2 (multiplexed with SPI1-2) */ +# define GD32_NDCI 1 /* Digital camera interface (DCI) */ +# define GD32_NTLI 1 /* TFT-LCD interface (TLI) */ +# define GD32_NSDIO 1 /* Secure digital input/output interface */ +# define GD32_NEXMC 1 /* External memory controller */ +# define GD32_NCAN 2 /* CAN0-1 */ +# define GD32_NETHERNET 1 /* 10/100 Ethernet MAC */ +# define GD32_NUSBFS 1 /* USB FS*/ +# define GD32_NUSBHS 1 /* USB HS*/ + +#elif defined(CONFIG_ARCH_CHIP_GD32F450ZK) +# define GD32_NGPIO_PORTS 8 /* GPIOA-H */ +# define GD32_NCRC 1 /* CRC calculation unit */ +# define GD32_NTRNG 1 /* True random number generator (RNG) */ +# define GD32_NDMA 2 /* DMA0,1 */ +# define GD32_NIPA 1 /* Image processing accelerator */ +# define GD32_NIREF 1 /* Programmable current reference */ +# define GD32_NADC 3 /* 12-bit ADC0-2, 19 channels */ +# define GD32_NDAC 2 /* 12-bit DAC0,1 */ +# define GD32_NATIMER 2 /* Two advanced timers TIMER0 and 7 that support DMA */ +# define GD32_NGTIMER 4 /* 16-bit general timers TIMER2 and 3 + * 32-bit general timers TIMER1 and 4 that support DMA */ +# define GD32_NGTIMNDMA 6 /* 16-bit general timers TIMER8-13 that not support DMA */ +# define GD32_NBTIMER 2 /* Two basic timers, TIMER5,6 that support DMA */ +# define GD32_NUSART 8 /* USART0-2 and 5, UART 3,4 and 6,7 */ +# define GD32_NI2C 3 /* I2C0-2 */ +# define GD32_NSPI 6 /* SPI0-5 */ +# define GD32_NI2S 2 /* I2S1-2 (multiplexed with SPI1-2) */ +# define GD32_NDCI 1 /* Digital camera interface (DCI) */ +# define GD32_NTLI 1 /* TFT-LCD interface (TLI) */ +# define GD32_NSDIO 1 /* Secure digital input/output interface */ +# define GD32_NEXMC 1 /* External memory controller */ +# define GD32_NCAN 2 /* CAN0-1 */ +# define GD32_NETHERNET 1 /* 10/100 Ethernet MAC */ +# define GD32_NUSBFS 1 /* USB FS*/ +# define GD32_NUSBHS 1 /* USB HS*/ +#else +# error "Unknown GD32F4 chip type" +#endif + +/* Get customizations for each supported chip and provide alternate function + * pin-mapping + * + * NOTE: Each GPIO pin may serve either for general purpose I/O or for a + * special alternate function (such as USART, CAN, USB, SDIO, etc.). That + * particular pin-mapping will depend on the package and GD32 family. If + * you are incorporating a new GD32 chip into NuttX, you will need to add + * the pin-mapping to a header file and to include that header file below. + * The chip-specific pin-mapping is defined in the chip datasheet. + */ + +/* NVIC priority levels *****************************************************/ + +#define NVIC_SYSH_PRIORITY_MIN 0xf0 /* All bits set in minimum priority */ +#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */ +#define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ +#define NVIC_SYSH_PRIORITY_STEP 0x10 /* Four bits of interrupt priority used */ + +#endif /* __ARCH_ARM_INCLUDE_GD32F4_CHIP_H */ diff --git a/arch/arm/include/gd32f4/gd32f4xx_irq.h b/arch/arm/include/gd32f4/gd32f4xx_irq.h new file mode 100644 index 0000000000..19b3324b13 --- /dev/null +++ b/arch/arm/include/gd32f4/gd32f4xx_irq.h @@ -0,0 +1,249 @@ +/**************************************************************************** + * arch/arm/include/gd32f4/gd32f4xx_irq.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_GD32_GD32F4XX_IRQ_H +#define __ARCH_ARM_INCLUDE_GD32_GD32F4XX_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +/* IRQ numbers. + * The IRQ number corresponds vector number and hence map directly to + * bits in the NVIC. This does, however, waste several words of memory in + * the IRQ to handle mapping tables. + * + * Processor Exceptions (vectors 0-15). These common definitions can + * be found in nuttx/arch/arm/include/gd32/irq.h + * + * External interrupts (vectors >= 16) + */ + +#define GD32_IRQ_WWDGT (GD32_IRQ_EXINT+0) /* 0: window watchdog timer interrupt */ +#define GD32_IRQ_LVD (GD32_IRQ_EXINT+1) /* 1: LVD through EXTI line detect interrupt */ +#define GD32_IRQ_TAMPER_STAMP (GD32_IRQ_EXINT+2) /* 2: tamper and timestamp through EXTI line detect */ +#define GD32_IRQ_RTC_WKUP (GD32_IRQ_EXINT+3) /* 3: RTC wakeup through EXTI line interrupt */ +#define GD32_IRQ_FMC (GD32_IRQ_EXINT+4) /* 4: FMC interrupt */ +#define GD32_IRQ_RCU_CTC (GD32_IRQ_EXINT+5) /* 5: RCU and CTC interrupt */ +#define GD32_IRQ_EXTI0 (GD32_IRQ_EXINT+6) /* 6: EXTI Line 0 interrupt */ +#define GD32_IRQ_EXTI1 (GD32_IRQ_EXINT+7) /* 7: EXTI Line 1 interrupt */ +#define GD32_IRQ_EXTI2 (GD32_IRQ_EXINT+8) /* 8: EXTI Line 2 interrupt */ +#define GD32_IRQ_EXTI3 (GD32_IRQ_EXINT+9) /* 9: EXTI Line 3 interrupt */ +#define GD32_IRQ_EXTI4 (GD32_IRQ_EXINT+10) /* 10: EXTI Line 4 interrupt */ +#define GD32_IRQ_DMA0_CHANNEL0 (GD32_IRQ_EXINT+11) /* 11: DMA0 channel0 Interrupt */ +#define GD32_IRQ_DMA0_CHANNEL1 (GD32_IRQ_EXINT+12) /* 12: DMA0 channel1 Interrupt */ +#define GD32_IRQ_DMA0_CHANNEL2 (GD32_IRQ_EXINT+13) /* 13: DMA0 channel2 Interrupt */ +#define GD32_IRQ_DMA0_CHANNEL3 (GD32_IRQ_EXINT+14) /* 14: DMA0 channel3 Interrupt */ +#define GD32_IRQ_DMA0_CHANNEL4 (GD32_IRQ_EXINT+15) /* 15: DMA0 channel4 Interrupt */ +#define GD32_IRQ_DMA0_CHANNEL5 (GD32_IRQ_EXINT+16) /* 16: DMA0 channel5 Interrupt */ +#define GD32_IRQ_DMA0_CHANNEL6 (GD32_IRQ_EXINT+17) /* 17: DMA0 channel6 Interrupt */ +#define GD32_IRQ_ADC (GD32_IRQ_EXINT+18) /* 18: ADC interrupt */ +#define GD32_IRQ_CAN0_TX (GD32_IRQ_EXINT+19) /* 19: CAN0 TX interrupt */ +#define GD32_IRQ_CAN0_RX0 (GD32_IRQ_EXINT+20) /* 20: CAN0 RX0 interrupt */ +#define GD32_IRQ_CAN0_RX1 (GD32_IRQ_EXINT+21) /* 21: CAN0 RX1 interrupt */ +#define GD32_IRQ_CAN0_EWMC (GD32_IRQ_EXINT+22) /* 22: CAN0 EWMC interrupt */ +#define GD32_IRQ_EXTI5_9 (GD32_IRQ_EXINT+23) /* 23: EXTI[9:5] interrupts */ +#define GD32_IRQ_TIMER0_BRK_TIMER8 (GD32_IRQ_EXINT+24) /* 24: TIMER0 break and TIMER8 interrupts */ +#define GD32_IRQ_TIMER0_UP_TIMER9 (GD32_IRQ_EXINT+25) /* 25: TIMER0 update and TIMER9 interrupts */ +#define GD32_IRQ_TIMER0_TRG_CMT_TIMER10 (GD32_IRQ_EXINT+26) /* 26: TIMER0 trigger and commutation and TIMER10 interrupts */ +#define GD32_IRQ_TIMER0_CHANNEL (GD32_IRQ_EXINT+27) /* 27: TIMER0 channel capture compare interrupt */ +#define GD32_IRQ_TIMER1 (GD32_IRQ_EXINT+28) /* 28: TIMER1 interrupt */ +#define GD32_IRQ_TIMER2 (GD32_IRQ_EXINT+29) /* 29: TIMER2 interrupt */ +#define GD32_IRQ_TIMER3 (GD32_IRQ_EXINT+30) /* 30: TIMER3 interrupt */ +#define GD32_IRQ_I2C0_EV (GD32_IRQ_EXINT+31) /* 31: I2C0 event interrupt */ +#define GD32_IRQ_I2C0_ER (GD32_IRQ_EXINT+32) /* 32: I2C0 error interrupt */ +#define GD32_IRQ_I2C1_EV (GD32_IRQ_EXINT+33) /* 33: I2C1 event interrupt */ +#define GD32_IRQ_I2C1_ER (GD32_IRQ_EXINT+34) /* 34: I2C1 error interrupt */ +#define GD32_IRQ_SPI0 (GD32_IRQ_EXINT+35) /* 35: SPI0 interrupt */ +#define GD32_IRQ_SPI1 (GD32_IRQ_EXINT+36) /* 36: SPI1 interrupt */ +#define GD32_IRQ_USART0 (GD32_IRQ_EXINT+37) /* 37: USART0 interrupt */ +#define GD32_IRQ_USART1 (GD32_IRQ_EXINT+38) /* 38: USART1 interrupt */ +#define GD32_IRQ_USART2 (GD32_IRQ_EXINT+39) /* 39: USART2 interrupt */ +#define GD32_IRQ_EXTI10_15 (GD32_IRQ_EXINT+40) /* 40: EXTI[15:10] interrupts */ +#define GD32_IRQ_RTC_Alarm (GD32_IRQ_EXINT+41) /* 41: RTC alarm interrupt */ +#define GD32_IRQ_USBFS_WKUP (GD32_IRQ_EXINT+42) /* 42: USBFS wakeup interrupt */ +#define GD32_IRQ_TIMER7_BRK_TIMER11 (GD32_IRQ_EXINT+43) /* 43: TIMER7 break and TIMER11 interrupts */ +#define GD32_IRQ_TIMER7_UP_TIMER12 (GD32_IRQ_EXINT+44) /* 44: TIMER7 update and TIMER12 interrupts */ +#define GD32_IRQ_TIMER7_TRG_CMT_TIMER13 (GD32_IRQ_EXINT+45) /* 45: TIMER7 trigger and commutation and TIMER13 interrupts */ +#define GD32_IRQ_TIMER7_CHANNEL (GD32_IRQ_EXINT+46) /* 46: TIMER7 channel capture compare interrupt */ +#define GD32_IRQ_DMA0_CHANNEL7 (GD32_IRQ_EXINT+47) /* 47: DMA0 channel7 interrupt */ + +#if defined(CONFIG_GD32F4_GD32F450) +#define GD32_IRQ_EXMC (GD32_IRQ_EXINT+48) /* 48: EXMC interrupt */ +#define GD32_IRQ_SDIO (GD32_IRQ_EXINT+49) /* 49: SDIO interrupt */ +#define GD32_IRQ_TIMER4 (GD32_IRQ_EXINT+50) /* 50: TIMER4 interrupt */ +#define GD32_IRQ_SPI2 (GD32_IRQ_EXINT+51) /* 51: SPI2 interrupt */ +#define GD32_IRQ_UART3 (GD32_IRQ_EXINT+52) /* 52: UART3 interrupt */ +#define GD32_IRQ_UART4 (GD32_IRQ_EXINT+53) /* 53: UART4 interrupt */ +#define GD32_IRQ_TIMER5_DAC (GD32_IRQ_EXINT+54) /* 54: TIMER5 and DAC0 DAC1 underrun error interrupts */ +#define GD32_IRQ_TIMER6 (GD32_IRQ_EXINT+55) /* 55: TIMER6 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL0 (GD32_IRQ_EXINT+56) /* 56: DMA1 channel0 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL1 (GD32_IRQ_EXINT+57) /* 57: DMA1 channel1 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL2 (GD32_IRQ_EXINT+58) /* 58: DMA1 channel2 interruptt */ +#define GD32_IRQ_DMA1_CHANNEL3 (GD32_IRQ_EXINT+59) /* 59: DMA1 channel3 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL4 (GD32_IRQ_EXINT+60) /* 60: DMA1 channel4 interrupt */ +#define GD32_IRQ_ENET (GD32_IRQ_EXINT+61) /* 61: ENET interrupt */ +#define GD32_IRQ_ENET_WKUP (GD32_IRQ_EXINT+62) /* 62: ENET wakeup interrupt */ +#define GD32_IRQ_CAN1_TX (GD32_IRQ_EXINT+63) /* 63: CAN1 TX interrupt */ +#define GD32_IRQ_CAN1_RX0 (GD32_IRQ_EXINT+64) /* 64: CAN1 RX0 interrupt */ +#define GD32_IRQ_CAN1_RX1 (GD32_IRQ_EXINT+65) /* 65: CAN1 RX1 interrupt */ +#define GD32_IRQ_CAN1_EWMC (GD32_IRQ_EXINT+66) /* 66: CAN1 EWMC interrupt */ +#define GD32_IRQ_USBFS (GD32_IRQ_EXINT+67) /* 67: USBFS interrupt */ +#define GD32_IRQ_DMA1_CHANNEL5 (GD32_IRQ_EXINT+68) /* 68: DMA1 channel5 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL6 (GD32_IRQ_EXINT+69) /* 69: DMA1 channel6 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL7 (GD32_IRQ_EXINT+70) /* 70: DMA1 channel7 interrupt */ +#define GD32_IRQ_USART5 (GD32_IRQ_EXINT+71) /* 71: USART5 interrupt */ +#define GD32_IRQ_I2C2_EV (GD32_IRQ_EXINT+72) /* 72: I2C2 event interrupt */ +#define GD32_IRQ_I2C2_ER (GD32_IRQ_EXINT+73) /* 73: I2C2 error interrupt */ +#define GD32_IRQ_USBHS_EP1_Out (GD32_IRQ_EXINT+74) /* 74: USBHS endpoint 1 out interrupt */ +#define GD32_IRQ_USBHS_EP1_In (GD32_IRQ_EXINT+75) /* 75: USBHS endpoint 1 in interrupt */ +#define GD32_IRQ_USBHS_WKUP (GD32_IRQ_EXINT+76) /* 76: USBHS wakeup through EXTI line interrupt */ +#define GD32_IRQ_USBHS (GD32_IRQ_EXINT+77) /* 77: USBHS interrupt */ +#define GD32_IRQ_DCI (GD32_IRQ_EXINT+78) /* 78: DCI interrupt */ +#define GD32_IRQ_TRNG (GD32_IRQ_EXINT+80) /* 80: TRNG interrupt */ +#define GD32_IRQ_FPU (GD32_IRQ_EXINT+81) /* 81: FPU interrupt */ +#define GD32_IRQ_UART6 (GD32_IRQ_EXINT+82) /* 82: UART6 interrupt */ +#define GD32_IRQ_UART7 (GD32_IRQ_EXINT+83) /* 83: UART7 interrupt */ +#define GD32_IRQ_SPI3 (GD32_IRQ_EXINT+84) /* 84: SPI3 interrupt */ +#define GD32_IRQ_SPI4 (GD32_IRQ_EXINT+85) /* 85: SPI4 interrupt */ +#define GD32_IRQ_SPI5 (GD32_IRQ_EXINT+86) /* 86: SPI5 interrupt */ +#define GD32_IRQ_TLI (GD32_IRQ_EXINT+88) /* 88: TLI interrupt */ +#define GD32_IRQ_TLI_ER (GD32_IRQ_EXINT+89) /* 89: TLI error interrupt */ +#define GD32_IRQ_IPA (GD32_IRQ_EXINT+90) /* 90: IPA interrupt */ + +#elif defined(CONFIG_GD32F4_GD32F407) +#define GD32_IRQ_EXMC (GD32_IRQ_EXINT+48) /* 48: EXMC interrupt */ +#define GD32_IRQ_SDIO (GD32_IRQ_EXINT+49) /* 49: SDIO interrupt */ +#define GD32_IRQ_TIMER4 (GD32_IRQ_EXINT+50) /* 50: TIMER4 interrupt */ +#define GD32_IRQ_SPI2 (GD32_IRQ_EXINT+51) /* 51: SPI2 interrupt */ +#define GD32_IRQ_UART3 (GD32_IRQ_EXINT+52) /* 52: UART3 interrupt */ +#define GD32_IRQ_UART4 (GD32_IRQ_EXINT+53) /* 53: UART4 interrupt */ +#define GD32_IRQ_TIMER5_DAC (GD32_IRQ_EXINT+54) /* 54: TIMER5 and DAC0 DAC1 underrun error interrupts */ +#define GD32_IRQ_TIMER6 (GD32_IRQ_EXINT+55) /* 55: TIMER6 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL0 (GD32_IRQ_EXINT+56) /* 56: DMA1 channel0 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL1 (GD32_IRQ_EXINT+57) /* 57: DMA1 channel1 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL2 (GD32_IRQ_EXINT+58) /* 58: DMA1 channel2 interruptt */ +#define GD32_IRQ_DMA1_CHANNEL3 (GD32_IRQ_EXINT+59) /* 59: DMA1 channel3 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL4 (GD32_IRQ_EXINT+60) /* 60: DMA1 channel4 interrupt */ +#define GD32_IRQ_ENET (GD32_IRQ_EXINT+61) /* 61: ENET interrupt */ +#define GD32_IRQ_ENET_WKUP (GD32_IRQ_EXINT+62) /* 62: ENET wakeup interrupt */ +#define GD32_IRQ_CAN1_TX (GD32_IRQ_EXINT+63) /* 63: CAN1 TX interrupt */ +#define GD32_IRQ_CAN1_RX0 (GD32_IRQ_EXINT+64) /* 64: CAN1 RX0 interrupt */ +#define GD32_IRQ_CAN1_RX1 (GD32_IRQ_EXINT+65) /* 65: CAN1 RX1 interrupt */ +#define GD32_IRQ_CAN1_EWMC (GD32_IRQ_EXINT+66) /* 66: CAN1 EWMC interrupt */ +#define GD32_IRQ_USBFS (GD32_IRQ_EXINT+67) /* 67: USBFS interrupt */ +#define GD32_IRQ_DMA1_CHANNEL5 (GD32_IRQ_EXINT+68) /* 68: DMA1 channel5 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL6 (GD32_IRQ_EXINT+69) /* 69: DMA1 channel6 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL7 (GD32_IRQ_EXINT+70) /* 70: DMA1 channel7 interrupt */ +#define GD32_IRQ_USART5 (GD32_IRQ_EXINT+71) /* 71: USART5 interrupt */ +#define GD32_IRQ_I2C2_EV (GD32_IRQ_EXINT+72) /* 72: I2C2 event interrupt */ +#define GD32_IRQ_I2C2_ER (GD32_IRQ_EXINT+73) /* 73: I2C2 error interrupt */ +#define GD32_IRQ_USBHS_EP1_Out (GD32_IRQ_EXINT+74) /* 74: USBHS endpoint 1 out interrupt */ +#define GD32_IRQ_USBHS_EP1_In (GD32_IRQ_EXINT+75) /* 75: USBHS endpoint 1 in interrupt */ +#define GD32_IRQ_USBHS_WKUP (GD32_IRQ_EXINT+76) /* 76: USBHS wakeup through EXTI line interrupt */ +#define GD32_IRQ_USBHS (GD32_IRQ_EXINT+77) /* 77: USBHS interrupt */ +#define GD32_IRQ_DCI (GD32_IRQ_EXINT+78) /* 78: DCI interrupt */ +#define GD32_IRQ_TRNG (GD32_IRQ_EXINT+80) /* 80: TRNG interrupt */ +#define GD32_IRQ_FPU (GD32_IRQ_EXINT+81) /* 81: FPU interrupt */ + +#elif defined(CONFIG_GD32F4_GD32F405) +#define GD32_IRQ_SDIO (GD32_IRQ_EXINT+49) /* 49: SDIO interrupt */ +#define GD32_IRQ_TIMER4 (GD32_IRQ_EXINT+50) /* 50: TIMER4 interrupt */ +#define GD32_IRQ_SPI2 (GD32_IRQ_EXINT+51) /* 51: SPI2 interrupt */ +#define GD32_IRQ_UART3 (GD32_IRQ_EXINT+52) /* 52: UART3 interrupt */ +#define GD32_IRQ_UART4 (GD32_IRQ_EXINT+53) /* 53: UART4 interrupt */ +#define GD32_IRQ_TIMER5_DAC (GD32_IRQ_EXINT+54) /* 54: TIMER5 and DAC0 DAC1 underrun error interrupts */ +#define GD32_IRQ_TIMER6 (GD32_IRQ_EXINT+55) /* 55: TIMER6 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL0 (GD32_IRQ_EXINT+56) /* 56: DMA1 channel0 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL1 (GD32_IRQ_EXINT+57) /* 57: DMA1 channel1 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL2 (GD32_IRQ_EXINT+58) /* 58: DMA1 channel2 interruptt */ +#define GD32_IRQ_DMA1_CHANNEL3 (GD32_IRQ_EXINT+59) /* 59: DMA1 channel3 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL4 (GD32_IRQ_EXINT+60) /* 60: DMA1 channel4 interrupt */ +#define GD32_IRQ_CAN1_TX (GD32_IRQ_EXINT+63) /* 63: CAN1 TX interrupt */ +#define GD32_IRQ_CAN1_RX0 (GD32_IRQ_EXINT+64) /* 64: CAN1 RX0 interrupt */ +#define GD32_IRQ_CAN1_RX1 (GD32_IRQ_EXINT+65) /* 65: CAN1 RX1 interrupt */ +#define GD32_IRQ_CAN1_EWMC (GD32_IRQ_EXINT+66) /* 66: CAN1 EWMC interrupt */ +#define GD32_IRQ_USBFS (GD32_IRQ_EXINT+67) /* 67: USBFS interrupt */ +#define GD32_IRQ_DMA1_CHANNEL5 (GD32_IRQ_EXINT+68) /* 68: DMA1 channel5 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL6 (GD32_IRQ_EXINT+69) /* 69: DMA1 channel6 interrupt */ +#define GD32_IRQ_DMA1_CHANNEL7 (GD32_IRQ_EXINT+70) /* 70: DMA1 channel7 interrupt */ +#define GD32_IRQ_USART5 (GD32_IRQ_EXINT+71) /* 71: USART5 interrupt */ +#define GD32_IRQ_I2C2_EV (GD32_IRQ_EXINT+72) /* 72: I2C2 event interrupt */ +#define GD32_IRQ_I2C2_ER (GD32_IRQ_EXINT+73) /* 73: I2C2 error interrupt */ +#define GD32_IRQ_USBHS_EP1_Out (GD32_IRQ_EXINT+74) /* 74: USBHS endpoint 1 out interrupt */ +#define GD32_IRQ_USBHS_EP1_In (GD32_IRQ_EXINT+75) /* 75: USBHS endpoint 1 in interrupt */ +#define GD32_IRQ_USBHS_WKUP (GD32_IRQ_EXINT+76) /* 76: USBHS wakeup through EXTI line interrupt */ +#define GD32_IRQ_USBHS (GD32_IRQ_EXINT+77) /* 77: USBHS interrupt */ +#define GD32_IRQ_DCI (GD32_IRQ_EXINT+78) /* 78: DCI interrupt */ +#define GD32_IRQ_TRNG (GD32_IRQ_EXINT+80) /* 80: TRNG interrupt */ +#define GD32_IRQ_FPU (GD32_IRQ_EXINT+81) /* 81: FPU interrupt */ + +#else + #error "Unkonwn GD32F4xx chip." +#endif /* CONFIG_GD32F4_GD32F450 */ + +#if defined(CONFIG_GD32F4_GD32F450) +# define GD32_IRQ_NEXTINT (91) +# define NR_IRQS (GD32_IRQ_EXINT + GD32_IRQ_NEXTINT) +#elif defined(CONFIG_GD32F4_GD32F407) +# define GD32_IRQ_NEXTINT (82) +# define NR_IRQS (GD32_IRQ_EXINT + GD32_IRQ_NEXTINT) +#elif defined(CONFIG_GD32F4_GD32F405) +# define GD32_IRQ_NEXTINT (82) +# define NR_IRQS (GD32_IRQ_EXINT + GD32_IRQ_NEXTINT) +#else +# error "Unknown GD32F4xx chip!" +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_GD32_GD32F4XX_IRQ_H */ diff --git a/arch/arm/include/gd32f4/irq.h b/arch/arm/include/gd32f4/irq.h new file mode 100644 index 0000000000..50e964a26d --- /dev/null +++ b/arch/arm/include/gd32f4/irq.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * arch/arm/include/gd32f4/irq.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_GD32F4_IRQ_H +#define __ARCH_ARM_INCLUDE_GD32F4_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +/* IRQ numbers. + * The IRQ number corresponds vector number and hence map directly to + * bits in the NVIC. This does, however, waste several words of memory in + * the IRQ to handle mapping tables. + */ + +/* Processor Exceptions (vectors 0-15) */ + +#define GD32_IRQ_RESERVED (0) /* Reserved vector (only used with CONFIG_DEBUG_FEATURES) */ + /* Vector 0: Reset stack pointer value */ + /* Vector 1: Reset (not handler as an IRQ) */ +#define GD32_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt (NMI) */ +#define GD32_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */ +#define GD32_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */ +#define GD32_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */ +#define GD32_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */ +#define GD32_IRQ_SVCALL (11) /* Vector 11: SVC call */ +#define GD32_IRQ_DBGMONITOR (12) /* Vector 12: Debug Monitor */ + /* Vector 13: Reserved */ +#define GD32_IRQ_PENDSV (14) /* Vector 14: Pendable system service request */ +#define GD32_IRQ_SYSTICK (15) /* Vector 15: System tick */ + +/* External interrupts (vectors >= 16). + * These definitions are chip-specific + */ + +#define GD32_IRQ_EXINT (16) /* Vector number of the first external interrupt */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#if defined(CONFIG_GD32F4_GD32F4XX) +# include +#else +# error "Uknown GD32 chip" +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_GD32F4_IRQ_H */ diff --git a/arch/arm/src/gd32f4/Kconfig b/arch/arm/src/gd32f4/Kconfig new file mode 100644 index 0000000000..f8dfa3bf3e --- /dev/null +++ b/arch/arm/src/gd32f4/Kconfig @@ -0,0 +1,2501 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +# if ARCH_CHIP_GD32F4 + +comment "GD32F4 Configuration Options" + +choice + prompt "GD32F4 Chip Selection" + default ARCH_CHIP_GD32F450ZK + depends on ARCH_CHIP_GD32F4 + +config ARCH_CHIP_GD32F405VG + bool "GD32F405VG" + select GD32F4_GD32F4XX + select GD32F4_GD32F405 + ---help--- + GD32 F4 Cortex M4, 1024 Kb FLASH, 192 Kb SRAM + +config ARCH_CHIP_GD32F407VG + bool "GD32F407VG" + select GD32F4_GD32F4XX + select GD32F4_GD32F407 + ---help--- + GD32 F4 Cortex M4, 1024 Kb FLASH, 192 Kb SRAM + +config ARCH_CHIP_GD32F407ZK + bool "GD32F450ZK" + select GD32F4_GD32F4XX + select GD32F4_GD32F407 + ---help--- + GD32 F4 Cortex M4, 3072 Kb FLASH, 256 Kb SRAM + +config ARCH_CHIP_GD32F450VK + bool "GD32F450VK" + select GD32F4_GD32F4XX + select GD32F4_GD32F450V + ---help--- + GD32 F4 Cortex M4, 3072 Kb FLASH, 192 Kb SRAM + +config ARCH_CHIP_GD32F450ZK + bool "GD32F450ZK" + select GD32F4_GD32F4XX + select GD32F4_GD32F450Z_I + ---help--- + GD32 F4 Cortex M4, 3072 Kb FLASH, 256 Kb SRAM + +config ARCH_CHIP_GD32F450ZI + bool "GD32F450ZI" + select GD32F4_GD32F4XX + select GD32F4_GD32F450Z_I + select GD32F4_GD32F450XI + +config ARCH_CHIP_GD32F450IK + bool "GD32F450IK" + select GD32F4_GD32F4XX + select GD32F4_GD32F450Z_I + ---help--- + GD32 F4 Cortex M4, 3072 Kb FLASH, 256 Kb SRAM + + +endchoice # GD32F4 Chip Seclection + +choice + prompt "Override Flash Size Designator" + default GD32F4_FLASH_CONFIG_DEFAULT + depends on ARCH_CHIP_GD32F4 + ---help--- + GD32F4 series parts numbering (sans the package type) + ends with a number or letter that designates the FLASH size. + + Designator Size in KiB + E 512 + G 1024 + I 2048 + K 3072 + + This configuration option defaults to using the configuration based + on that designator or the default smaller size if there is no last + character designator is present in the GD32F4 Chip Selection. + + Examples: + If the GD32F407VE is chosen, the Flash configuration would be + 'E', if a variant of the part with a 2048 KiB Flash is released + in the future one could simply select the 'I' designator here. + + If an GD32F450xx or Series parts is chosen the default Flash + configuration will be 'E' and can be set herein to 'K' to choose + the larger FLASH part. + +config GD32F4_FLASH_CONFIG_DEFAULT + bool "Default" + +config GD32F4_FLASH_CONFIG_E + bool "E 512KiB" + +config GD32F4_FLASH_CONFIG_G + bool "G 1024KiB" + +config GD32F4_FLASH_CONFIG_I + bool "I 2048KiB" + +config GD32F4_FLASH_CONFIG_K + bool "K 3072KiB" + +endchoice + + +config GD32F4_GD32F4XX + bool + default n + select ARCH_HAVE_FPU + select GD32F4_HAVE_TCM + select GD32F4_HAVE_OVERDRIVE + select GD32F4_HAVE_EXMC + + +config GD32F4_GD32F405 + bool + default n + +config GD32F4_GD32F407 + bool + default n + select GD32F4_HAVE_ENETMAC + +config GD32F4_GD32F450Z_I + # bool "GD32F450Z or GD32F450I" + bool + default n + select GD32F4_GD32F450 + select GD32F4_HAVE_SPI5 + +config GD32F4_GD32F450XI + # bool "GD32F450xI, 512K SRAM" + bool + default n + +config GD32F4_GD32F450V + bool + default n + select GD32F4_GD32F450 + +config GD32F4_GD32F450 + bool + default n + select GD32F4_HAVE_ENETMAC + select GD32F4_HAVE_IPA + select GD32F4_HAVE_SPI3 + select GD32F4_HAVE_SPI4 + select GD32F4_HAVE_TLI + select GD32F4_HAVE_UART6 + select GD32F4_HAVE_UART7 + +config GD32F4_DFU + bool "DFU bootloader" + default n + depends on !GD32F4_VALUELINE + ---help--- + Configure and position code for use with the GD MCU DFU bootloader. Do + not select this option if you will load code using JTAG/SWM. + + +menu "GD32 Peripheral Support" + +# These "hidden" settings determine whether a peripheral option is available +# for the selected MCU + +config GD32F4_HAVE_OVERDRIVE + bool + default n + +config GD32F4_HAVE_ENETMAC + bool + default n + +config GD32F4_HAVE_EXMC + bool + default n + +config GD32F4_HAVE_IPA + bool + default n + +config GD32F4_HAVE_SPI3 + bool + default n + +config GD32F4_HAVE_SPI4 + bool + default n + +config GD32F4_HAVE_SPI5 + bool + default n + +config GD32F4_HAVE_UART6 + bool + default n + +config GD32F4_HAVE_UART7 + bool + default n + +config GD32F4_HAVE_TCM + bool + default n + +config GD32F4_HAVE_TLI + bool + default n + + +# These are the peripheral selections proper + +config GD32F4_ADC0 + bool "ADC0" + default n + select GD32F4_ADC + select GD32F4_HAVE_ADC0_DMA if GD32F4_DMA1 + +config GD32F4_ADC1 + bool "ADC1" + default n + select GD32F4_ADC + select GD32F4_HAVE_ADC1_DMA if GD32F4_DMA1 + +config GD32F4_ADC2 + bool "ADC2" + default n + select GD32F4_ADC + select GD32F4_HAVE_ADC2_DMA if GD32F4_DMA1 + +config GD32F4_BKPSRAM + bool "Enable BKP SRAM Domain" + default n + +config GD32F4_CAN0 + bool "CAN0" + select CAN + select GD32F4_CAN + default n + +config GD32F4_CAN1 + bool "CAN1" + select CAN + select GD32F4_CAN + default n + +config GD32F4_CRC + bool "CRC" + default n + +config GD32F4_CTC + bool "CTC" + default n + +config GD32F4_DAC0 + bool "DAC0" + default n + select GD32F4_DAC + +config GD32F4_DAC1 + bool "DAC1" + default n + select GD32F4_DAC + +config GD32F4_DBG + bool "DBG" + default n + +config GD32F4_DCI + bool "DCI" + default n + +config GD32F4_DMA0 + bool "DMA0" + default n + select GD32F4_DMA + select ARCH_DMA + +config GD32F4_DMA1 + bool "DMA1" + default n + select GD32F4_DMA + select ARCH_DMA + +config GD32F4_ENETMAC + bool "Ethernet MAC" + default n + depends on GD32F4_HAVE_ENETMAC + select NETDEVICES + select ARCH_HAVE_PHY + +config GD32F4_EXMC + bool "EXMC" + default n + depends on GD32F4_HAVE_EXMC + +config GD32F4_FMC + bool "FMC" + default n + +config GD32F4_PROGMEM + bool "PROGMEM" + default n + depends on GD32F4_FMC + select ARCH_HAVE_PROGMEM + select MTD_PROGMEM + # select MTD_PROGMEM_ERASESTATE + ---help--- + Use a part of GD32F4xx's internal flash memory as a + Memory-Technology-Device (MTD). + +config GD32F4_MTD + bool "MTD driver" + default n + depends on GD32F4_FMC + select MTD + select MTD_BYTE_WRITE + ---help--- + Initialize an MTD driver for the GD32F4xx on chip Flash, which will + add an entry at /dev for application access from userspace. + + +config GD32F4_FWDGT + bool "FWDGT" + default n + select GD32F4_WDGT + select WATCHDOG + +config GD32F4_IPA + bool "IPA" + default n + depends on GD32F4_HAVE_IPA + +config GD32F4_IREF + bool "IREF" + default n + +config GD32F4_I2C0 + bool "I2C0" + default n + select GD32F4_I2C + +config GD32F4_I2C1 + bool "I2C1" + default n + select GD32F4_I2C + +config GD32F4_I2C2 + bool "I2C2" + default n + select GD32F4_I2C + +config GD32F4_I2S1 + bool "I2S1" + default n + select SPI + select GD32F4_I2S + +config GD32F4_I2S2 + bool "I2S2" + default n + select SPI + select GD32F4_I2S + +config GD32F4_RTC + bool "RTC" + default n + +config GD32F4_PMU + bool "PMU" + default n + +config GD32F4_SDIO + bool "SDIO" + default n + +config GD32F4_SPI0 + bool "SPI0" + default n + select SPI + select GD32F4_SPI + +config GD32F4_SPI1 + bool "SPI1" + default n + select SPI + select GD32F4_SPI + +config GD32F4_SPI2 + bool "SPI2" + default n + select SPI + select GD32F4_SPI + +config GD32F4_SPI3 + bool "SPI3" + default n + select SPI + select GD32F4_SPI + depends on GD32F4_HAVE_SPI3 + +config GD32F4_SPI4 + bool "SPI4" + default n + select SPI + select GD32F4_SPI + depends on GD32F4_HAVE_SPI4 + +config GD32F4_SPI5 + bool "SPI5" + default n + select SPI + select GD32F4_SPI + depends on GD32F4_HAVE_SPI5 + +config GD32F4_SYSCFG + bool "SYSCFG" + default y + +config GD32F4_TCMSRAM + bool "CMD/DATA TCMSRAM" + default n + +config GD32F4_TIMER0 + bool "TIMER0" + default n + select GD32F4_TIMER + +config GD32F4_TIMER1 + bool "TIMER1" + default n + select GD32F4_TIMER + +config GD32F4_TIMER2 + bool "TIMER2" + default n + select GD32F4_TIMER + +config GD32F4_TIMER3 + bool "TIMER3" + default n + select GD32F4_TIMER + +config GD32F4_TIMER4 + bool "TIMER4" + default n + select GD32F4_TIMER + +config GD32F4_TIMER5 + bool "TIMER5" + default n + select GD32F4_TIMER + +config GD32F4_TIMER6 + bool "TIMER6" + default n + select GD32F4_TIMER + +config GD32F4_TIMER7 + bool "TIMER7" + default n + select GD32F4_TIMER + +config GD32F4_TIMER8 + bool "TIMER8" + default n + select GD32F4_TIMER + +config GD32F4_TIMER9 + bool "TIMER9" + default n + select GD32F4_TIMER + +config GD32F4_TIMER10 + bool "TIMER10" + default n + select GD32F4_TIMER + +config GD32F4_TIMER11 + bool "TIMER11" + default n + select GD32F4_TIMER + +config GD32F4_TIMER12 + bool "TIMER12" + default n + select GD32F4_TIMER + +config GD32F4_TIMER13 + bool "TIMER13" + default n + select GD32F4_TIMER + +config GD32F4_TLI + bool "TLI" + default n + +config GD32F4_TRNG + bool "TRNG" + default n + +config GD32F4_USART0 + bool "USART0" + default y + select GD32F4_USART + +config GD32F4_USART1 + bool "USART1" + default n + select GD32F4_USART + +config GD32F4_USART2 + bool "USART2" + default n + select GD32F4_USART + +config GD32F4_UART3 + bool "UART3" + default n + select GD32F4_USART + +config GD32F4_UART4 + bool "UART4" + default n + select GD32F4_USART + +config GD32F4_USART5 + bool "USART5" + default n + select GD32F4_USART + +config GD32F4_UART6 + bool "UART6" + default n + depends on GD32F4_HAVE_UART6 + select GD32F4_USART + +config GD32F4_UART7 + bool "UART7" + default n + depends on GD32F4_HAVE_UART7 + select GD32F4_USART + +config GD32F4_USBFS + bool "USBFS" + default n + +config GD32F4_USBHS + bool "USBHS" + default n + +config GD32F4_WWDGT + bool "WWDGT" + default n + select GD32F4_WDGT + select WATCHDOG + +endmenu #"GD32 Peripheral Support" + + +config GD32F4_ADC + bool + default n + +config GD32F4_CAN + bool + default n + +config GD32F4_DAC + bool + default n + +config GD32F4_DMA + bool + default n + +config GD32F4_EXMC + bool + default n + +config GD32F4_IPA + bool + default n + +config GD32F4_I2C + bool + default n + +config GD32F4_I2S + bool + default n + +config GD32F4_SPI + bool + default n + +config GD32F4_TIMER + bool + default n + +config GD32F4_USART + bool + default n + +config GD32F4_WDGT + bool + default n + + +config GD32F4_NOEXT_VECTORS + bool "Disable the ARMv7-M EXT vectors" + default n + ---help--- + Sometimes you may not need any Vector support beyond SysTick + and wish to save memory. This applies only to ARMv7-M architectures. + + +choice + prompt "JTAG Configuration" + default GD32F4_JTAG_DISABLE + ---help--- + JTAG Enable settings (by default JTAG-DP and SW-DP are disabled) + +config GD32F4_JTAG_DISABLE + bool "Disable all JTAG clocking" + +config GD32F4_JTAG_FULL_ENABLE + bool "Enable full SWJ (JTAG-DP + SW-DP)" + +config GD32F4_JTAG_NOJNTRST_ENABLE + bool "Enable full SWJ (JTAG-DP + SW-DP) but without JNTRST" + +config GD32F4_JTAG_SW_ENABLE + bool "Set JTAG-DP disabled and SW-DP enabled" + +endchoice + + +config GD32F4_DISABLE_IDLE_SLEEP_DURING_DEBUG + bool "Disable IDLE Sleep (WFI) in debug mode" + default n + ---help--- + In debug configuration, disables the WFI instruction in the IDLE loop + to prevent the JTAG from disconnecting. + +config GD32F4_FORCEPOWER + bool "Force power" + default n + ---help--- + Timer and I2C devices may need to the following to force power to be applied + unconditionally at power up. (Otherwise, the device is powered when it is + initialized). + +config ARCH_BOARD_GD32F4_CUSTOM_CLOCKCONFIG + bool "Custom clock configuration" + default n + ---help--- + Enables special, board-specific GD32F4 clock configuration. + +config GD32F4_TCMEXCLUDE + bool "Exclude TCM SRAM from the heap" + default y if ARCH_DMA || LIBC_ARCH_ELF + depends on GD32F4_HAVE_TCM + ---help--- + Exclude TCM SRAM from the HEAP because it cannot be used for DMA + and it appears to be impossible to execute ELF modules from TCM + RAM. + +config GD32F4_TCM_PROCFS + bool "TCM PROCFS support" + default n + depends on !DISABLE_MOUNTPOINT && FS_PROCFS && FS_PROCFS_REGISTER + ---help--- + Select to build in support for /proc/tcm. Reading from /proc/tcm + will provide statistics about TCM memory use similar to what you + would get from mallinfo() for the user heap. + + +config GD32F4_EXTERNAL_RAM + bool "External RAM on EXMC" + default n + depends on GD32F4_EXMC + select ARCH_HAVE_HEAP2 + ---help--- + In addition to internal SRAM, external RAM may be available through the EXMC. + + +menu "Timer Configuration" + depends on GD32F4_TIMER + +if SCHED_TICKLESS + +config GD32F4_TICKLESS_TIMER + int "Tickless by hardware timer" + default 1 + range 0 13 + depends on !GD32F4_TICKLESS_SYSTICK + ---help--- + If the Tickless OS feature is enabled, then one clock must be + assigned to provided the timer needed by the OS. + +config GD32F4_TICKLESS_CHANNEL + int "Tickless timer channel" + default 0 + range 0 3 + ---help--- + If the Tickless OS feature is enabled, the one clock must be + assigned to provided the free-running timer needed by the OS + and one channel on that clock is needed to handle intervals. + +endif # SCHED_TICKLESS + +config GD32F4_FREERUN + bool "Timer free-running wrapper" + default n + ---help--- + Enable a wrapper around the low level timer/counter functions to + support a free-running timer. + +config GD32F4_ONESHOT + bool "Timer one-shot wrapper" + default n + ---help--- + Enable a wrapper around the low level timer/counter functions to + support one-shot timer. + +config GD32F4_ONESHOT_MAXTIMERS + int "Maximum number of oneshot timers" + default 1 + range 1 8 + depends on GD32F4_ONESHOT + ---help--- + Determines the maximum number of oneshot timers that can be + supported. This setting pre-allocates some minimal support for each + of the timers and places an upper limit on the number of oneshot + timers that you can use. + +# config GD32F4_TIMER0 +# bool "TIMER0" +# default n +# depend on GD32F4_HAVE_TIMER0 + +config GD32F4_TIMER0_PWM + bool "TIMER0 PWM" + default n + depends on GD32F4_TIMER0 + select ARCH_HAVE_PWM_PULSECOUNT + ---help--- + Reserve timer 0 for use by PWM + + Timer devices may be used for different purposes. One special purpose is + to generate modulated outputs for such things as motor control. + If GD32F4_TIMER0 is defined then THIS following may also be defined + to indicate that the timer is intended to be used for pulsed output + modulation. + + +config GD32F4_TIMER0_MODE + int "TIMER0 Mode" + default 0 + range 0 4 + depends on GD32F4_TIMER0_PWM + ---help--- + Specifies the timer mode. + + +config GD32F4_TIMER0_FDTS + int "TIMER0 CKDIV for f_DTS" + default 0 + range 0 2 + depends on GD32F4_TIMER0_PWM + ---help--- + The CKDIV bits can be configured by software to specify division ratio + between the timer clock (TIMER_CK) and the dead-time and sampling clock (DTS), + which is used by the dead-time generators and the digital filters. + +config GD32F4_TIMER0_DEADTIME + int "TIMER0 Dead-time configure" + default 0 + range 0 255 + depends on GD32F4_TIMER0_PWM + ---help--- + This controls the value of the dead-time, which is inserted before the + output transitions. + + +config GD32F4_TIMER0_CHANNEL0 + bool "TIMER0 PWM Channel 0" + default n + depends on GD32F4_TIMER0_PWM + ---help--- + Enables channel 0. + +config GD32F4_TIMER0_CH1MODE + int "TIMER0 Channel 0 compare output mode control" + default 6 + range 0 7 + depends on GD32F4_TIMER0_CHANNEL0 + ---help--- + This controls the behavior of the output reference signal O0CPRE + which drives CH0_O and CH0_ON. + +config GD32F4_TIMER0_CH0O + bool "TIMER0 Channel 0 Output" + default n + depends on GD32F4_TIMER0_CHANNEL0 + ---help--- + Enables channel 0 output. + +config GD32F4_TIMER0_CH0ON + bool "TIMER0 Channel 0 Complementary Output" + default n + depends on GD32F4_TIMER0_CHANNEL0 + ---help--- + Enables channel 0 Complementary Output. + +config GD32F4_TIMER0_CHANNEL1 + bool "TIMER0 PWM Channel 1" + default n + depends on GD32F4_TIMER0_PWM + ---help--- + Enables channel 1. + +config GD32F4_TIMER0_CH1MODE + int "TIMER0 Channel 1 compare output mode control" + default 6 + range 0 7 + depends on GD32F4_TIMER0_CHANNEL1 + ---help--- + This controls the behavior of the output reference signal O1CPRE + which drives CH1_O and CH1_ON. + +config GD32F4_TIMER0_CH1O + bool "TIMER0 Channel 1 Output" + default n + depends on GD32F4_TIMER0_CHANNEL1 + ---help--- + Enables channel 1 output. + +config GD32F4_TIMER0_CH1ON + bool "TIMER0 Channel 1 Complementary Output" + default n + depends on GD32F4_TIMER0_CHANNEL1 + ---help--- + Enables channel 1 Complementary Output. + +config GD32F4_TIMER0_CHANNEL2 + bool "TIMER0 PWM Channel 2" + default n + depends on GD32F4_TIMER0_PWM + ---help--- + Enables channel 2. + +config GD32F4_TIMER0_CH2MODE + int "TIMER0 Channel 2 compare output mode control" + default 6 + range 0 7 + depends on GD32F4_TIMER0_CHANNEL2 + ---help--- + This controls the behavior of the output reference signal O2CPRE + which drives CH2_O and CH2_ON. + +config GD32F4_TIMER0_CH2O + bool "TIMER0 Channel 2 Output" + default n + depends on GD32F4_TIMER0_CHANNEL2 + ---help--- + Enables channel 2 output. + +config GD32F4_TIMER0_CH2ON + bool "TIMER0 Channel 2 Complementary Output" + default n + depends on GD32F4_TIMER0_CHANNEL2 + ---help--- + Enables channel 2 Complementary Output. + +config GD32F4_TIMER0_CHANNEL3 + bool "TIMER0 PWM Channel 3" + default n + depends on GD32F4_TIMER0_PWM + ---help--- + Enables channel 3. + +config GD32F4_TIMER0_CH3MODE + int "TIMER0 Channel 3 compare output mode control" + default 6 + range 0 7 + depends on GD32F4_TIMER0_CHANNEL3 + ---help--- + This controls the behavior of the output reference signal O3CPRE + which drives CH3_O and CH3_ON. + +config GD32F4_TIMER0_CH3O + bool "TIMER0 Channel 2 Output" + default n + depends on GD32F4_TIMER0_CHANNEL2 + ---help--- + Enables channel 2 output. + +config GD32F4_TIMER0_CH3ON + bool "TIMER0 Channel 3 Complementary Output" + default n + depends on GD32F4_TIMER0_CHANNEL3 + ---help--- + Enables channel 3 Complementary Output. + + +config GD32F4_TIMER0_ADC + bool "TIMER0 ADC" + default n + depends on GD32F4_TIMER0 && GD32F4_ADC + ---help--- + Reserve timer 0 for use by ADC + + Timer can be used for different purposes. When the timer0 + is intended to be used for ADC conversion, the GD32F4_TIMER0 + and GD32F4_ADC should be defined before. There requires two + definition for ADC usage: First, assign which timer is used to + trigger the ADC. Second, and configure which ADC to sample. + +choice + prompt "Select TIMER0 ADC channel" + default GD32F4_TIMER0_ADC0 + depends on GD32F4_TIMER0_ADC + +config GD32F4_TIMER0_ADC0 + bool "TIMER0 ADC channel 0" + depends on GD32F4_ADC0 + select GD32F4_HAVE_ADC0_TIMER + ---help--- + Reserve TIMER0 to trigger ADC0 + +config GD32F4_TIMER0_ADC1 + bool "TIMER0 ADC channel 1" + depends on GD32F4_ADC1 + select GD32F4_HAVE_ADC1_TIMER + ---help--- + Reserve TIMER0 to trigger ADC1 + +config GD32F4_TIMER0_ADC2 + bool "TIMER0 ADC channel 2" + depends on GD32F4_ADC2 + select GD32F4_HAVE_ADC2_TIMER + ---help--- + Reserve TIMER0 to trigger ADC2 + +endchoice + + + +config GD32F4_HAVE_ADC0_TIMER + bool + default n + +config GD32F4_HAVE_ADC1_TIMER + bool + default n + +config GD32F4_HAVE_ADC2_TIMER + bool + default n + + +config GD32F4_ADC0_SAMPLE_FREQUENCY + int "ADC0 Sampling Frequency" + default 500 + depends on GD32F4_HAVE_ADC0_TIMER + ---help--- + ADC0 sampling frequency. Default: 500Hz + +config GD32F4_ADC0_TIMERTRIG + int "ADC0 Timer Trigger Select" + default 0 + range 0 4 + depends on GD32F4_HAVE_ADC0_TIMER + ---help--- + Values 0:CH0 1:CH1 2:CH2 3:CH3 4:TRGO + +config GD32F4_ADC1_SAMPLE_FREQUENCY + int "ADC0 Sampling Frequency" + default 500 + depends on GD32F4_HAVE_ADC1_TIMER + ---help--- + ADC0 sampling frequency. Default: 500Hz + +config GD32F4_ADC1_TIMERTRIG + int "ADC0 Timer Trigger Select" + default 0 + range 0 4 + depends on GD32F4_HAVE_ADC1_TIMER + ---help--- + Values 0:CH0 1:CH1 2:CH2 3:CH3 4:TRGO + +config GD32F4_ADC2_SAMPLE_FREQUENCY + int "ADC0 Sampling Frequency" + default 500 + depends on GD32F4_HAVE_ADC2_TIMER + ---help--- + ADC0 sampling frequency. Default: 500Hz + +config GD32F4_ADC2_TIMERTRIG + int "ADC0 Timer Trigger Select" + default 0 + range 0 4 + depends on GD32F4_HAVE_ADC2_TIMER + ---help--- + Values 0:CH0 1:CH1 2:CH2 3:CH3 4:TRGO + + + +config GD32F4_TIMER0_DAC + bool "TIMER0 DAC" + default n + depends on GD32F4_TIMER0 && GD32F4_DAC + ---help--- + Reserve timer 0 for use by DAC + + Timer can be used for different purposes. When the timer0 + is intended to be used for DAC conversion, the GD32F4_TIMER0 + and GD32F4_DAC should be defined before. There requires two + definition for DAC usage: First, assign which timer is used to + trigger the DAC. Second, and configure which DAC channel to work. + +choice + prompt "Select TIMER DAC channel" + default GD32F4_TIMER0_DAC0 + depends on GD32F4_TIMER0_DAC + +config GD32F4_TIMER0_DAC0 + bool "TIMER0 DAC channel 0" + ---help--- + Reserve TIMER0 to trigger DAC0 + +config GD32F4_TIMER0_DAC1 + bool "TIMER0 DAC channel 1" + ---help--- + Reserve TIMER0 to trigger DAC1 + +endchoice + + +config GD32F4_TIMER0_CAP + bool "TIMER0 Capture" + default n + depends on GD32F4_TIMER0 + ---help--- + Reserve timer 0 for use by Capture + + Timer can be used for different purposes. To capture input is + one of the usual purpose. + + +menu "GD32F4 TIMER Outputs Configuration" + +config GD32F4_TIMER0_CH0P + int "TIMER0 Channel 0 Output polarity" + default 0 + range 0 1 + depends on GD32F4_TIMER0_CH0O + ---help--- + TIMER0 Channel 0 output polarity + +config GD32F4_TIMER0_CH0IDLE + int "TIMER0 Idle State of Channel 0 Output" + default 0 + range 0 1 + depends on GD32F4_TIMER0_CH0O + ---help--- + TIMER0 channel 0 output idle state + +config GD32F4_TIMER0_CH0NP + int "TIMER0 Channel 0 Complementary Output polarity" + default 0 + range 0 1 + depends on GD32F4_TIMER0_CH0ON + ---help--- + TIMER0 Channel 0 Complementary Output polarity + +config GD32F4_TIMER0_CH0NIDLE + int "TIMER0 Idle State of Channel 0 Complementary Output" + default 0 + range 0 1 + depends on GD32F4_TIMER0_CH0ON + ---help--- + TIMER0 channel 0 complementary output idle state + +endmenu # GD32F4 Timer Outputs Configuration + +endmenu # Timer Configuration + + +menu "ADC Configuration" + depends on GD32F4_ADC + +config GD32F4_ADC0_RESOLUTION + int "ADC0 resolution" + depends on GD32F4_ADC0 + default 0 + range 0 3 + ---help--- + ADC0 data resolution. 0: 12 bit, 1: 10 bit, + 2: 8 bit, 3: 6 bit + +config GD32F4_ADC1_RESOLUTION + int "ADC1 resolution" + depends on GD32F4_ADC1 + default 0 + range 0 3 + ---help--- + ADC1 data resolution. 0: 12 bit, 1: 10 bit, + 2: 8 bit, 3: 6 bit + +config GD32F4_ADC2_RESOLUTION + int "ADC2 resolution" + depends on GD32F4_ADC2 + default 0 + range 0 3 + ---help--- + ADC2 data resolution. 0: 12 bit, 1: 10 bit, + 2: 8 bit, 3: 6 bit + +config GD32F4_ADC_MAX_SAMPLES + int "The maximum number of channels that can be sampled" + default 16 + ---help--- + The ADC supports 19 multiplexed channels and two groups: regular and inserted channel group. + The maximum number of samples for regular group can be 16, for inserted channel group + can be 4. + User can change the default value according to the board initialize. The user should + correctly configure this value. + +config GD32F4_ADC_NOINT + bool "Do not use ADC interrupts" + default n + ---help--- + Do not use ADC interrupts handlers. + +config GD32F4_ADC_LL_OPS + bool "ADC low level operations" + default n + ---help--- + Enable low level ADC operations. + +config GD32F4_ADC_CHANGE_SAMPLETIME + bool "ADC sample time configuration" + default n + depends on GD32F4_ADC_LL_OPS + ---help--- + Enable ADC sample time configuration (SMPTx registers). + +config GD32F4_ADC0_DMA + bool "ADC0 DMA" + depends on GD32F4_ADC0 && GD32F4_HAVE_ADC0_DMA + default n + ---help--- + When the ADC is configured to support DMA transfer, + the DMA should be selected. When multiple channels are read + or if very high trigger frequencies are used, the ADC DMA transfer + is necessary. + +config GD32F4_ADC0_SCAN + bool "ADC0 scan mode" + depends on GD32F4_ADC0 + default y if GD32F4_ADC0_DMA + default n + +config GD32F4_ADC0_DMA_CFG + int "ADC0 DMA configuration" + depends on GD32F4_ADC0_DMA + range 0 1 + default 0 + ---help--- + 0 - ADC0 DMA in Circular Mode disable, 1 - ADC0 DMA in Circular Mode enable + +config GD32F4_ADC0_ANIOC_SWTRIG + int "ADC0 software trigger (ANIOC_TRIGGER) configuration" + depends on GD32F4_ADC0 + range 1 3 + default 3 + ---help--- + 1 - ANIOC_TRIGGER only trigger regular conversion + 2 - ANIOC_TRIGGER only trigger injected conversion + 3 - ANIOC_TRIGGER trigger both regular and injected conversions + +config GD32F4_ADC1_DMA + bool "ADC1 DMA" + depends on GD32F4_ADC1 && GD32F4_HAVE_ADC1_DMA + default n + ---help--- + When the ADC is configured to support DMA transfer, + the DMA should be selected. When multiple channels are read + or if very high trigger frequencies are used, the ADC DMA transfer + is necessary. + +config GD32F4_ADC1_SCAN + bool "ADC1 scan mode" + depends on GD32F4_ADC1 + default y if GD32F4_ADC1_DMA + default n + +config GD32F4_ADC1_DMA_CFG + int "ADC1 DMA configuration" + depends on GD32F4_ADC1_DMA + range 0 1 + default 0 + ---help--- + 0 - ADC0 DMA in Circular Mode disable, 1 - ADC0 DMA in Circular Mode enable + +config GD32F4_ADC1_ANIOC_SWTRIG + int "ADC1 software trigger (ANIOC_TRIGGER) configuration" + depends on GD32F4_ADC1 + range 1 3 + default 3 + ---help--- + 1 - ANIOC_TRIGGER only trigger regular conversion + 2 - ANIOC_TRIGGER only trigger injected conversion + 3 - ANIOC_TRIGGER trigger both regular and injected conversions + +config GD32F4_ADC2_DMA + bool "ADC2 DMA" + depends on GD32F4_ADC2 && GD32F4_HAVE_ADC2_DMA + default n + ---help--- + When the ADC is configured to support DMA transfer, + the DMA should be selected. When multiple channels are read + or if very high trigger frequencies are used, the ADC DMA transfer + is necessary. + +config GD32F4_ADC2_SCAN + bool "ADC2 scan mode" + depends on GD32F4_ADC2 + default y if GD32F4_ADC2_DMA + default n + +config GD32F4_ADC2_DMA_CFG + int "ADC2 DMA configuration" + depends on GD32F4_ADC2_DMA + range 0 1 + default 0 + ---help--- + 0 - ADC0 DMA in Circular Mode disable, 1 - ADC0 DMA in Circular Mode enable + +config GD32F4_ADC2_ANIOC_SWTRIG + int "ADC2 software trigger (ANIOC_TRIGGER) configuration" + depends on GD32F4_ADC2 + range 1 3 + default 3 + ---help--- + 1 - ANIOC_TRIGGER only trigger regular conversion + 2 - ANIOC_TRIGGER only trigger injected conversion + 3 - ANIOC_TRIGGER trigger both regular and injected conversions + +config GD32F4_ADC0_INJECTED_CHANNEL + int "ADC0 injected channels" + depends on GD32F4_ADC0 + range 0 4 + default 0 + ---help--- + Support for ADC0 injected channels. + +config GD32F4_ADC1_INJECTED_CHANNEL + int "ADC2 injected channels" + depends on GD32F4_ADC1 + range 0 4 + default 0 + ---help--- + Support for ADC1 injected channels. + +config GD32F4_ADC2_INJECTED_CHANNEL + int "ADC2 injected channels" + depends on GD32F4_ADC2 + range 0 4 + default 0 + ---help--- + Support for ADC2 injected channels. + +config GD32F4_ADC0_EXTTRIG_REGULAR + bool "ADC0 external trigger for regular group" + depends on GD32F4_ADC0 && !GD32F4_HAVE_ADC0_TIMER + default n + ---help--- + Enable EXTTRIG_REGULAR for ADC0. + +config GD32F4_ADC1_EXTTRIG_REGULAR + bool "ADC1 external trigger for regular group" + depends on GD32F4_ADC1 && !GD32F4_HAVE_ADC1_TIMER + default n + ---help--- + Enable EXTTRIG_REGULAR for ADC1. + +config GD32F4_ADC2_EXTTRIG_REGULAR + bool "ADC2 external trigger for regular group" + depends on GD32F4_ADC2 && !GD32F4_HAVE_ADC2_TIMER + default n + ---help--- + Enable EXTTRIG_REGULAR for ADC2. + +config GD32F4_ADC0_EXTTRIG_INSERTED + bool "ADC0 external trigger for injected group" + depends on GD32F4_ADC0 + default n + ---help--- + Enable EXTTRIG_INSERTED for ADC0. + +config GD32F4_ADC1_EXTTRIG_INSERTED + bool "ADC1 external trigger for injected group" + depends on GD32F4_ADC1 + default n + ---help--- + Enable EXTTRIG_INSERTED for ADC1. + +config GD32F4_ADC2_EXTTRIG_INSERTED + bool "ADC2 external trigger for injected group" + depends on GD32F4_ADC2 + default n + ---help--- + Enable EXTTRIG_INSERTED for ADC2. + +endmenu # ADC Configuration + + +menu "DAC Configuration" + depends on GD32F4_DAC + +config GD32F4_DAC0_OUTPUT_BUFFER + bool "DAC0 output buffer enable" + depends on GD32F4_DAC0 + default y + ---help--- + DAC0 output buffer configuration + +config GD32F4_DAC0_DATA + int "DAC0 data configuration" + depends on GD32F4_DAC0 + range 0 2 + default 0 + ---help--- + 0 - data right 12 bit alignment, + 1 - data left 12 bit alignment, + 2 - data right 8 bit alignment + +config GD32F4_DAC0_TRIG + bool "DAC0 trigger enable" + depends on GD32F4_DAC0 + default y + ---help--- + DAC0 trigger configuration + +config GD32F4_DAC0_TRIG_MODE + int "DAC0 trigger source select" + depends on GD32F4_DAC0 && GD32F4_DAC0_TRIG + default 0 + range 0 7 + ---help--- + 0 - TIMER5 TRGO, 1 - TIMER7 TRGO, 2 - TIMER6 TRGO, 3 - TIMER4 TRGO, + 4 - TIMER1 TRGO, 5 - TIMER2 TRGO, 6 - EXTI interrupt line9 event, 7 - software trigger + + +config GD32F4_DAC0_TIMER_FREQUENCY + int "DAC0 timer frequency" + depends on GD32F4_DAC0 && GD32F4_DAC0_TRIG + default 1000 + ---help--- + DAC0 output frequency, only in timer triggrer mode is useful. + Default: 1000Hz + +config GD32F4_DAC0_DMA + bool "DAC0 DMA" + depends on GD32F4_DAC0 && GD32F4_DAC0_TRIG + default n + ---help--- + When the external trigger is enabled, the DMA request can be enabled by setting the + DDMAENx bits of the DAC_CTL register. A DMA request will be generated by DAC when an + external hardware trigger (not a software trigger) occurs. The user should note that + when use DMA. + The timer and output frequency must also be provided to support the DMA transfer, + when the timer is selected to trigger DAC DMA. + +config GD32F4_DAC0_DMA_BUFFER_SIZE + int "DAC0 DMA buffer size" + depends on GD32F4_DAC0_DMA + default 64 + +config GD32F4_DAC1_OUTPUT_BUFFER + bool "DAC1 output buffer enable" + depends on GD32F4_DAC1 + default y + ---help--- + DAC0 output buffer configuration + +config GD32F4_DAC1_DATA + int "DAC1 data configuration" + depends on GD32F4_DAC1 + range 0 2 + default 0 + ---help--- + 0 - data right 12 bit alignment, + 1 - data left 12 bit alignment, + 2 - data right 8 bit alignment + +config GD32F4_DAC1_TRIG + bool "DAC1 trigger enable" + depends on GD32F4_DAC1 + default y + ---help--- + DAC1 trigger configuration + +config GD32F4_DAC1_TRIG_MODE + int "DAC1 trigger source select" + depends on GD32F4_DAC1 && GD32F4_DAC1_TRIG + default 0 + range 0 7 + ---help--- + 0 - TIMER5 TRGO, 1 - TIMER7 TRGO, 2 - TIMER6 TRGO, 3 - TIMER4 TRGO, + 4 - TIMER1 TRGO, 5 - TIMER2 TRGO, 6 - EXTI interrupt line9 event, 7 - software trigger + + +config GD32F4_DAC1_TIMER_FREQUENCY + int "DAC1 timer frequency" + depends on GD32F4_DAC1 && GD32F4_DAC1_TRIG + default 1000 + ---help--- + DAC1 output frequency, only in timer triggrer mode is useful. + Default: 1000Hz + +config GD32F4_DAC1_DMA + bool "DAC1 DMA" + depends on GD32F4_DAC1 && GD32F4_DAC1_TRIG + default n + ---help--- + When the external trigger is enabled, the DMA request can be enabled by setting the + DDMAENx bits of the DAC_CTL register. A DMA request will be generated by DAC when an + external hardware trigger (not a software trigger) occurs. The user should note that + when use DMA. + The timer and output frequency must also be provided to support the DMA transfer, + when the timer is selected to trigger DAC DMA. + +config GD32F4_DAC1_DMA_BUFFER_SIZE + int "DAC1 DMA buffer size" + depends on GD32F4_DAC1_DMA + default 64 + +endmenu # DAC Configuration + + +config GD32F4_USART_RXDMA + bool + default n + +config GD32F4_SERIALDRIVER + bool + default n + +config GD32F4_1WIREDRIVER + bool + default n + +menu "USART Configuration" + depends on GD32F4_USART + +comment "USART Device Configuration" + +choice + prompt "USART0 Driver Configuration" + default GD32F4_USART0_SERIALDRIVER + depends on GD32F4_USART0 + +config GD32F4_USART0_SERIALDRIVER + bool "Standard serial driver" + select USART0_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + select GD32F4_SERIALDRIVER + +config GD32F4_USART0_1WIREDRIVER + bool "1-Wire driver" + select GD32F4_1WIREDRIVER + +endchoice # USART0 Driver Configuration + +if GD32F4_USART0_SERIALDRIVER + +config USART0_RS485 + bool "Enable RS-485 on USART0" + default n + ---help--- + USART0 RS-485 function configuration. If the user configure the RS-485 on + USART, the user's should to provide GPIO_USART0_RS485_DIR pin definition + in board initialization. + And it cannot be used with GD32F4_USART0_RXDMA currently. + +config USART0_RS485_DIR_POLARITY + int "Configure USART0 RS-485 DIR pin polarity" + default 1 + range 0 1 + depends on USART0_RS485 + ---help--- + Polarity of GPIO_USART0_RS485_DIR pin for RS-485 on USART0. + The state on DIR pin: 0 - receive , 1 - transmit. + +config GD32F4_USART0_RXDMA + bool "USART0 Rx DMA" + default n + depends on GD32F4_DMA1 + select GD32F4_USART_RXDMA + select USART0_RXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the receiving data buffer. + +config GD32F4_USART0_TXDMA + bool "USART0 Tx DMA" + default n + depends on GD32F4_DMA1 + select GD32F4_USART_TXDMA + select USART0_TXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the transmitting data buffer. + +endif # GD32F4_USART0_SERIALDRIVER + +choice + prompt "USART1 Driver Configuration" + default GD32F4_USART1_SERIALDRIVER + depends on GD32F4_USART1 + +config GD32F4_USART1_SERIALDRIVER + bool "Standard serial driver" + select USART1_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + select GD32F4_SERIALDRIVER + +config GD32F4_USART1_1WIREDRIVER + bool "1-Wire driver" + select GD32F4_1WIREDRIVER + +endchoice # USART1 Driver Configuration + +if GD32F4_USART1_SERIALDRIVER + +config USART1_RS485 + bool "Enable RS-485 on USART1" + default n + ---help--- + USART1 RS-485 function configuration. If the user configure the RS-485 on + USART, the user's should to provide GPIO_USART0_RS485_DIR pin definition + in board initialization. + And it cannot be used with GD32F4_USART1_RXDMA currently. + +config USART1_RS485_DIR_POLARITY + int "Configure USART1 RS-485 DIR pin polarity" + default 1 + range 0 1 + depends on USART1_RS485 + ---help--- + Polarity of GPIO_USART1_RS485_DIR pin for RS-485 on USART1. + The state on DIR pin: 0 - receive , 1 - transmit. + +config GD32F4_USART1_RXDMA + bool "USART1 Rx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_RXDMA + select USART1_RXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the receiving data buffer. + +config GD32F4_USART1_TXDMA + bool "USART1 Tx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_TXDMA + select USART1_TXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the transmitting data buffer. + +endif # GD32F4_USART1_SERIALDRIVER + +choice + prompt "USART2 Driver Configuration" + default GD32F4_USART2_SERIALDRIVER + depends on GD32F4_USART2 + +config GD32F4_USART2_SERIALDRIVER + bool "Standard serial driver" + select USART2_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + select GD32F4_SERIALDRIVER + +config GD32F4_USART2_1WIREDRIVER + bool "1-Wire driver" + select GD32F4_1WIREDRIVER + +endchoice # USART2 Driver Configuration + +if GD32F4_USART2_SERIALDRIVER + +config USART2_RS485 + bool "Enable RS-485 on USART2" + default n + ---help--- + USART2 RS-485 function configuration. If the user configure the RS-485 on + USART, the user's should to provide GPIO_USART2_RS485_DIR pin definition + in board initialization. + And it cannot be used with GD32F4_USART2_RXDMA currently. + +config USART2_RS485_DIR_POLARITY + int "Configure USART2 RS-485 DIR pin polarity" + default 1 + range 0 1 + depends on USART1_RS485 + ---help--- + Polarity of GPIO_USART2_RS485_DIR pin for RS-485 on USART2. + The state on DIR pin: 0 - receive , 1 - transmit. + +config GD32F4_USART2_RXDMA + bool "USART2 Rx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_RXDMA + select USART2_RXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the receiving data buffer. + +config GD32F4_USART2_TXDMA + bool "USART2 Tx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_TXDMA + select USART2_TXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the transmitting data buffer. + +endif # GD32F4_USART2_SERIALDRIVER + +choice + prompt "UART3 Driver Configuration" + default GD32F4_UART3_SERIALDRIVER + depends on GD32F4_UART3 + +config GD32F4_UART3_SERIALDRIVER + bool "Standard serial driver" + select UART3_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + select GD32F4_SERIALDRIVER + +config GD32F4_UART3_1WIREDRIVER + bool "1-Wire driver" + select GD32F4_1WIREDRIVER + +endchoice # UART3 Driver Configuration + +if GD32F4_UART3_SERIALDRIVER + +config UART3_RS485 + bool "Enable RS-485 on UART3" + default n + ---help--- + UART3 RS-485 function configuration. If the user configure the RS-485 on + UART, the user's should to provide UART3_RS485_DIR_POLARITY pin definition + in board initialization. + And it cannot be used with GD32F4_UART3_RXDMA currently. + +config UART3_RS485_DIR_POLARITY + int "Configure UART3 RS-485 DIR pin polarity" + default 1 + range 0 1 + depends on UART3_RS485 + ---help--- + Polarity of GPIO_UART3_RS485_DIR pin for RS-485 on UART3. + The state on DIR pin: 0 - receive , 1 - transmit. + +config GD32F4_UART3_RXDMA + bool "UART3 Rx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_RXDMA + select UART3_RXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the receiving data buffer. + +config GD32F4_UART3_TXDMA + bool "UART3 Tx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_TXDMA + select UART3_TXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the transmit data buffer. + +endif # GD32F4_UART3_SERIALDRIVER + +choice + prompt "UART4 Driver Configuration" + default GD32F4_UART4_SERIALDRIVER + depends on GD32F4_UART4 + +config GD32F4_UART4_SERIALDRIVER + bool "Standard serial driver" + select UART4_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + select GD32F4_SERIALDRIVER + +config GD32F4_UART4_1WIREDRIVER + bool "1-Wire driver" + select GD32F4_1WIREDRIVER + +endchoice # UART4 Driver Configuration + +if GD32F4_UART4_SERIALDRIVER + +config UART4_RS485 + bool "Enable RS-485 on UART4" + default n + ---help--- + UART4 RS-485 function configuration. If the user configure the RS-485 on + UART, the user's should to provide UART4_RS485_DIR_POLARITY pin definition + in board initialization. + And it cannot be used with GD32F4_UART4_RXDMA currently. + +config UART4_RS485_DIR_POLARITY + int "Configure UART4 RS-485 DIR pin polarity" + default 1 + range 0 1 + depends on UART4_RS485 + ---help--- + Polarity of GPIO_UART4_RS485_DIR pin for RS-485 on UART4. + The state on DIR pin: 0 - receive , 1 - transmit. + +config GD32F4_UART4_RXDMA + bool "UART4 Rx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_RXDMA + select UART4_RXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the receiving data buffer. + +config GD32F4_UART4_TXDMA + bool "UART4 Tx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_TXDMA + select UART4_TXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the transmit data buffer. + +endif # GD32F4_UART4_SERIALDRIVER + +choice + prompt "USART5 Driver Configuration" + default GD32F4_USART5_SERIALDRIVER + depends on GD32F4_USART5 + +config GD32F4_USART5_SERIALDRIVER + bool "Standard serial driver" + select USART5_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + select GD32F4_SERIALDRIVER + +config GD32F4_USART5_1WIREDRIVER + bool "1-Wire driver" + select GD32F4_1WIREDRIVER + +endchoice # USART5 Driver Configuration + +if GD32F4_USART5_SERIALDRIVER + +config USART5_RS485 + bool "Enable RS-485 on USART5" + default n + ---help--- + USART5 RS-485 function configuration. If the user configure the RS-485 on + USART, the user's should to provide GPIO_USART5_RS485_DIR pin definition + in board initialization. + And it cannot be used with GD32F4_USART5_RXDMA currently. + +config USART5_RS485_DIR_POLARITY + int "Configure USART5 RS-485 DIR pin polarity" + default 1 + range 0 1 + depends on USART1_RS485 + ---help--- + Polarity of GPIO_USART5_RS485_DIR pin for RS-485 on USART5. + The state on DIR pin: 0 - receive , 1 - transmit. + +config GD32F4_USART5_RXDMA + bool "USART5 Rx DMA" + default n + depends on GD32F4_DMA1 + select GD32F4_USART_RXDMA + select USART5_RXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the receiving data buffer. + +config GD32F4_USART5_TXDMA + bool "USART5 Tx DMA" + default n + depends on GD32F4_DMA1 + select GD32F4_USART_TXDMA + select USART5_TXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the transmitting data buffer. + +endif # GD32F4_USART5_SERIALDRIVER + + +choice + prompt "UART6 Driver Configuration" + default GD32F4_UART6_SERIALDRIVER + depends on GD32F4_UART6 + +config GD32F4_UART6_SERIALDRIVER + bool "Standard serial driver" + select UART6_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + select GD32F4_SERIALDRIVER + +config GD32F4_UART6_1WIREDRIVER + bool "1-Wire driver" + select GD32F4_1WIREDRIVER + +endchoice # UART6 Driver Configuration + +if GD32F4_UART6_SERIALDRIVER + +config UART6_RS485 + bool "Enable RS-485 on UART6" + default n + ---help--- + UART6 RS-485 function configuration. If the user configure the RS-485 on + UART, the user's should to provide UART6_RS485_DIR_POLARITY pin definition + in board initialization. + And it cannot be used with GD32F4_UART6_RXDMA currently. + +config UART6_RS485_DIR_POLARITY + int "Configure UART6 RS-485 DIR pin polarity" + default 1 + range 0 1 + depends on UART6_RS485 + ---help--- + Polarity of GPIO_UART6_RS485_DIR pin for RS-485 on UART6. + The state on DIR pin: 0 - receive , 1 - transmit. + +config GD32F4_UART6_RXDMA + bool "UART6 Rx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_RXDMA + select UART6_RXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the receiving data buffer. + +config GD32F4_UART6_TXDMA + bool "UART6 Tx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_TXDMA + select UART6_TXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the transmit data buffer. + +endif # GD32F4_UART6_SERIALDRIVER + + +choice + prompt "UART7 Driver Configuration" + default GD32F4_UART7_SERIALDRIVER + depends on GD32F4_UART7 + +config GD32F4_UART7_SERIALDRIVER + bool "Standard serial driver" + select UART7_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + select GD32F4_SERIALDRIVER + +config GD32F4_UART7_1WIREDRIVER + bool "1-Wire driver" + select GD32F4_1WIREDRIVER + +endchoice # UART7 Driver Configuration + +if GD32F4_UART7_SERIALDRIVER + +config UART7_RS485 + bool "Enable RS-485 on UART7" + default n + ---help--- + UART7 RS-485 function configuration. If the user configure the RS-485 on + UART, the user's should to provide UART7_RS485_DIR_POLARITY pin definition + in board initialization. + And it cannot be used with GD32F4_UART7_RXDMA currently. + +config UART7_RS485_DIR_POLARITY + int "Configure UART7 RS-485 DIR pin polarity" + default 1 + range 0 1 + depends on UART7_RS485 + ---help--- + Polarity of GPIO_UART7_RS485_DIR pin for RS-485 on UART7. + The state on DIR pin: 0 - receive , 1 - transmit. + +config GD32F4_UART7_RXDMA + bool "UART7 Rx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_RXDMA + select UART7_RXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the receiving data buffer. + +config GD32F4_UART7_TXDMA + bool "UART7 Tx DMA" + default n + depends on GD32F4_DMA0 + select GD32F4_USART_TXDMA + select UART7_TXDMA + ---help--- + To reduce the burden of the processor in fast data transmit, DMA can be used to + access the transmit data buffer. + +endif # GD32F4_UART7_SERIALDRIVER + + +menu "Serial Driver Configuration" + depends on GD32F4_SERIALDRIVER + +config GD32F4_SERIAL_RXDMA_BUFFER_SIZE + int "Rx DMA buffer size" + default 32 + range 32 4096 + depends on GD32F4_USART_RXDMA + ---help--- + The RX DMA buffer size when using RX DMA receive data. + Recommended size value given here is multiple of 4 bytes. + +config GD32F4_SERIAL_DISABLE_REORDERING + bool "Disable reordering of ttySx devices." + default n + ---help--- + NuttX per default reorders the serial ports (/dev/ttySx) so that the + console is always on /dev/ttyS0. If more than one UART is in use this + can, however, have the side-effect that all port mappings + (hardware USART0 -> /dev/ttyS0) change if the console is moved to another + USART. This is in particular relevant if a project uses the USB console + in some boards and a serial console in other boards, but does not + want the side effect of having all serial port names change when just + the console is moved from serial to USB. + +config GD32F4_FLOWCONTROL_BROKEN + bool "Use Software UART RTS flow control" + default n + ---help--- + Enable USART RTS flow control using Software. When implement USART RTS by + hardware, the nRTS pin should be configured. + +config GD32F4_USART_BREAKS + bool "Add TIOxSBRK to support sending Breaks" + default n + ---help--- + Add TIOCxBRK routines to send a line break per the GD32F4 manual, the + break will be a pulse based on the value M. This is not a BSD compatible + break. + +config GD32F4_SERIALBRK_BSDCOMPAT + bool "Use GPIO To send Break" + depends on GD32F4_USART_BREAKS + default n + ---help--- + Enable using GPIO on the TX pin to send a BSD compatible break: + TIOCSBRK will start the break and TIOCCBRK will end the break. + The current GD32F4 USARTS have no way to leave the break (TX=LOW) + on because the software starts the break and then the hadware automatically + clears the break. This makes it is difficult to sent a long break. + +config GD32F4_USART_SINGLEWIRE + bool "Single Wire Support" + default n + depends on GD32F4_USART + ---help--- + Enable USART half-duplex mode. The option enables support for the + TIOCSSINGLEWIRE ioctl in the GD32F4 serial driver. + +config GD32F4_USART_INVERT + bool "Signal inversion support for RX/TX pin" + default n + depends on GD32F4_USART0 || GD32F4_USART1 || GD32F4_USART1 || GD32F4_USART5 + ---help--- + Enable signal inversion support for USART RX/TX pin . The option enables + support for the TIOCSINVERT ioctl in the gd32f4 serial driver. + RX/TX inversion only support for USART0, 1, 2, 5 + +endmenu # Serial Driver Configuration + + +if PM + +config GD32F4_PM_SERIAL_ACTIVITY + int "PM serial activity" + default 10 + ---help--- + PM activity reported to power management logic on every serial + interrupt. + +endif + +endmenu # USART Configuration + + +menu "I2C Configuration" + depends on GD32F4_I2C + +endmenu + + +config GD32F4_HAVE_RTC_COUNTER + bool + default n + +config GD32F4_HAVE_RTC_SUBSECONDS + bool + select ARCH_HAVE_RTC_SUBSECONDS + default n + +menu "RTC Configuration" + depends on GD32F4_RTC + +config GD32F4_RTC_MAGIC_REG + int "BKP register" + default 0 + range 0 19 + depends on !GD32F4_HAVE_RTC_COUNTER + ---help--- + The BKP register used to store/check the Magic value to determine if + RTC is already setup + +config GD32F4_RTC_MAGIC + hex "RTC Magic 1" + default 0xfacefeed + depends on !GD32F4_HAVE_RTC_COUNTER + ---help--- + Value used as Magic to determine if the RTC is already setup + +config GD32F4_RTC_MAGIC_TIME_SET + hex "RTC Magic 2" + default 0xf00dface + depends on !GD32F4_HAVE_RTC_COUNTER + ---help--- + Value used as Magic to determine if the RTC has been setup and has + time set + +choice + prompt "RTC clock source" + default GD32F4_RTC_LXTALCLOCK + +config GD32F4_RTC_LXTALCLOCK + bool "LXTAL clock" + ---help--- + The RTC clock source is the LXTAL clock + +config GD32F4_RTC_IRC16MCLOCK + bool "IRC16M clock" + ---help--- + The RTC clock source is the IRC16M clock + +config GD32F4_RTC_HXTALCLOCK + bool "HXTAL clock" + ---help--- + The RTC clock source is the HXTAL clock, divided down to 1MHz. + +endchoice # RTC clock source +endmenu # RTC configuration + + +menu "SDIO Configuration" + depends on GD32F4_SDIO + +endmenu + +menu "SPI Configuration" + depends on GD32F4_SPI + +config GD32F4_SPI_INTERRUPT + bool "Support SPI interrupt" + default n + ---help--- + Select to support SPI interrupt. Non-interrupt-driven,poll-waiting is recommended + if the interrupt rate would be to high in the interrupt driven case. + +config GD32F4_SPI_DMA + bool "SPI DMA" + default n + depends on GD32F4_DMA && !GD32F4_SPI_INTERRUPT + ---help--- + Use DMA to improve SPI transfer performance. + Should not used with GD32F4_SPI_INTERRUPT at the same time. + +config GD32F4_SPI_DMATHRESHOLD + int "SPI DMA threshold" + default 4 + depends on GD32F4_SPI_DMA + ---help--- + When SPI DMA is enabled, if transfers size is less than GD32F4_SPI_DMATHRESHOLD, + the data transfer will still be performed by polling logic. + +config GD32F4_SPI0_DMA + bool "SPI0 DMA" + default n + depends on GD32F4_SPI0 && GD32F4_SPI_DMA + # depends on GD32F4_SPI0 && GD32F4_SPI_DMA && GD32F4_DMA1 + ---help--- + Use DMA to improve SPI0 transfer performance. + Should enable GD32F4 DMA1. + +config GD32F4_SPI0_DMA_BUFFER + int "SPI0 DMA buffer size" + default 0 + depends on GD32F4_SPI0_DMA + ---help--- + DMA buffer for SPI0 RX and TX DMA, recommended buffer size is a multiple of 4. + +config GD32F4_SPI1_DMA + bool "SPI1 DMA" + default n + depends on GD32F4_SPI1 && GD32F4_SPI_DMA + # depends on GD32F4_SPI1 && GD32F4_SPI_DMA && GD32F4_DMA0 + ---help--- + Use DMA to improve SPI1 transfer performance. + Should enable GD32F4 DMA0. + +config GD32F4_SPI1_DMA_BUFFER + int "SPI1 DMA buffer size" + default 0 + depends on GD32F4_SPI1_DMA + ---help--- + DMA buffer for SPI1 RX and TX DMA, recommended buffer size is a multiple of 4. + +config GD32F4_SPI2_DMA + bool "SPI2 DMA" + default n + depends on GD32F4_SPI2 && GD32F4_SPI_DMA + # depends on GD32F4_SPI2 && GD32F4_SPI_DMA && GD32F4_DMA0 + ---help--- + Use DMA to improve SPI1 transfer performance. + Should enable GD32F4 DMA0. + +config GD32F4_SPI2_DMA_BUFFER + int "SPI2 DMA buffer size" + default 0 + depends on GD32F4_SPI2_DMA + ---help--- + DMA buffer for SPI2 RX and TX DMA, recommended buffer size is a multiple of 4. + +config GD32F3_SPI3_DMA + bool "SPI3 DMA" + default n + depends on GD32F4_SPI3 && GD32F4_SPI_DMA + # depends on GD32F4_SPI3 && GD32F4_SPI_DMA && GD32F4_DMA1 + ---help--- + Use DMA to improve SPI3 transfer performance. + Should enable GD32F4 DMA1. + +config GD32F4_SPI3_DMA_BUFFER + int "SPI3 DMA buffer size" + default 0 + depends on GD32F4_SPI3_DMA + ---help--- + DMA buffer for SPI3 RX and TX DMA, recommended buffer size is a multiple of 4. + +config GD32F4_SPI4_DMA + bool "SPI4 DMA" + default n + depends on GD32F4_SPI4 && GD32F4_SPI_DMA + # depends on GD32F4_SPI4 && GD32F4_SPI_DMA && GD32F4_DMA1 + ---help--- + Use DMA to improve SPI4 transfer performance. + Should enable GD32F4 DMA1. + +config GD32F4_SPI4_DMA_BUFFER + int "SPI4 DMA buffer size" + default 0 + depends on GD32F4_SPI4_DMA + ---help--- + DMA buffer for SPI4 RX and TX DMA, recommended buffer size is a multiple of 4. + +config GD32F4_SPI5_DMA + bool "SPI5 DMA" + default n + depends on GD32F4_SPI5 && GD32F4_SPI_DMA + # depends on GD32F4_SPI5 && GD32F4_SPI_DMA && GD32F4_DMA1 + ---help--- + Use DMA to improve SPI5 transfer performance. + Should enable GD32F4 DMA1. + +config GD32F4_SPI5_DMA_BUFFER + int "SPI5 DMA buffer size" + default 0 + depends on GD32F4_SPI5_DMA + ---help--- + DMA buffer for SPI5 RX and TX DMA, recommended buffer size is a multiple of 4. + +endmenu # SPI Configuration + +menu "I2S Configuration" + depends on GD32F4_I2S1 || GD32F4_I2S2 + +endmenu # I2S Configuration + + +config GD32F4_BKPDSRAM + bool "Backup domain SRAM File Support" + default n + depends on GD32F4_BKPSRAM + +config GD32F4_BKPDSRAM_FILES + int "Max Files to support in Backup domain SRAM" + default 4 + depends on GD32F4_BKPSRAM + +config GD32F4_SAVE_CRASHDUMP + bool "Enable Saving Panic to Backup domain SRAM" + default n + depends on GD32F4_BKPSRAM + + +menu "Ethernet MAC configuration" + depends on GD32F4_ENETMAC + +config GD32F4_PHY_ADDR + int "PHY address" + default 1 + ---help--- + The 5-bit address of the PHY on the board. Default: 1 + +config GD32F4_PHY_INIT + bool "Board-specific PHY Initialization" + default n + ---help--- + Before the PHY can be used, Some boards require specialized initialization of it. + This may include such things as configuring GPIOs, clock, resetting the PHY, etc. + If GD32F4_PHY_INIT is defined in the configuration then the board specific logic must + provide the function of phyinitialize(); Before first uses the PHY, the GD32F4 Ethernet + driver will call this function one time . + +config GD32F4_MII + bool "Use the media-independent interface (MII) interface" + default n + ---help--- + Select Ethernet MII interface. The application can only select one of + the MII or RMII mode. + +choice + prompt "MII clock configuration" + default GD32F4_MII_CKOUT0 + depends on GD32F4_MII + +config GD32F4_MII_CKOUT0 + bool "Use CKOUT0 as MII clock" + ---help--- + Use CKOUT0 to clock the MII interface. + +config GD32F4_MII_CKOUT1 + bool "Use CKOUT1 as MII clock" + ---help--- + Use CKOUT1 to clock the MII interface. + +config GD32F4_MII_EXTCLK + bool "External MII clock" + ---help--- + MII clock is provided by external clock. And not use CKOUT for + MII clock. + +endchoice + +config GD32F4_AUTO_NEGOTIATION + bool "Use autonegotiation" + default y + ---help--- + Use PHY's autonegotiation mode, and according to the negotiation result + to determine the speed and mode. + +config GD32F4_ENET_MODE_FULLDUPLEX + bool "Full duplex mode" + default y + depends on !GD32F4_AUTO_NEGOTIATION + ---help--- + If GD32F4_AUTO_NEGOTIATION is not defined, then the ENET full duplex mode + should be configured. + +config GD32F4_ENET_SPEEDMODE_100M + bool "100 Mbps" + default y + depends on !GD32F4_AUTO_NEGOTIATION + ---help--- + If GD32F4_AUTO_NEGOTIATION is not defined, then the ENET 100 Mbps mode + should be configured. + +config GD32F4_PHY_SR + int "PHY Status Register Address (decimal)" + depends on GD32F4_AUTO_NEGOTIATION + ---help--- + This must be provided if GD32F4_AUTO_NEGOTIATION is defined. Because of the + PHY status register address may different from PHY to PHY, the user should set + the address of the PHY status register according to the PHY on board. + +config GD32F4_PHY_SR_ALTCONFIG + bool "PHY Status Alternate Bit Layout" + default n + depends on GD32F4_AUTO_NEGOTIATION + ---help--- + Different PHYs present speed and mode information in different ways. Some + will present separate information for speed and mode (this is the default). + Those PHYs, for example, may provide a 10/100 Mbps indication and a separate + full/half duplex indication. This options selects an alternative representation + where speed and mode information are combined. This might mean, for example, + separate bits for 10HD, 100HD, 10FD and 100FD. + +config GD32F4_PHY_SR_SPEED + hex "PHY Speed Mask" + depends on GD32F4_AUTO_NEGOTIATION && !GD32F4_PHY_SR_ALTCONFIG + ---help--- + This must be provided if GD32F4_AUTO_NEGOTIATION is defined. This provides bit mask + for isolating the 10 or 100MBps speed indication. + +config GD32F4_PHY_SR_100M + hex "PHY 100Mbps Speed Value" + depends on GD32F4_AUTO_NEGOTIATION && !GD32F4_PHY_SR_ALTCONFIG + ---help--- + This must be provided if GD32F4_AUTO_NEGOTIATION is defined. This provides the value + of the speed bit(s) indicating 100MBps speed. + +config GD32F4_PHY_SR_MODE + hex "PHY Mode Mask" + depends on GD32F4_AUTO_NEGOTIATION && !GD32F4_PHY_SR_ALTCONFIG + ---help--- + This must be provided if GD32F4_AUTO_NEGOTIATION is defined. This provide bit mask + for isolating the full or half duplex mode bits. + +config GD32F4_PHY_SR_FULLDUPLEX + hex "PHY Full Duplex Mode Value" + depends on GD32F4_AUTO_NEGOTIATION && !GD32F4_PHY_SR_ALTCONFIG + ---help--- + This must be provided if GD32F4_AUTO_NEGOTIATION is defined. This provides the + value of the mode bits indicating full duplex mode. + +config GD32F4_PHY_SR_ALTMODE + hex "PHY Mode Mask" + depends on GD32F4_AUTO_NEGOTIATION && GD32F4_PHY_SR_ALTCONFIG + ---help--- + This must be provided if GD32F4_AUTO_NEGOTIATION is defined. This provide bit mask + for isolating the speed and full/half duplex mode bits. + +config GD32F4_PHY_SR_10HD + hex "10MBase-T Half Duplex Value" + depends on GD32F4_AUTO_NEGOTIATION && GD32F4_PHY_SR_ALTCONFIG + ---help--- + This must be provided if GD32F4_AUTO_NEGOTIATION is defined. This is the value + under the bit mask that represents the 10Mbps, half duplex setting. + +config GD32F4_PHY_SR_100HD + hex "100Base-T Half Duplex Value" + depends on GD32F4_AUTO_NEGOTIATION && GD32F4_PHY_SR_ALTCONFIG + ---help--- + This must be provided if GD32F4_AUTO_NEGOTIATION is defined. This is the value + under the bit mask that represents the 100Mbps, half duplex setting. + +config GD32F4_PHY_SR_10FD + hex "10Base-T Full Duplex Value" + depends on GD32F4_AUTO_NEGOTIATION && GD32F4_PHY_SR_ALTCONFIG + ---help--- + This must be provided if GD32F4_AUTO_NEGOTIATION is defined. This is the value + under the bit mask that represents the 10Mbps, full duplex setting. + +config GD32F4_PHY_SR_100FD + hex "100Base-T Full Duplex Value" + depends on GD32F4_AUTO_NEGOTIATION && GD32F4_PHY_SR_ALTCONFIG + ---help--- + This must be provided if GD32F4_AUTO_NEGOTIATION is defined. This is the value + under the bit mask that represents the 100Mbps, full duplex setting. + +config GD32F4_ENET_PTP + bool "Precision Time Protocol (PTP)" + default n + ---help--- + Precision Time Protocol (PTP). Not supported but some hooks are indicated + with this condition. + +config GD32F4_RMII + bool "Use the reduced media-independent interface (RMII) interface" + default y if !GD32F4_MII + ---help--- + Select Ethernet MII interface. The application can only select one of + the MII or RMII mode. + +choice + prompt "RMII clock configuration" + default GD32F4_RMII_CKOUT0 + depends on GD32F4_RMII + +config GD32F4_RMII_CKOUT0 + bool "Use CKOUT0 as RMII clock" + ---help--- + Use CKOUT0 to clock the RMII interface. + +config GD32F4_RMII_CKOUT1 + bool "Use CKOUT1 as RMII clock" + ---help--- + Use CKOUT1 to clock the RMII interface. + +config GD32F4_RMII_EXTCLK + bool "External RMII clock" + ---help--- + Clocking is provided by external clock. And not use CKOUT for + RMII clock. + +endchoice # RMII clock configuration + +config GD32F4_ENET_MAC_REGDEBUG + bool "Register Level Debug" + default n + depends on DEBUG_NET_INFO + ---help--- + Enable very low-level register access debug. Depends on CONFIG_DEBUG_FEATURES. + +endmenu # Ethernet MAC configuration + +config GD32F4_USBHOST + bool "Enable USB Host Support" + depends on GD32F4_OTGFS || GD32F4_OTGHS + default n + select USBHOST + +menu "USB FS Host Configuration" + depends on GD32F4_OTGFS && GD32F4_USBHOST + +endmenu + +menu "USB HS Host Configuration" + depends on GD32F4_OTGHS && GD32F4_USBHOST + +endmenu + +menu "USB Host Debug Configuration" + depends on GD32F4_USBHOST + +endmenu + +comment "USB Device Configuration" + +config GD32F4_USB_ITRMP + bool "Re-map USB interrupt" + default n if !GD32F4_CAN1 + default y if GD32F4_CAN1 + depends on GD32F4_USB && GD32F4_GD32F4XX + ---help--- + The legacy USB in the F1 series shared interrupt lines with USB + device and CAN1. In the F3 series, a hardware options was added to + either retain the legacy F1 behavior or to map the USB interrupts to + their own dedicated vectors. The option is available only for the + F3 family and selects the use of the dedicated USB interrupts. + +menu "CAN driver configuration" + depends on GD32F4_CAN + +endmenu # "CAN driver configuration" + + +if GD32F4_TLI + +menu "TLI Configuration" + depends on GD32F4_TLI + +endmenu # TLI Configuration + +endif # GD32F4_TLI + +menu "GD32F4 QEncoder Driver" + depends on SENSORS_QENCODER + depends on GD32F4_TIMER0 || GD32F4_TIMER1 || GD32F4_TIMER2 || GD32F4_TIMER3 || GD32F4_TIMER4 || GD32F4_TIMER7 + +endmenu # GD32F4 QEncoder Driver + +# endif # ARCH_CHIP_GD32F4 diff --git a/arch/arm/src/gd32f4/Make.defs b/arch/arm/src/gd32f4/Make.defs new file mode 100644 index 0000000000..4b38cfae5c --- /dev/null +++ b/arch/arm/src/gd32f4/Make.defs @@ -0,0 +1,57 @@ +############################################################################ +# arch/arm/src/gd32f4/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include armv7-m/Make.defs + +CHIP_CSRCS = gd32f4xx_allocateheap.c gd32f4xx_start.c gd32f4xx_rcu.c +CHIP_CSRCS += gd32f4xx_serial.c gd32f4xx_lowputc.c +CHIP_CSRCS += gd32f4xx_gpio.c gd32f4xx_syscfg.c +CHIP_CSRCS += gd32f4xx_irq.c gd32f4xx_exti.c +CHIP_CSRCS += gd32f4xx_dma.c + +ifneq ($(CONFIG_SCHED_TICKLESS),y) +CHIP_CSRCS += gd32f4xx_timerisr.c +else +CHIP_CSRCS += gd32f4xx_tickless.c +endif + +ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y) +CHIP_CSRCS += gd32f4xx_idle.c +endif + +#ifneq ($(CONFIG_ARCH_CUSTOM_PMINIT),y) +#CHIP_CSRCS += gd32f4xx_pminitialize.c +#endif + +#ifneq ($(CONFIG_GD32F4_PROGMEM),y) +CHIP_CSRCS += gd32f4xx_fmc.c gd32f4xx_progmem.c +#endif + +ifeq ($(CONFIG_GD32F4_ENETMAC),y) +CHIP_CSRCS += gd32f4xx_enet.c +endif + +ifeq ($(CONFIG_GD32F4_PMU),y) +CHIP_CSRCS += gd32f4xx_pmu.c +endif + +ifeq ($(CONFIG_GD32F4_SPI),y) +CHIP_CSRCS += gd32f4xx_spi.c +endif diff --git a/arch/arm/src/gd32f4/chip.h b/arch/arm/src/gd32f4/chip.h new file mode 100644 index 0000000000..16990b4e7b --- /dev/null +++ b/arch/arm/src/gd32f4/chip.h @@ -0,0 +1,57 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_CHIP_H +#define __ARCH_ARM_SRC_GD32F4_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* Include the chip capabilities file */ + +#include + +/* Include the chip interrupt definition file */ + +#include + +/* Include the chip memory map */ + +#include "hardware/gd32f4xx_memorymap.h" + +/* Include the chip pinmap */ + +#include "hardware/gd32f4xx_pinmap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Provide the required number of peripheral interrupt vector definitions as + * well. The definition GD32_IRQ_NEXTINT simply comes from the chip-specific + * IRQ header file included by arch/gd32f4/irq.h. + */ + +#define ARMV7M_PERIPHERAL_INTERRUPTS GD32_IRQ_NEXTINT + +#endif /* __ARCH_ARM_SRC_GD32F4_CHIP_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx.h b/arch/arm/src/gd32f4/gd32f4xx.h new file mode 100644 index 0000000000..4e04d4c01c --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include "arm_internal.h" + +/* Peripherals **************************************************************/ + +#include "chip.h" +#include "gd32f4xx_exti.h" +#include "gd32f4xx_enet.h" +#include "gd32f4xx_dma.h" +#include "gd32f4xx_gpio.h" +#include "gd32f4xx_rcu.h" +#include "gd32f4xx_usart.h" +#include "gd32f4xx_lowputc.h" +#include "gd32f4xx_fmc.h" +#include "gd32f4xx_pmu.h" +#include "gd32f4xx_spi.h" +#include "gd32f4xx_syscfg.h" + +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_allocateheap.c b/arch/arm/src/gd32f4/gd32f4xx_allocateheap.c new file mode 100644 index 0000000000..174eb7b1ad --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_allocateheap.c @@ -0,0 +1,395 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_allocateheap.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "chip.h" + +#include "mpu.h" +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The GD32F4xx all contains System SRAM and tightly-coupled memory + * SRAM (TCMSRAM) on the chip. + * The following definitions must be provided to specify the size and + * location of System SRAM: + * + * CONFIG_RAM_END : SRAM end address + * + * The TCMSRAM is different to SRAM, and it be accessed only by the data + * bus of the Cortex®-M4 core, and can not be used for DMA. When used DMA, + * then the following should be defined to exclude TCMSRAM from the heap: + * + * CONFIG_GD32F4_TCMEXCLUDE : Exclude TCMSRAM from the HEAP + * + * In addition to internal SRAM, external RAM may also be available through + * the EXMC. When external RAM is want to be used, then the following + * definitions should to be provided: + * + * CONFIG_GD32F4_EXMC=y : Enable the EXMC + * CONFIG_GD32F4_EXTERNAL_RAM=y : Indicates that via the EXMC, external + * RAM can be used. + * CONFIG_HEAP2_BASE : External RAM base address + * CONFIG_HEAP2_SIZE : External RAM size + * CONFIG_MM_REGIONS : Must be set to the value match to how + * many RAMs you have used. + */ + +#if !defined(CONFIG_GD32F4_EXMC) +# undef CONFIG_GD32F4_EXTERNAL_RAM +#endif + +/* The heap is in one contiguous block starting at g_idle_topstack and + * extending through CONFIG_RAM_END. + */ + +#if defined(CONFIG_GD32F4_GD32F4XX) + +/* Set the end of system SRAM */ + +# if defined(CONFIG_GD32F4_GD32F450) +# if defined(CONFIG_GD32F4_GD32F450XI) +# define SRAM_END 0x20070000 +# else +# define SRAM_END 0x20030000 +# endif +# else +# define SRAM_END 0x20020000 +# endif + +/* Set the range of TCMSRAM */ + +# define TCMSRAM_START 0x10000000 +# define TCMSRAM_END 0x10010000 + +/* There are 4 possible SRAM configuration case: + * + * Case 0. System SRAM + * CONFIG_MM_REGIONS define as 1 + * CONFIG_GD32F4_TCMEXCLUDE defined, not use TCMSRAM + * CONFIG_GD32F4_EXTERNAL_RAM NOT defined + * + * Case 1. System SRAM and TCM SRAM + * CONFIG_MM_REGIONS define as 2 + * CONFIG_GD32F4_TCMEXCLUDE NOT defined, use TCMSRAM + * CONFIG_GD32F4_EXTERNAL_RAM NOT defined + * + * Case 2. System SRAM and EXMC SRAM + * CONFIG_MM_REGIONS define as 2 + * CONFIG_GD32F4_TCMEXCLUDE defined, not use TCMSRAM + * CONFIG_GD32F4_EXTERNAL_RAM defined + * + * Case 3. System SRAM, CCM SRAM, and EXMC SRAM + * CONFIG_MM_REGIONS define as 3 + * CONFIG_GD32F4_TCMEXCLUDE NOT defined, use TCMSRAM + * CONFIG_GD32F4_EXTERNAL_RAM defined + * + * Make sure that all definitions are consistent before doing anything else + */ + +# if CONFIG_MM_REGIONS < 1 + +# error "There is at least one memory region" +# define CONFIG_MM_REGIONS 1 +# undef CONFIG_GD32F4_EXTERNAL_RAM +# undef CONFIG_GD32F4_TCMEXCLUDE +# define CONFIG_GD32F4_TCMEXCLUDE 1 + +# elif CONFIG_MM_REGIONS < 2 +/* Only one memory region. Force Case 0 */ + +# warning "EXMC SRAM (and TCMSRAM) excluded from the heap" +# undef CONFIG_GD32F4_EXTERNAL_RAM +# undef CONFIG_GD32F4_TCMEXCLUDE +# define CONFIG_GD32F4_TCMEXCLUDE 1 + +# elif CONFIG_MM_REGIONS < 3 +/* Two memory regions. Case 1 or 2 */ + +# if !defined(CONFIG_GD32F4_TCMEXCLUDE) && defined(CONFIG_GD32F4_EXTERNAL_RAM) +# error "Can not support both TCM SRAM and EXMC SRAM, when CONFIG_MM_REGIONS is 2 " +# undef CONFIG_GD32F4_TCMEXCLUDE +# define CONFIG_GD32F4_TCMEXCLUDE 1 +# endif + +/* Case 1, TCMSRAM is used. In this case, DMA should not be used */ + +# if !defined(CONFIG_GD32F4_TCMEXCLUDE) + +# ifdef CONFIG_ARCH_DMA +# error "TCMSRAM is included in the heap AND DMA is enabled" +# endif +# endif + +# elif CONFIG_MM_REGIONS == 3 +/* Three memory regions. Case 3 */ + +# ifdef CONFIG_ARCH_DMA +# error "TCM SRAM is included in the heap AND DMA is enabled" +# endif + +# else +# error "CONFIG_MM_REGIONS > 3 but there no more region(s) are other than SRAM, TCMSRAM and EXMC RAM" +# undef CONFIG_MM_REGIONS +# define CONFIG_MM_REGIONS 3 + +# endif /* CONFIG_MM_REGIONS */ + +#else +# error "Unsupported GD32 chip" +#endif + +/* If EXMC SRAM is going to be used as heap, then verify that the starting + * address and size of the external SRAM region has been provided in the + * configuration (as CONFIG_HEAP2_BASE and CONFIG_HEAP2_SIZE). + */ + +#ifdef CONFIG_GD32F4_EXTERNAL_RAM +# if !defined(CONFIG_HEAP2_BASE) || !defined(CONFIG_HEAP2_SIZE) +# error "When use EXMC RAM CONFIG_HEAP2_BASE and CONFIG_HEAP2_SIZE must be provided" +# undef CONFIG_GD32F4_EXTERNAL_RAM +# endif +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_heap_color + * + * Description: + * Set heap memory to a known, non-zero state to checking heap usage. + * + ****************************************************************************/ + +#ifdef CONFIG_HEAP_COLORATION +static inline void up_heap_color(void *start, size_t size) +{ + memset(start, HEAP_COLOR, size); +} +#else +# define up_heap_color(start,size) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_heap + * + * Description: + * This function will be called to dynamically set aside the heap region. + * + * For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and + * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the + * size of the unprotected, user-space heap. + * + * If a protected kernel-space heap is provided, the kernel heap must be + * allocated (and protected) by an analogous up_allocate_kheap(). + * + * The following memory map is assumed for the flat build: + * + * .data region. Size determined at link time. + * .bss region Size determined at link time. + * IDLE thread stack. Size determined by CONFIG_IDLETHREAD_STACKSIZE. + * Heap. Extends to the end of SRAM. + * + * The following memory map is assumed for the kernel build: + * + * Kernel .data region Size determined at link time + * Kernel .bss region Size determined at link time + * Kernel IDLE thread stack Size determined by + * CONFIG_IDLETHREAD_STACKSIZE + * Padding for alignment + * User .data region Size determined at link time + * User .bss region Size determined at link time + * Kernel heap Size determined by + * CONFIG_MM_KERNEL_HEAPSIZE + * User heap Extends to the end of SRAM + * + ****************************************************************************/ + +void up_allocate_heap(void **heap_start, size_t *heap_size) +{ +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) + /* Get the unaligned size and position of the user-space heap. + * This heap begins after the user-space .bss section at an offset + * of CONFIG_MM_KERNEL_HEAPSIZE (subject to alignment). + */ + + uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend + + CONFIG_MM_KERNEL_HEAPSIZE; + size_t usize = SRAM_END - ubase; + int log2; + + DEBUGASSERT(ubase < (uintptr_t)SRAM_END); + + /* Adjust that size to account for MPU alignment requirements. + * NOTE that there is an implicit assumption that the SRAM_END + * is aligned to the MPU requirement. + */ + + log2 = (int)mpu_log2regionfloor(usize); + + usize = (1 << log2); + ubase = SRAM_END - usize; + + /* Return the user-space heap settings */ + + board_autoled_on(LED_HEAPALLOCATE); + *heap_start = (void *)ubase; + *heap_size = usize; + + /* Colorize the heap for debug */ + + up_heap_color((void *)ubase, usize); + + /* Allow user-mode access to the user heap memory */ + + gd32_mpu_uheap((uintptr_t)ubase, usize); +#else + + /* Return the heap settings */ + + board_autoled_on(LED_HEAPALLOCATE); + *heap_start = (void *)g_idle_topstack; + *heap_size = SRAM_END - g_idle_topstack; + + /* Colorize the heap for debug */ + + up_heap_color(*heap_start, *heap_size); +#endif +} + +/**************************************************************************** + * Name: up_allocate_kheap + * + * Description: + * For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and + * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function allocates + * (and protects) the kernel-space heap. + * + ****************************************************************************/ + +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) +void up_allocate_kheap(void **heap_start, size_t *heap_size) +{ + /* Get the unaligned size and position of the user-space heap. + * This heap begins after the user-space .bss section at an offset + * of CONFIG_MM_KERNEL_HEAPSIZE (subject to alignment). + */ + + uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend + + CONFIG_MM_KERNEL_HEAPSIZE; + size_t usize = SRAM_END - ubase; + int log2; + + DEBUGASSERT(ubase < (uintptr_t)SRAM_END); + + /* Adjust that size to account for MPU alignment requirements. + * NOTE that there is an implicit assumption that the SRAM_END + * is aligned to the MPU requirement. + */ + + log2 = (int)mpu_log2regionfloor(usize); + + usize = (1 << log2); + ubase = SRAM_END - usize; + + /* Return the kernel heap settings (i.e., the part of the heap region + * that was not dedicated to the user heap). + */ + + *heap_start = (void *)USERSPACE->us_bssend; + *heap_size = ubase - (uintptr_t)USERSPACE->us_bssend; +} +#endif + +/**************************************************************************** + * Name: arm_addregion + * + * Description: + * Memory may be added in non-contiguous chunks. Additional chunks are + * added by calling this function. + * + ****************************************************************************/ + +#if CONFIG_MM_REGIONS > 1 +void arm_addregion(void) +{ +#ifndef CONFIG_GD32F4_TCMEXCLUDE +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) + + /* Allow user-mode access to the TCMSRAM heap */ + + gd32_mpu_uheap((uintptr_t)TCMSRAM_START, TCMSRAM_END - TCMSRAM_START); + +#endif + + /* Colorize the heap for debug */ + + up_heap_color((void *)TCMSRAM_START, TCMSRAM_END - TCMSRAM_START); + + /* Add the TCMSRAM user heap region. */ + + kumm_addregion((void *)TCMSRAM_START, TCMSRAM_END - TCMSRAM_START); +#endif + +#ifdef CONFIG_GD32F4_EXTERNAL_RAM +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) + + /* Allow user-mode access to the EXMC SRAM user heap memory */ + + gd32_mpu_uheap((uintptr_t)CONFIG_HEAP2_BASE, CONFIG_HEAP2_SIZE); + +#endif + + /* Colorize the heap for debug */ + + up_heap_color((void *)CONFIG_HEAP2_BASE, CONFIG_HEAP2_SIZE); + + /* Add the external EXMC SRAM user heap region. */ + + kumm_addregion((void *)CONFIG_HEAP2_BASE, CONFIG_HEAP2_SIZE); +#endif +} +#endif diff --git a/arch/arm/src/gd32f4/gd32f4xx_dma.c b/arch/arm/src/gd32f4/gd32f4xx_dma.c new file mode 100644 index 0000000000..fb374baa25 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_dma.c @@ -0,0 +1,1051 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_dma.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sched/sched.h" +#include "chip.h" +#include "gd32f4xx_dma.h" +#include "gd32f4xx.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if GD32_NDMA > 1 + +#define DMA0_NPERIPHS (8) + +#define DMA0_NCHANNELS (8) +#define DMA1_NCHANNELS (8) +#define DMA_NCHANNELS (DMA0_NCHANNELS + DMA1_NCHANNELS) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes one DMA channel */ + +struct gd32_dma_channel_s +{ + uint8_t chan_num; /* DMA channel number (0-7) */ + uint8_t irq; /* DMA channel IRQ number */ + uint8_t periph; /* DMA peripheral number (0-7) */ + sem_t chsem; /* Used to wait for DMA channel to become available */ + uint32_t dmabase; /* DMA base address */ + dma_callback_t callback; /* Callback invoked when the DMA completes */ + void *arg; /* Argument passed to callback function */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static uint8_t gd32_dma_interrupt_flag_get(uint32_t dma_periph, + uint8_t channelx); +static void gd32_dma_interrupt_flag_clear(uint32_t dma_periph, + uint8_t channelx, + uint8_t flag); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This array describes the state of each DMA */ + +static struct gd32_dma_channel_s g_dmachan[DMA_NCHANNELS] = +{ + { + .chan_num = GD32_DMA_CH0, + .irq = GD32_IRQ_DMA0_CHANNEL0, + .dmabase = GD32_DMA0, + }, + { + .chan_num = GD32_DMA_CH1, + .irq = GD32_IRQ_DMA0_CHANNEL1, + .dmabase = GD32_DMA0, + }, + { + .chan_num = GD32_DMA_CH2, + .irq = GD32_IRQ_DMA0_CHANNEL2, + .dmabase = GD32_DMA0, + }, + { + .chan_num = GD32_DMA_CH3, + .irq = GD32_IRQ_DMA0_CHANNEL3, + .dmabase = GD32_DMA0, + }, + { + .chan_num = GD32_DMA_CH4, + .irq = GD32_IRQ_DMA0_CHANNEL4, + .dmabase = GD32_DMA0, + }, + { + .chan_num = GD32_DMA_CH5, + .irq = GD32_IRQ_DMA0_CHANNEL5, + .dmabase = GD32_DMA0, + }, + { + .chan_num = GD32_DMA_CH6, + .irq = GD32_IRQ_DMA0_CHANNEL6, + .dmabase = GD32_DMA0, + }, + { + .chan_num = GD32_DMA_CH7, + .irq = GD32_IRQ_DMA0_CHANNEL7, + .dmabase = GD32_DMA0, + }, + + { + .chan_num = GD32_DMA_CH0, + .irq = GD32_IRQ_DMA1_CHANNEL0, + .dmabase = GD32_DMA1, + }, + { + .chan_num = GD32_DMA_CH1, + .irq = GD32_IRQ_DMA1_CHANNEL1, + .dmabase = GD32_DMA1, + }, + { + .chan_num = GD32_DMA_CH2, + .irq = GD32_IRQ_DMA1_CHANNEL2, + .dmabase = GD32_DMA1, + }, + { + .chan_num = GD32_DMA_CH3, + .irq = GD32_IRQ_DMA1_CHANNEL3, + .dmabase = GD32_DMA1, + }, + { + .chan_num = GD32_DMA_CH4, + .irq = GD32_IRQ_DMA1_CHANNEL4, + .dmabase = GD32_DMA1, + }, + { + .chan_num = GD32_DMA_CH5, + .irq = GD32_IRQ_DMA1_CHANNEL5, + .dmabase = GD32_DMA1, + }, + { + .chan_num = GD32_DMA_CH6, + .irq = GD32_IRQ_DMA1_CHANNEL6, + .dmabase = GD32_DMA1, + }, + { + .chan_num = GD32_DMA_CH7, + .irq = GD32_IRQ_DMA1_CHANNEL7, + .dmabase = GD32_DMA1, + }, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_dma_clock_enable + * + * Description: + * Enable DMA clock + ****************************************************************************/ + +static void gd32_dma_clock_enable(uint32_t dmabase) +{ + uint32_t rcu_en; + uint32_t regaddr; + + /* Determine which DMA to configure */ + + switch (dmabase) + { + default: + return; +#ifdef CONFIG_GD32F4_DMA0 + case GD32_DMA0: + rcu_en = RCU_AHB1EN_DMA0EN; + regaddr = GD32_RCU_AHB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_DMA1 + case GD32_DMA1: + rcu_en = RCU_AHB1EN_DMA1EN; + regaddr = GD32_RCU_AHB1EN; + break; +#endif + } + + /* Enable AHB1 clock for DMA */ + + modifyreg32(regaddr, 0, rcu_en); +} + +/**************************************************************************** + * Name: gd32_dmasem_take + * + * Description: + * Used to request exclusive access to a DMA channel. + * + ****************************************************************************/ + +static int gd32_dmasem_take(struct gd32_dma_channel_s *dmachan) +{ + return nxsem_wait_uninterruptible(&dmachan->chsem); +} + +/**************************************************************************** + * Name: gd32_dmasem_give + * + * Description: + * Used to free exclusive access to a DMA channel. + * + ****************************************************************************/ + +static inline void gd32_dmasem_give(struct gd32_dma_channel_s *dmachan) +{ + nxsem_post(&dmachan->chsem); +} + +/**************************************************************************** + * Name: gd32_dma_channel_get + * + * Description: + * Get the g_dmachan table entry associated with a DMA controller and + * a channel number + ****************************************************************************/ + +static inline struct gd32_dma_channel_s + *gd32_dma_channel_get(uint32_t channelx, + uint32_t dma_periph) +{ + int index; + + DEBUGASSERT(channelx < DMA0_NCHANNELS); + + DEBUGASSERT(dma_periph == GD32_DMA0_BASE && dma_periph == GD32_DMA1_BASE); + + /* Convert the dma_periph + chan_num based on the fact that there are + * 8 channel per dma_periph. + */ + + if (dma_periph == GD32_DMA0_BASE) + { + index = channelx; + } + else + { + index = channelx + DMA0_NCHANNELS; + } + + /* Then return the chan_num structure associated with the chan_num index */ + + return &g_dmachan[index]; +} + +/**************************************************************************** + * Name: gd32_channel_enable + * + * Description: + * Enable the DMA channelx + * + ****************************************************************************/ + +static void gd32_channel_enable(uint32_t dma_periph, uint8_t channelx) +{ + uint32_t regaddr; + uint32_t regval; + + DEBUGASSERT(channelx < DMA0_NCHANNELS); + + DEBUGASSERT(dma_periph == GD32_DMA0_BASE && dma_periph == GD32_DMA1_BASE); + + /* Get DMA channel control register address */ + + regaddr = GD32_DMA_CHCTL(dma_periph, channelx); + + /* Enable DMA channelx */ + + regval = getreg32(regaddr); + regval |= DMA_CHXCTL_CHEN; + + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Name: gd32_channel_disable + * + * Description: + * Disable the DMA channelx + * + ****************************************************************************/ + +static void gd32_channel_disable(uint32_t dma_periph, uint8_t channelx) +{ + uint32_t regaddr; + uint32_t regval; + + DEBUGASSERT(channelx < DMA0_NCHANNELS); + + DEBUGASSERT(dma_periph == GD32_DMA0_BASE && dma_periph == GD32_DMA1_BASE); + + /* Get DMA channel control register address */ + + regaddr = GD32_DMA_CHCTL(dma_periph, channelx); + + /* Disable DMA channelx */ + + regval = getreg32(regaddr); + regval &= ~DMA_CHXCTL_CHEN; + + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Name: gd32_channel_interrupt_enable + * + * Description: + * Enable the DMA channelx interrupt + * + ****************************************************************************/ + +static void gd32_channel_interrupt_enable(uint32_t dma_periph, + uint8_t channelx, + uint32_t interrupt) +{ + uint32_t regaddr; + uint32_t regval; + + DEBUGASSERT(channelx < DMA0_NCHANNELS); + + DEBUGASSERT(dma_periph == GD32_DMA0_BASE && dma_periph == GD32_DMA1_BASE); + + /* Get DMA channel control register address */ + + regaddr = GD32_DMA_CHCTL(dma_periph, channelx); + + /* Disable all interrupts at the DMA controller */ + + regval = getreg32(regaddr); + regval &= ~(DMA_CHXCTL_SDEIE | DMA_CHXCTL_TAEIE | + DMA_CHXCTL_HTFIE | DMA_CHXCTL_FTFIE); + + /* Set DMA channelx interrupt */ + + regval |= interrupt; + + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Name: gd32_channel_interrupt_disable + * + * Description: + * Disable the DMA channelx interrupt + * + ****************************************************************************/ + +static void gd32_channel_interrupt_disable(uint32_t dma_periph, + uint8_t channelx) +{ + uint32_t regaddr; + uint32_t regval; + + DEBUGASSERT(channelx < DMA0_NCHANNELS); + + DEBUGASSERT(dma_periph == GD32_DMA0_BASE && dma_periph == GD32_DMA1_BASE); + + /* Get DMA channel control register address */ + + regaddr = GD32_DMA_CHCTL(dma_periph, channelx); + + /* Disable all interrupts at the DMA controller */ + + regval = getreg32(regaddr); + regval &= ~(DMA_CHXCTL_SDEIE | DMA_CHXCTL_TAEIE | + DMA_CHXCTL_HTFIE | DMA_CHXCTL_FTFIE); + + putreg32(regval, regaddr); + + /* Clear channelx interrupt flag */ + + regval = (DMA_INTF_FEEIF | DMA_INTF_SDEIF | DMA_INTF_TAEIF | + DMA_INTF_HTFIF | DMA_INTF_FTFIF); + gd32_dma_interrupt_flag_clear(dma_periph, channelx, (uint8_t)regval); +} + +/**************************************************************************** + * Name: gd32_dma_interrupt_flag_get + * + * Description: + * Get DMA interrupt flag + * + ****************************************************************************/ + +static uint8_t gd32_dma_interrupt_flag_get(uint32_t dma_periph, + uint8_t channelx) +{ + uint32_t regval; + uint8_t chan_intf_shift = 0; + uint8_t status = 0; + + DEBUGASSERT(channelx < DMA0_NCHANNELS); + + DEBUGASSERT(dma_periph == GD32_DMA0_BASE && dma_periph == GD32_DMA1_BASE); + + /* Get the interrupt status for this channel */ + + if (channelx < 4) + { + /* Calculate channelx interrupt flag shift */ + + chan_intf_shift = channelx * 8 - (channelx % 2) * 2; + + regval = getreg32(dma_periph + GD32_DMA_INTF0_OFFSET); + status = (regval >> chan_intf_shift) & DMA_INTF_MASK; + } + else + { + /* Calculate channelx interrupt flag shift */ + + channelx = channelx - 4; + chan_intf_shift = channelx * 8 - (channelx % 2) * 2; + + regval = getreg32(dma_periph + GD32_DMA_INTF1_OFFSET); + status = (regval >> chan_intf_shift) & DMA_INTF_MASK; + } + + return status; +} + +/**************************************************************************** + * Name: gd32_dma_interrupt_flag_clear + * + * Description: + * Clear DMA interrupt flag + * + ****************************************************************************/ + +static void gd32_dma_interrupt_flag_clear(uint32_t dma_periph, + uint8_t channelx, uint8_t flag) +{ + uint32_t regval; + uint8_t chan_intf_shift = 0; + + DEBUGASSERT(channelx < DMA0_NCHANNELS); + + DEBUGASSERT(dma_periph == GD32_DMA0_BASE && dma_periph == GD32_DMA1_BASE); + + /* Clear the interrupt status for this channel */ + + if (channelx < 4) + { + /* Calculate channelx interrupt flag shift */ + + chan_intf_shift = channelx * 8 - (channelx % 2) * 2; + + if (flag) + { + regval = flag << chan_intf_shift; + + /* Clear channelx interrupt flag */ + + putreg32(regval, (dma_periph + GD32_DMA_INTC0_OFFSET)); + } + } + else + { + /* Calculate channelx interrupt flag shift */ + + channelx = channelx - 4; + chan_intf_shift = channelx * 8 - (channelx % 2) * 2; + + if (flag) + { + regval = flag << chan_intf_shift; + + /* Clear channelx interrupt flag */ + + putreg32(regval, (dma_periph + GD32_DMA_INTC1_OFFSET)); + } + } +} + +/**************************************************************************** + * Name: gd32_dma_interrupt + * + * Description: + * DMA interrupt handler + * + ****************************************************************************/ + +static int gd32_dma_interrupt(int irq, void *context, void *arg) +{ + struct gd32_dma_channel_s *dmachan; + uint8_t status; + + /* 'arg' should the DMA channel instance. */ + + dmachan = (struct gd32_dma_channel_s *)arg; + + DEBUGASSERT(dmachan != NULL); + + if (dmachan->dmabase == GD32_DMA0_BASE) + { + DEBUGASSERT(dmachan == &g_dmachan[dmachan->chan_num]); + } + else + { + DEBUGASSERT(dmachan == &g_dmachan[dmachan->chan_num + DMA0_NCHANNELS]); + } + + /* Get the interrupt status for this channel */ + + status = gd32_dma_interrupt_flag_get(dmachan->dmabase, dmachan->chan_num); + + if (status) + { + gd32_dma_interrupt_flag_clear(dmachan->dmabase, dmachan->chan_num, + status); + + /* Call the DMA callback */ + + if (dmachan->callback) + { + dmachan->callback(dmachan, status, dmachan->arg); + } + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_dma_initialize + * + * Description: + * Initialize the DMA subsystem + * + * Returned Value: + * None + * + ****************************************************************************/ + +void weak_function arm_dma_initialize(void) +{ + struct gd32_dma_channel_s *dmachan; + uint8_t channelx; + + dmainfo("Initialize DMA\n"); + + /* Initialize each DMA channel */ + + for (channelx = 0; channelx < DMA_NCHANNELS; channelx++) + { + dmachan = &g_dmachan[channelx]; + + DEBUGASSERT(dmachan != NULL); + + nxsem_init(&dmachan->chsem, 0, 1); + + /* Attach DMA interrupt vectors */ + + irq_attach(dmachan->irq, gd32_dma_interrupt, dmachan); + + /* Disable the DMA channel and channel interrupt */ + + gd32_channel_interrupt_disable(dmachan->dmabase, dmachan->chan_num); + gd32_channel_disable(dmachan->dmabase, dmachan->chan_num); + + /* Enable the channel interrupts at the NVIC (still disabled + * at the DMA controller) + */ + + up_enable_irq(dmachan->irq); + } +} + +/**************************************************************************** + * Name: gd32_dma_channel_alloc + * + * Description: + * Allocate a DMA channel. This function gives the caller mutually + * exclusive access to the DMA channel specified by the 'dmamap' argument. + * Should note that a DMA channel only can be used by on peripheral at the + * time. + * + * If the DMA channel is not available, then gd32_dma_channel_alloc() will + * wait until the holder of the channel relinquishes the channel by calling + * gd32_dma_channel_free(). + * + * Input Parameters: + * periph_req - Identifies the DMA channle is request by which peripheral + * + * Returned Value: + * If periph_req is valid, this function ALWAYS returns a non-NULL + * void* DMA channel handle. + * + ****************************************************************************/ + +DMA_HANDLE gd32_dma_channel_alloc(uint8_t periph_req) +{ + struct gd32_dma_channel_s *dmachan; + int ret; + uint8_t index = 0; + uint8_t subperiph = 0; + + /* Get the peripheral numbers from the peripheral request */ + + subperiph = (periph_req >> PERIPH_SHIFT) & PERIPH_MASK; + + DEBUGASSERT(subperiph < DMA0_NPERIPHS); + + /* Get the channel index from the peripheral request */ + + index = (periph_req >> CHANNEL_SHIFT) & CHANNEL_MASK; + + DEBUGASSERT(index < DMA_NCHANNELS); + + /* Get the chan_num index from the bit-encoded channel value */ + + dmachan = &g_dmachan[index]; + + DEBUGASSERT(dmachan != NULL); + + /* Get exclusive access to the DMA channel */ + + ret = gd32_dmasem_take(dmachan); + if (ret < 0) + { + gd32_dmasem_give(dmachan); + return NULL; + } + + dmachan->periph = subperiph; + + return (DMA_HANDLE)dmachan; +} + +/**************************************************************************** + * Name: gd32_dma_channel_free + * + * Description: + * Release a DMA channel. If another thread is waiting for this DMA + * channel in a call to gd32_dma_channel_alloc, then this function will + * re-assign the DMA channel to that thread and wake it up. + * NOTE: The 'handle' used in this argument must NEVER be used again + * until gd32_dma_channel_alloc() is called again to re-gain access to + * the channel. + * + * Returned Value: + * None + * + * Assumptions: + * - The caller holds the DMA channel. + * - There is no DMA in progress + * + ****************************************************************************/ + +void gd32_dma_channel_free(DMA_HANDLE handle) +{ + struct gd32_dma_channel_s *dmachan = (struct gd32_dma_channel_s *)handle; + + DEBUGASSERT(dmachan != NULL); + + /* Disable the DMA channel and channel interrupt */ + + gd32_channel_interrupt_disable(dmachan->dmabase, dmachan->chan_num); + gd32_channel_disable(dmachan->dmabase, dmachan->chan_num); + + /* Release the channel */ + + gd32_dmasem_give(dmachan); +} + +/**************************************************************************** + * Name: gd32_dma_singlemode_setup + * + * Description: + * Configure DMA single data mode before using + * + ****************************************************************************/ + +void gd32_dma_singlemode_setup(struct gd32_dma_channel_s *dmachan, + dma_single_data_parameter_struct *init_struct) +{ + uint32_t regaddr; + uint32_t regval; + + dmainfo("peripheral address: %08" PRIx32 "memory address: %08" PRIx32 + "transfer numbers: %08" PRIx16 "\n", + init_struct->periph_addr, init_struct->memory0_addr, + init_struct->number); + + /* Clear CHEN bit in channel x control register */ + + regaddr = GD32_DMA_CHCTL(dmachan->dmabase, dmachan->chan_num); + + regval = getreg32(regaddr); + regval &= ~DMA_CHXCTL_CHEN; + putreg32(regval, regaddr); + + /* Clear channelx interrupt flag */ + + regval = (DMA_INTF_FEEIF | DMA_INTF_SDEIF | DMA_INTF_TAEIF | + DMA_INTF_HTFIF | DMA_INTF_FTFIF); + gd32_dma_interrupt_flag_clear(dmachan->dmabase, dmachan->chan_num, + (uint8_t)regval); + + /* Select single data mode */ + + regaddr = GD32_DMA_CHFCTL(dmachan->dmabase, dmachan->chan_num); + regval = getreg32(regaddr); + regval &= ~DMA_CHXFCTL_MDMEN; + putreg32(regval, regaddr); + + /* Configure peripheral base address */ + + regaddr = GD32_DMA_CHPADDR(dmachan->dmabase, dmachan->chan_num); + putreg32(init_struct->periph_addr, regaddr); + + /* Configure memory base address */ + + regaddr = GD32_DMA_CHM0ADDR(dmachan->dmabase, dmachan->chan_num); + putreg32(init_struct->memory0_addr, regaddr); + + /* Configure the number of remaining data to be transferred */ + + regaddr = GD32_DMA_CHCNT(dmachan->dmabase, dmachan->chan_num); + putreg32(init_struct->number, regaddr); + + /* Configure peripheral and memory transfer width, channel priotity, + * transfer mode + */ + + regaddr = GD32_DMA_CHCTL(dmachan->dmabase, dmachan->chan_num); + regval = getreg32(regaddr); + + regval &= ~(DMA_CHXCTL_PWIDTH_MASK | DMA_CHXCTL_MWIDTH_MASK | + DMA_CHXCTL_PRIO_MASK | DMA_CHXCTL_TM_MASK); + + regval |= init_struct->direction; + + if (DMA_WIDTH_8BITS_SELECT == init_struct->periph_memory_width) + { + regval |= DMA_MEMORY_WIDTH_8BIT; + } + else if (DMA_WIDTH_16BITS_SELECT == init_struct->periph_memory_width) + { + regval |= DMA_MEMORY_WIDTH_16BIT; + } + else if (DMA_WIDTH_32BITS_SELECT == init_struct->periph_memory_width) + { + regval |= DMA_MEMORY_WIDTH_32BIT; + } + else + { + regval |= DMA_MEMORY_WIDTH_8BIT; + } + + if (DMA_PRIO_LOW_SELECT == init_struct->priority) + { + regval |= DMA_PRIORITY_LOW; + } + else if (DMA_PRIO_MEDIUM_SELECT == init_struct->priority) + { + regval |= DMA_PRIORITY_MEDIUM; + } + else if (DMA_PRIO_HIGH_SELECT == init_struct->priority) + { + regval |= DMA_PRIORITY_HIGH; + } + else if (DMA_PRIO_ULTRA_HIGHSELECT == init_struct->priority) + { + regval |= DMA_PRIORITY_ULTRA_HIGH; + } + else + { + regval |= DMA_PRIORITY_MEDIUM; + } + + /* Configure peripheral, memory increasing mode and DMA circular mode */ + + if (DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc) + { + regval |= DMA_CHXCTL_PNAGA; + } + else if (DMA_PERIPH_INCREASE_DISABLE == init_struct->periph_inc) + { + regval &= ~DMA_CHXCTL_PNAGA; + } + else + { + regval |= DMA_CHXCTL_PAIF; + } + + if (DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc) + { + regval |= DMA_CHXCTL_MNAGA; + } + else + { + regval &= ~DMA_CHXCTL_MNAGA; + } + + if (DMA_CIRCULAR_MODE_ENABLE == init_struct->circular_mode) + { + regval |= DMA_CHXCTL_CMEN; + } + else + { + regval &= ~DMA_CHXCTL_CMEN; + } + + /* DMA channel peripheral select */ + + regval &= ~DMA_CHXCTL_PERIEN_MASK; + regval |= (dmachan->periph << DMA_CHXCTL_PERIEN_SHIFT); + + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Name: gd32_dma_setup + * + * Description: + * Configure DMA before using + * + ****************************************************************************/ + +void gd32_dma_setup(DMA_HANDLE handle, void *arg, uint8_t data_mode) +{ + struct gd32_dma_channel_s *dmachan = (struct gd32_dma_channel_s *)handle; + + gd32_dma_clock_enable(dmachan->dmabase); + + data_mode = 1; + + if (data_mode) + { + dma_single_data_parameter_struct *init_struct = + (dma_single_data_parameter_struct *)arg; + gd32_dma_singlemode_setup(dmachan, init_struct); + } +} + +/**************************************************************************** + * Name: gd32_dma_start + * + * Description: + * Start the DMA transfer + * + * Assumptions: + * - DMA handle allocated by gd32_dma_channel_alloc() + * - No DMA in progress + * + ****************************************************************************/ + +void gd32_dma_start(DMA_HANDLE handle, dma_callback_t callback, void *arg, + uint32_t interrupt) +{ + struct gd32_dma_channel_s *dmachan = (struct gd32_dma_channel_s *)handle; + uint32_t regval; + + DEBUGASSERT(dmachan != NULL); + + DEBUGASSERT(dmachan->chan_num < DMA0_NCHANNELS); + + DEBUGASSERT(dmachan->dmabase == GD32_DMA0_BASE && + dmachan->dmabase == GD32_DMA1_BASE); + + /* Save the callback info. This will be invoked when the DMA completes */ + + dmachan->callback = callback; + dmachan->arg = arg; + + if (interrupt & DMA_INT_MASK) + { + regval = (interrupt & DMA_INT_MASK); + } + else + { + /* If interrupt flag is not set, then set full transfer finish + * interrupt as default + */ + + regval = DMA_CHXCTL_FTFIE; + } + + /* Enable DMA channel and channel interrupt */ + + gd32_channel_interrupt_enable(dmachan->dmabase, dmachan->chan_num, regval); + + gd32_channel_enable(dmachan->dmabase, dmachan->chan_num); +} + +/**************************************************************************** + * Name: gd32_dma_stop + * + * Description: + * Cancel the DMA. After gd32_dma_stop() is called, the DMA channel is + * reset and gd32_dma_setup() must be called before gd32_dma_start() + * can be called again + * + * Assumptions: + * - DMA handle allocated by gd32_dma_channel_alloc() + * + ****************************************************************************/ + +void gd32_dma_stop(DMA_HANDLE handle) +{ + struct gd32_dma_channel_s *dmachan = (struct gd32_dma_channel_s *)handle; + + DEBUGASSERT(dmachan != NULL); + + DEBUGASSERT(dmachan->chan_num < DMA0_NCHANNELS); + + DEBUGASSERT(dmachan->dmabase == GD32_DMA0_BASE && + dmachan->dmabase == GD32_DMA1_BASE); + + gd32_channel_interrupt_disable(dmachan->dmabase, dmachan->chan_num); + gd32_channel_disable(dmachan->dmabase, dmachan->chan_num); +} + +/**************************************************************************** + * Name: gd32_dma_tansnum_get + * + * Description: + * Get the number of remaining data to be transferred by the DMA + * + * Assumptions: + * - DMA handle allocated by gd32_dma_channel_alloc() + * + ****************************************************************************/ + +size_t gd32_dma_tansnum_get(DMA_HANDLE handle) +{ + struct gd32_dma_channel_s *dmachan = (struct gd32_dma_channel_s *)handle; + uint32_t remain_num; + + DEBUGASSERT(dmachan != NULL); + + DEBUGASSERT(dmachan->chan_num < DMA0_NCHANNELS); + + DEBUGASSERT(dmachan->dmabase == GD32_DMA0_BASE && + dmachan->dmabase == GD32_DMA1_BASE); + + remain_num = getreg32(GD32_DMA_CHCNT(dmachan->dmabase, dmachan->chan_num)); + + return (size_t)remain_num; +} + +/**************************************************************************** + * Name: gd32_dma_sample + * + * Description: + * Sample DMA register contents + * + * Assumptions: + * - DMA handle allocated by gd32_dma_channel_alloc() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA_INFO +void gd32_dma_sample(DMA_HANDLE handle, struct gd32_dmaregs_s *regs) +{ + struct gd32_dma_channel_s *dmachan = (struct gd32_dma_channel_s *)handle; + irqstate_t flags; + + DEBUGASSERT(dmachan != NULL); + + DEBUGASSERT(dmachan->chan_num < DMA0_NCHANNELS); + + DEBUGASSERT(dmachan->dmabase == GD32_DMA0_BASE && + dmachan->dmabase == GD32_DMA1_BASE); + + flags = enter_critical_section(); + + regs->intf0 = getreg32(dmachan->dmabase + GD32_DMA_INTF0_OFFSET); + regs->intf1 = getreg32(dmachan->dmabase + GD32_DMA_INTF1_OFFSET); + regs->chctl = getreg32(GD32_DMA_CHCTL(dmachan->dmabase, + dmachan->chan_num)); + regs->chcnt = getreg32(GD32_DMA_CHCNT(dmachan->dmabase, + dmachan->chan_num)); + regs->chpaddr = getreg32(GD32_DMA_CHPADDR(dmachan->dmabase, + dmachan->chan_num)); + regs->chm0addr = getreg32(GD32_DMA_CHM0ADDR(dmachan->dmabase, + dmachan->chan_num)); + regs->chm1addr = getreg32(GD32_DMA_CHM1ADDR(dmachan->dmabase, + dmachan->chan_num)); + regs->chfctl = getreg32(GD32_DMA_CHFCTL(dmachan->dmabase, + dmachan->chan_num)); + + leave_critical_section(flags); +} +#endif + +/**************************************************************************** + * Name: gd32_dma_dump + * + * Description: + * Dump previously sampled DMA register contents + * + * Assumptions: + * - DMA handle allocated by gd32_dma_channel_alloc() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA_INFO +void gd32_dma_dump(DMA_HANDLE handle, const struct gd32_dmaregs_s *regs, + const char *msg) +{ + struct gd32_dma_channel_s *dmachan = (struct gd32_dma_channel_s *)handle; + + DEBUGASSERT(dmachan != NULL); + + dmainfo("DMA Registers: %s\n", msg); + dmainfo(" INTF0: %08x\n", regs->intf0); + dmainfo(" INTF1: %08x\n", regs->intf1); + dmainfo(" CHCTL: %08x\n", regs->chctl); + dmainfo(" CHCNT: %08x\n", regs->chcnt); + dmainfo(" CHPADDR: %08x\n", regs->chpaddr); + dmainfo(" CHM0ADDR: %08x\n", regs->chm0addr); + dmainfo(" CHM1ADDR: %08x\n", regs->chm1addr); + dmainfo(" CHFCTL: %08x\n", regs->chfctl); +} +#endif + +#endif /* GD32_NDMA */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_dma.h b/arch/arm/src/gd32f4/gd32f4xx_dma.h new file mode 100644 index 0000000000..d1a03135aa --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_dma.h @@ -0,0 +1,262 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_dma.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_DMA_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_DMA_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" + +#include "hardware/gd32f4xx_dma.h" + +/* The DMA transfer status definitions */ + +#define DMA_STATUS_ERROR (DMA_INTF_FEEIF | DMA_INTF_SDEIF | DMA_INTF_TAEIF) +#define DMA_STATUS_SUCCESS (DMA_INTF_HTFIF | DMA_INTF_FTFIF) + +#define DMA_INTF_MASK (0x3f) + +#define DMA_INT_MASK (DMA_CHXCTL_SDEIE | DMA_CHXCTL_TAEIE | DMA_CHXCTL_HTFIE | DMA_CHXCTL_FTFIE) + +/* The DMA controllers */ + +#define GD32_DMA0 (GD32_DMA0_BASE) +#define GD32_DMA1 (GD32_DMA1_BASE) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* DMA_HANDLE provides an opaque reference that can be used to represent a + * DMA channel. + */ + +typedef void *DMA_HANDLE; + +/* Description: + * This is the type of the callback that is used to inform the user of the + * completion of the DMA. + * + * Input Parameters: + * handle - Refers to the DMA channel or stream + * status - A bit encoded value that provides the completion status. See + * the DMASTATUS_* definitions above. + * arg - A user-provided value that was provided when gd32_dma_start() + * was called. + */ + +typedef void (*dma_callback_t)(DMA_HANDLE handle, uint16_t status, + void *arg); + +#ifdef CONFIG_DEBUG_DMA_INFO +struct gd32_dmaregs_s +{ + uint32_t intf0; + uint32_t intf1; + uint32_t chctl; + uint32_t chcnt; + uint32_t chpaddr; + uint32_t chm0addr; + uint32_t chm1addr; + uint32_t chfctl; +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* DMA singledata mode initialize struct */ + +typedef struct +{ + uint32_t periph_addr; /* Peripheral base address */ + uint32_t memory0_addr; /* Memory 0 base address */ + uint16_t number; /* Channel transfer number */ + uint8_t periph_inc; /* Peripheral increasing mode */ + uint8_t memory_inc; /* Memory increasing mode */ + uint8_t periph_memory_width; /* Transfer data size of peripheral */ + uint8_t circular_mode; /* DMA circular mode */ + uint8_t direction; /* Channel data transfer direction */ + uint8_t priority; /* Channel priority level */ +} dma_single_data_parameter_struct; + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_dma_channel_alloc + * + * Description: + * Allocate a DMA channel. This function gives the caller mutually + * exclusive access to the DMA channel specified by the 'dmamap' argument. + * Should note that a DMA channel only can be used by on peripheral at the + * time. + * + * If the DMA channel is not available, then gd32_dma_channel_alloc() will + * wait until the holder of the channel relinquishes the channel by calling + * gd32_dma_channel_free(). + * + * Input Parameters: + * periph_req - Identifies the DMA channle is request by which peripheral + * + * Returned Value: + * If periph_req is valid, this function ALWAYS returns a non-NULL + * void* DMA channel handle. + * + ****************************************************************************/ + +DMA_HANDLE gd32_dma_channel_alloc(uint8_t periph_req); + +/**************************************************************************** + * Name: gd32_dma_channel_free + * + * Description: + * Release a DMA channel. If another thread is waiting for this DMA + * channel in a call to gd32_dma_channel_alloc, then this function will + * re-assign the DMA channel to that thread and wake it up. + * NOTE: The 'handle' used in this argument must NEVER be used again + * until gd32_dma_channel_alloc() is called again to re-gain access to + * the channel. + * + * Returned Value: + * None + * + * Assumptions: + * - The caller holds the DMA channel. + * - There is no DMA in progress + * + ****************************************************************************/ + +void gd32_dma_channel_free(DMA_HANDLE handle); + +/**************************************************************************** + * Name: gd32_dma_setup + * + * Description: + * Configure DMA before using + * + ****************************************************************************/ + +void gd32_dma_setup(DMA_HANDLE handle, void *arg, uint8_t data_mode); + +/**************************************************************************** + * Name: gd32_dma_start + * + * Description: + * Start the DMA transfer + * + * Assumptions: + * - DMA handle allocated by gd32_dma_channel_alloc() + * - No DMA in progress + * + ****************************************************************************/ + +void gd32_dma_start(DMA_HANDLE handle, dma_callback_t callback, void *arg, + uint32_t interrupt); + +/**************************************************************************** + * Name: gd32_dma_stop + * + * Description: + * Cancel the DMA. After gd32_dma_stop() is called, the DMA channel is + * reset and gd32_dma_setup() must be called before gd32_dma_start() + * can be called again + * + * Assumptions: + * - DMA handle allocated by gd32_dma_channel_alloc() + * + ****************************************************************************/ + +void gd32_dma_stop(DMA_HANDLE handle); + +/**************************************************************************** + * Name: gd32_dma_tansnum_get + * + * Description: + * Get the number of remaining data to be transferred by the DMA + * + * Assumptions: + * - DMA handle allocated by gd32_dma_channel_alloc() + * + ****************************************************************************/ + +size_t gd32_dma_tansnum_get(DMA_HANDLE handle); + +/**************************************************************************** + * Name: gd32_dma_sample + * + * Description: + * Sample DMA register contents + * + * Assumptions: + * - DMA handle allocated by gd32_dma_channel_alloc() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA_INFO +void gd32_dma_sample(DMA_HANDLE handle, struct gd32_dmaregs_s *regs); +#else +# define gd32_dma_sample(handle,regs) +#endif + +/**************************************************************************** + * Name: gd32_dma_dump + * + * Description: + * Dump previously sampled DMA register contents + * + * Assumptions: + * - DMA handle allocated by gd32_dma_channel_alloc() + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_DMA_INFO +void gd32_dma_dump(DMA_HANDLE handle, const struct gd32_dmaregs_s *regs, + const char *msg); +#else +# define gd32_dma_dump(handle,regs,msg) +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_DMA_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_enet.c b/arch/arm/src/gd32f4/gd32f4xx_enet.c new file mode 100644 index 0000000000..ed9a9bd6d0 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_enet.c @@ -0,0 +1,3878 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_enet.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#define GD32_ENET_NUM 1 + +#if defined(CONFIG_NET) && defined(CONFIG_GD32F4_ENETMAC) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_NET_PKT) +#include +#endif /* CONFIG_NET_PKT */ + +#include "arm_internal.h" + +#include "chip.h" +#include "gd32f4xx_gpio.h" +#include "gd32f4xx_rcu.h" +#include "gd32f4xx_syscfg.h" +#include "gd32f4xx_enet.h" + +#include + +/* GD32_NETHERNET determines the number of physical interfaces + * that will be supported. + */ + +#if GD32_NETHERNET > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* See boards/arm/gd32/gd3240g-eval/README.txt for an explanation of the + * configuration settings. + */ + +#if GD32_NETHERNET > 1 +# error "Logic to support multiple Ethernet interfaces is incomplete" +#endif + +/* Work queue support is required. */ + +#if !defined(CONFIG_SCHED_WORKQUEUE) +# error Work queue support is required +#endif + +/* The low priority work queue is preferred. If it is not enabled, LPWORK + * will be the same as HPWORK. + * + * NOTE: However, the network should NEVER run on the high priority work + * queue! That queue is intended only to service short back end interrupt + * processing that never suspends. Suspending the high priority work queue + * may bring the system to its knees! + */ + +#define ENET_WORK LPWORK + +#if !defined(CONFIG_GD32F4_SYSCFG) +# error "CONFIG_GD32F4_SYSCFG must be defined in the NUTTX config.h" +#endif + +#ifndef CONFIG_GD32F4_PHY_ADDR +# error "CONFIG_GD32F4_PHY_ADDR must be defined in the NUTTX config.h" +#endif + +#if !defined(CONFIG_GD32F4_MII) && !defined(CONFIG_GD32F4_RMII) +# warning "Neither CONFIG_GD32F4_MII nor CONFIG_GD32F4_RMII defined" +#endif + +#if defined(CONFIG_GD32F4_MII) && defined(CONFIG_GD32F4_RMII) +# error "Both CONFIG_GD32F4_MII and CONFIG_GD32F4_RMII defined" +#endif + +#ifdef CONFIG_GD32F4_MII +# if !defined(CONFIG_GD32F4_MII_CKOUT0) && !defined(CONFIG_GD32F4_MII_CKOUT1) && !defined(CONFIG_GD32F4_MII_EXTCLK) +# warning "Neither CONFIG_GD32F4_MII_CKOUT0, CONFIG_GD32F4_MII_CKOUT1, nor CONFIG_GD32F4_MII_EXTCLK defined" +# endif +# if defined(CONFIG_GD32F4_MII_CKOUT0) && defined(CONFIG_GD32F4_MII_CKOUT1) +# error "Both CONFIG_GD32F4_MII_CKOUT0 and CONFIG_GD32F4_MII_CKOUT1 defined" +# endif +#endif + +#ifdef CONFIG_GD32F4_RMII +# if !defined(CONFIG_GD32F4_RMII_CKOUT0) && !defined(CONFIG_GD32F4_RMII_CKOUT1) && !defined(CONFIG_GD32F4_RMII_EXTCLK) +# warning "Neither CONFIG_GD32F4_RMII_CKOUT0, CONFIG_GD32F4_RMII_CKOUT1, nor CONFIG_GD32F4_RMII_EXTCLK defined" +# endif +# if defined(CONFIG_GD32F4_RMII_CKOUT0) && defined(CONFIG_GD32F4_RMII_CKOUT1) +# error "Both CONFIG_GD32F4_RMII_CKOUT0 and CONFIG_GD32F4_RMII_CKOUT1 defined" +# endif +#endif + +#ifdef CONFIG_GD32F4_AUTO_NEGOTIATION +# ifndef CONFIG_GD32F4_PHY_SR +# error "CONFIG_GD32F4_PHY_SR must be defined in the NUTTX config.h" +# endif +# ifdef CONFIG_GD32F4_PHY_SR_ALTCONFIG +# ifndef CONFIG_GD32F4_PHY_SR_ALTMODE +# error "CONFIG_GD32F4_PHY_SR_ALTMODE must be defined in the NUTTX config.h" +# endif +# ifndef CONFIG_GD32F4_PHY_SR_10HD +# error "CONFIG_GD32F4_PHY_SR_10HD must be defined in the NUTTX config.h" +# endif +# ifndef CONFIG_GD32F4_PHY_SR_100HD +# error "CONFIG_GD32F4_PHY_SR_100HD must be defined in the NUTTX config.h" +# endif +# ifndef CONFIG_GD32F4_PHY_SR_10FD +# error "CONFIG_GD32F4_PHY_SR_10FD must be defined in the NUTTX config.h" +# endif +# ifndef CONFIG_GD32F4_PHY_SR_100FD +# error "CONFIG_GD32F4_PHY_SR_100FD must be defined in the NUTTX config.h" +# endif +# else +# ifndef CONFIG_GD32F4_PHY_SR_SPEED +# error "CONFIG_GD32F4_PHY_SR_SPEED must be defined in the NUTTX config.h" +# endif +# ifndef CONFIG_GD32F4_PHY_SR_100M +# error "CONFIG_GD32F4_PHY_SR_100M must be defined in the NUTTX config.h" +# endif +# ifndef CONFIG_GD32F4_PHY_SR_MODE +# error "CONFIG_GD32F4_PHY_SR_MODE must be defined in the NUTTX config.h" +# endif +# ifndef CONFIG_GD32F4_PHY_SR_FULLDUPLEX +# error "CONFIG_GD32F4_PHY_SR_FULLDUPLEX must be defined in the NUTTX config.h" +# endif +# endif +#endif + +/* These definitions are used to enable the PHY interrupts */ + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +# if defined( CONFIG_ETH0_PHY_AM79C874) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_KS8721) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_KSZ8041) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_KSZ8051) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_KSZ8061) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_KSZ8081) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_KSZ90x1) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_DP83848C) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_LAN8720) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_LAN8740) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_LAN8740A) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_LAN8742A) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_DM9161) +# error missing logic +# else +# error "unknown PHY" +# endif +#endif + +#ifdef CONFIG_NET_ICMPv6 +#warning "CONFIG_NET_ICMPv6 is not yet supported" +#endif + +#ifdef CONFIG_NET_IPv6 +# warning "CONFIG_NET_IPv6 is not yet supported" +#endif + +#ifdef CONFIG_GD32F4_ENET_PTP +# warning "CONFIG_GD32F4_ENET_PTP is not yet supported" +#endif + +/* This driver does not use enhanced descriptors. Enhanced descriptors must + * be used, however, if time stamping or and/or IPv4 checksum offload is + * supported. + */ + +#undef CONFIG_GD32F4_ENET_ENHANCEDDESC +#define CONFIG_GD32_ENET_HWCHECKSUM + +/* Add 4 to the configured buffer size to account for the 2 byte checksum + * memory needed at the end of the maximum size packet. Buffer sizes must + * be an even multiple of 4, 8, or 16 bytes (depending on buswidth). We + * will use the 16-byte alignment in all cases. + */ + +#define OPTIMAL_ENET_BUFSIZE ((CONFIG_NET_ETH_PKTSIZE + 4 + 15) & ~15) + +#ifndef CONFIG_GD32F4_ENET_BUFSIZE +# define CONFIG_GD32F4_ENET_BUFSIZE OPTIMAL_ENET_BUFSIZE +#endif + +#if CONFIG_GD32F4_ENET_BUFSIZE > ENET_TDES1_TB1S_MASK +# error "CONFIG_GD32F4_ENET_BUFSIZE is too large" +#endif + +#if (CONFIG_GD32F4_ENET_BUFSIZE & 15) != 0 +# error "CONFIG_GD32F4_ENET_BUFSIZE must be aligned" +#endif + +#if CONFIG_GD32F4_ENET_BUFSIZE != OPTIMAL_ENET_BUFSIZE +# warning "You using an incomplete/untested configuration" +#endif + +#ifndef CONFIG_GD32F4_ENET_NRXDESC +# define CONFIG_GD32F4_ENET_NRXDESC 8 +#endif +#ifndef CONFIG_GD32F4_ENET_NTXDESC +# define CONFIG_GD32F4_ENET_NTXDESC 4 +#endif + +/* We need at least one more free buffer than transmit buffers */ + +#define GD32_ENET_NFREEBUFFERS (CONFIG_GD32F4_ENET_NTXDESC + 1) + +/* Clock configure **********************************************************/ + +/* Set ENET_MAC_PHY_CTL CLR[2:0] bits depending on HCLK setting */ + +#if GD32_HCLK_FREQUENCY >= 20000000 && GD32_HCLK_FREQUENCY < 35000000 +# define ENET_MAC_PHY_CTL_CLR ENET_MDC_HCLK_DIV16 +#elif GD32_HCLK_FREQUENCY >= 35000000 && GD32_HCLK_FREQUENCY < 60000000 +# define ENET_MAC_PHY_CTL_CLR ENET_MDC_HCLK_DIV26 +#elif GD32_HCLK_FREQUENCY >= 60000000 && GD32_HCLK_FREQUENCY < 100000000 +# define ENET_MAC_PHY_CTL_CLR ENET_MDC_HCLK_DIV42 +#elif GD32_HCLK_FREQUENCY >= 100000000 && GD32_HCLK_FREQUENCY < 150000000 +# define ENET_MAC_PHY_CTL_CLR ENET_MDC_HCLK_DIV62 +#elif GD32_HCLK_FREQUENCY >= 150000000 && GD32_HCLK_FREQUENCY <= 240000000 +# define ENET_MAC_PHY_CTL_CLR ENET_MDC_HCLK_DIV102 +#else +# error "GD32_HCLK_FREQUENCY not supportable" +#endif + +/* Timing *******************************************************************/ + +/* TX poll delay = 1 seconds. + * CLK_TCK is the number of clock ticks per second + */ + +#define GD32_WDDELAY (1 * CLK_TCK) + +/* TX timeout = 1 minute */ + +#define GD32_TXTIMEOUT (60 * CLK_TCK) + +/* PHY reset/configuration delays in milliseconds */ + +#define PHY_RESET_DELAY (100) +#define PHY_CONFIG_DELAY (1000) + +/* PHY read/write delays in loop counts */ + +#define PHY_READ_TIMEOUT (0x0004FFFF) +#define PHY_WRITE_TIMEOUT (0x0004FFFF) +#define PHY_RETRY_TIMEOUT (0x0004FFFF) + +/* Register values **********************************************************/ + +/* Clear the MAC_CFG bits that will be setup during MAC initialization + * (or that are cleared unconditionally). Per the reference manual, + * all reserved bits must be retained at their reset value. + * + * ENET_MAC_CFG_REN Bit 2: receiver enable + * ENET_MAC_CFG_TEN Bit 3: transmitter enable + * ENET_MAC_CFG_DFC Bit 4: defferal check + * ENET_MAC_CFG_BOL Bits 5-6: back-off limit + * ENET_MAC_CFG_APCD Bit 7: automatic pad/CRC drop + * ENET_MAC_CFG_RTD Bit 9: retry disable + * ENET_MAC_CFG_IPFCO Bit 10: IP frame checksum offload + * ENET_MAC_CFG_DPM Bit 11: duplex mode + * ENET_MAC_CFG_LBM Bit 12: loopback mode + * ENET_MAC_CFG_ROD Bit 13: receive own disable + * ENET_MAC_CFG_SPD Bit 14: fast ethernet speed + * ENET_MAC_CFG_CSD Bit 16: carrier sense disable + * ENET_MAC_CFG_IGBS Bits 17-19: inter-frame gap bit selection + * ENET_MAC_CFG_JBD Bit 22: jabber disable + * ENET_MAC_CFG_WDD Bit 23: watchdog disable + * ENET_MAC_CFG_TFCD Bits 25: type frame CRC dropping + */ + +#define ENET_MAC_CFG_CLEAR_BITS (ENET_MAC_CFG_REN | \ + ENET_MAC_CFG_TEN | \ + ENET_MAC_CFG_DFC | \ + ENET_MAC_CFG_BOL_MASK | \ + ENET_MAC_CFG_APCD | \ + ENET_MAC_CFG_RTD | \ + ENET_MAC_CFG_IPFCO | \ + ENET_MAC_CFG_DPM | \ + ENET_MAC_CFG_LBM | \ + ENET_MAC_CFG_ROD | \ + ENET_MAC_CFG_SPD | \ + ENET_MAC_CFG_CSD | \ + ENET_MAC_CFG_IGBS_MASK | \ + ENET_MAC_CFG_JBD | \ + ENET_MAC_CFG_WDD | \ + ENET_MAC_CFG_TFCD) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ENET_MAC_CFG_REN receiver enable 0 (disabled) + * ENET_MAC_CFG_TEN transmitter enable 0 (disabled) + * ENET_MAC_CFG_DFC deferral check 0 (disabled) + * ENET_MAC_CFG_BOL back-off limit 0 (10) + * ENET_MAC_CFG_APCD automatic pad/CRC drop 0 (disabled) + * ENET_MAC_CFG_RTD retry disable 1 (disabled) + * ENET_MAC_CFG_IPFCO IP frame checksum offload Depends on + * CONFIG_GD32_ENET_HWCHECKSUM + * ENET_MAC_CFG_LBM loopback mode 0 (disabled) + * ENET_MAC_CFG_ROD receive own disable 0 (enabled) + * ENET_MAC_CFG_CSD carrier sense disable 0 (enabled) + * ENET_MAC_CFG_IGBS inter-frame gap bit selection 0 (96 bits) + * ENET_MAC_CFG_JBD jabber disable 0 (enabled) + * ENET_MAC_CFG_WDD watchdog disable 0 (enabled) + * ENET_MAC_CFG_TFCD type frame CRC dropping 0 (disabled) + * + * The following are set conditioinally based on mode and speed. + * + * ENET_MAC_CFG_DPM duplex mode Depends on priv->fduplex + * ENET_MAC_CFG_SPD fast Ethernet speed Depends on priv->mbps100 + */ + +#ifdef CONFIG_GD32_ENET_HWCHECKSUM + #define ENET_MAC_CFG_SET_BITS (ENET_BACKOFFLIMIT_10 | \ + ENET_MAC_CFG_RTD | \ + ENET_MAC_CFG_IPFCO | \ + ENET_MAC_CFG_IGBS(96)) +#else + #define ENET_MAC_CFG_SET_BITS (ENET_BACKOFFLIMIT_10 | \ + ENET_MAC_CFG_RTD | \ + ENET_MAC_CFG_IGBS(96)) +#endif + +/* Clear the MAC_FRMF bits that will be setup during MAC initialization + * (or that are cleared unconditionally). Per the reference manual, + * all reserved bits must be retained at their reset value. + * + * ENET_MAC_FRMF_PM Bit 0: promiscuous mode + * ENET_MAC_FRMF_HUF Bit 1: hash unicast filter + * ENET_MAC_FRMF_HMF Bit 2: hash multicast filter + * ENET_MAC_FRMF_DAIFLT Bit 3: destination address inverse filtering + * enable + * ENET_MAC_FRMF_MFD Bit 4: multicast filter disable + * ENET_MAC_FRMF_BFRMD Bit 5: broadcast frame disable + * ENET_MAC_FRMF_PCFRM Bits 6-7: pass control frames + * ENET_MAC_FRMF_SAIFLT Bit 8: source address inverse filtering + * ENET_MAC_FRMF_SAFLT Bit 9: source address filter + * ENET_MAC_FRMF_HPFLT Bit 10: hash or perfect filter + * ENET_MAC_FRMF_FAR Bit 31: receive all frames + */ + +#define ENET_MAC_FRMF_CLEAR_BITS (ENET_MAC_FRMF_PM | \ + ENET_MAC_FRMF_HUF | \ + ENET_MAC_FRMF_HMF | \ + ENET_MAC_FRMF_DAIFLT | \ + ENET_MAC_FRMF_MFD | \ + ENET_MAC_FRMF_BFRMD | \ + ENET_MAC_FRMF_PCFRM_MASK | \ + ENET_MAC_FRMF_SAIFLT | \ + ENET_MAC_FRMF_SAFLT | \ + ENET_MAC_FRMF_HPFLT | \ + ENET_MAC_FRMF_FAR) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ENET_MAC_FRMF_HUF hash unicast filter 0 (perfect dest filtering) + * ENET_MAC_FRMF_HMF hash multicast filter 0 (perfect dest filtering) + * ENET_MAC_FRMF_DAIFLT destination address 0 (normal) + * inverse filtering + * enable inverse filtering + * ENET_MAC_FRMF_MFD multicast filter disable 0 (depends on + * ENET_MAC_FRMF_HMF bit) + * ENET_MAC_FRMF_BFRMD broadcast frame disable 0 (enabled) + * ENET_MAC_FRMF_PCFRM pass control frames 1 (block all but PAUSE) + * ENET_MAC_FRMF_SAIFLT source address inverse 0 (not used) + * filtering + * ENET_MAC_FRMF_SAFLT source address filter 0 (disabled) + * ENET_MAC_FRMF_HPFLT hash or perfect filter 0 (Only matching frames + * passed) + * ENET_MAC_FRMF_FAR receive all frames 0 (disabled) + */ + +#ifdef CONFIG_NET_PROMISCUOUS + #define ENET_MAC_FRMF_SET_BITS (ENET_PCFRM_PREVENT_PAUSEFRAME | ENET_MAC_FRMF_PM) +#else + #define ENET_MAC_FRMF_SET_BITS (ENET_PCFRM_PREVENT_PAUSEFRAME) +#endif + +/* Clear the MAC_FCTL bits that will be setup during MAC initialization (or + * that are cleared unconditionally). Per the reference manual, all reserved + * bits must be retained at their reset value. + * + * ENET_MAC_FCTL_FLCBBKPA Bit 0: flow control busy(in full duplex mode) + * /backpressure activate(in half duplex + * mode) + * ENET_MAC_FCTL_TFCEN Bit 1: transmit flow control enable + * ENET_MAC_FCTL_RFCEN Bit 2: receive flow control enable + * ENET_MAC_FCTL_UPFDT Bit 3: unicast pause frame detect + * ENET_MAC_FCTL_PLTS Bits 4-5: pause low threshold + * ENET_MAC_FCTL_DZQP Bit 7: disable zero-quanta pause + * ENET_MAC_FCTL_PTM Bits 16-31: pause time + */ + +#define ENET_MAC_FCTL_CLEAR_MASK (ENET_MAC_FCTL_FLCBBKPA | \ + ENET_MAC_FCTL_TFCEN | \ + ENET_MAC_FCTL_RFCEN | \ + ENET_MAC_FCTL_UPFDT | \ + ENET_MAC_FCTL_PLTS_MASK | \ + ENET_MAC_FCTL_DZQP | \ + ENET_MAC_FCTL_PTM_MASK) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ENET_MAC_FCTL_FLCBBKPA flow control busy(in full 0 (no pause + * duplex mode)/backpressure control frame) + * activate(in half duplex mode) + * ENET_MAC_FCTL_TFCEN transmit flow control enable 0 (disabled) + * ENET_MAC_FCTL_RFCEN receive flow control enable 0 (disabled) + * ENET_MAC_FCTL_UPFDT unicast pause frame detect 0 (disabled) + * ENET_MAC_FCTL_PLTS pause low threshold 0 (pause time - 4) + * ENET_MAC_FCTL_DZQP disable zero-quanta pause 1 (disabled) + * ENET_MAC_FCTL_PTM pause time 0 + */ + +#define ENET_MAC_FCTL_SET_MASK (ENET_PAUSETIME_MINUS4 | ENET_MAC_FCTL_DZQP) + +/* Clear the DMA_CTL bits that will be setup during MAC initialization (or + * that are cleared unconditionally). Per the reference manual, all reserved + * bits must be retained at their reset value. + * + * ENET_DMA_CTL_SRE Bit 1: start/stop receive enable + * ENET_DMA_CTL_OSF Bit 2: operate on second frame + * ENET_DMA_CTL_RTHC Bits 3-4: receive threshold control + * ENET_DMA_CTL_FUF Bit 6: forward undersized good frames + * ENET_DMA_CTL_FERF Bit 7: forward error frames + * ENET_DMA_CTL_STE Bit 13: start/stop transmission enable + * ENET_DMA_CTL_TTHC Bits 14-16: transmit threshold control + * ENET_DMA_CTL_FTF Bit 20: flush transmit FIFO + * ENET_DMA_CTL_TSFD Bit 21: transmit store-and-forward + * ENET_DMA_CTL_DAFRF Bit 24: disable flushing of received frames + * ENET_DMA_CTL_RSFD Bit 25: receive store-and-forward + * ENET_DMA_CTL_DTCERFD Bit 26: dropping of TCP/IP checksum error + * frames disable + */ + +#define ENET_DMA_CTL_CLEAR_MASK (ENET_DMA_CTL_SRE | \ + ENET_DMA_CTL_OSF | \ + ENET_DMA_CTL_RTHC_MASK | \ + ENET_DMA_CTL_FUF | \ + ENET_DMA_CTL_FERF | \ + ENET_DMA_CTL_STE | \ + ENET_DMA_CTL_TTHC_MASK | \ + ENET_DMA_CTL_FTF | \ + ENET_DMA_CTL_TSFD | \ + ENET_DMA_CTL_DAFRF | \ + ENET_DMA_CTL_RSFD | \ + ENET_DMA_CTL_DTCERFD) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ENET_DMA_CTL_SRE start/stop receive 0 (disabled) + * enable + * ENET_DMA_CTL_OSF operate on second frame 0 (disabled) + * ENET_DMA_CTL_RTHC receive threshold 0 (64 bytes) + * control + * ENET_DMA_CTL_FUF forward undersized 0 (disabled) + * good frames + * ENET_DMA_CTL_FERF forward error frames 0 (disabled) + * ENET_DMA_CTL_STE start/stop trans- 0 (disabled) + * -mission enable + * ENET_DMA_CTL_TTHC transmit threshold 0 (64 bytes) + * control + * ENET_DMA_CTL_FTF flush transmit FIFO 0 (disabled) + * ENET_DMA_CTL_TSFD transmit store-and depends on + * -forward CONFIG_GD32_ENET_HWCHECKSUM + * ENET_DMA_CTL_DAFRF disable flushing of 0 (enabled) + * received frames + * ENET_DMA_CTL_RSFD receive store-and epends on + * -forward CONFIG_GD32_ENET_HWCHECKSUM + * ENET_DMA_CTL_DTCERFD dropping of TCP/IP depends on + * checksum error CONFIG_GD32_ENET_HWCHECKSUM + * frames disable + * + * When the checksum offload feature is enabled, we need to enable the Store + * and Forward mode: the store and forward guarantee that a whole frame is + * stored in the FIFO, so the MAC can insert/verify the checksum, if the + * checksum is OK the DMA can handle the frame otherwise the frame is dropped + */ + +#ifdef CONFIG_GD32_ENET_HWCHECKSUM + #define ENET_DMA_CTL_SET_MASK (ENET_RX_THRESHOLD_64BYTES | \ + ENET_TX_THRESHOLD_64BYTES | \ + ENET_DMA_CTL_TSFD | \ + ENET_DMA_CTL_RSFD) +#else + #define DMAOMR_SET_MASK (ENET_RX_THRESHOLD_64BYTES | \ + ENET_TX_THRESHOLD_64BYTES | \ + ENET_DMA_CTL_DTCERFD) +#endif + +/* Clear the DMA_BCTL bits that will be setup during MAC initialization (or + * that are cleared unconditionally). Per the reference manual, all reserved + * bits must be retained at their reset value. + * + * ENET_DMA_BCTL_SWR Bit 0: software reset + * ENET_DMA_BCTL_DAB Bit 1: DMA arbitration + * ENET_DMA_BCTL_DPSL Bits 2-6: descriptor skip length + * ENET_DMA_BCTL_DFM Bit 7: descriptor format mode + * ENET_DMA_BCTL_PGBL Bits 8-13: programmable burst length + * ENET_DMA_BCTL_RTPR Bits 14-15: RX TX priority ratio + * ENET_DMA_BCTL_FB Bit 16: fixed burst + * ENET_DMA_BCTL_RXDP Bits 17-22: RX DMA PGBL + * ENET_DMA_BCTL_UIP Bit 23: use independent PGBL + * ENET_DMA_BCTL_FPBL Bit 24: four times PGBL mode + * ENET_DMA_BCTL_AA Bit 25: address-aligned + * ENET_DMA_BCTL_MB Bit 26: mixed burst + */ + +#define ENET_DMA_BCTL_CLEAR_MASK (ENET_DMA_BCTL_SWR | \ + ENET_DMA_BCTL_DAB | \ + ENET_DMA_BCTL_DPSL_MASK | \ + ENET_DMA_BCTL_DFM | \ + ENET_DMA_BCTL_PGBL_MASK | \ + ENET_DMA_BCTL_RTPR_MASK | \ + ENET_DMA_BCTL_FB | \ + ENET_DMA_BCTL_RXDP_MASK | \ + ENET_DMA_BCTL_UIP | \ + ENET_DMA_BCTL_FPBL | \ + ENET_DMA_BCTL_AA | \ + ENET_DMA_BCTL_MB) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ENET_DMA_BCTL_SWR software reset 0 (no reset) + * ENET_DMA_BCTL_DAB DMA arbitration 0 (round robin) + * ENET_DMA_BCTL_DPSL descriptor skip 0 + * length + * ENET_DMA_BCTL_DFM descriptor format depends on + * mode CONFIG_GD32F4_ENET_ENHANCEDDESC + * ENET_DMA_BCTL_PGBL programmable burst 32 beats + * length + * ENET_DMA_BCTL_RTPR RX TX priority ratio 2:1 + * ENET_DMA_BCTL_FB fixed burst 1 (enabled) + * ENET_DMA_BCTL_RXDP RX DMA PGBL 32 beats + * ENET_DMA_BCTL_UIP use independent PGBL 1 (enabled) + * ENET_DMA_BCTL_FPBL four times PGBL mode 0 (disabled) + * ENET_DMA_BCTL_AA address-aligned 1 (enabled) + * ENET_DMA_BCTL_MB mixed burst 0 (disabled) + */ + +#ifdef CONFIG_GD32F4_ENET_ENHANCEDDESC + #define ENET_DMA_BCTL_SET_MASK (ENET_DMA_BCTL_DPSL(0) | \ + ENET_DMA_BCTL_PGBL(32) | \ + ENET_DMA_BCTL_DFM | \ + ENET_ARBITRATION_RXTX_2_1 | \ + ENET_DMA_BCTL_FB | \ + ENET_DMA_BCTL_RXDP(32) | \ + ENET_DMA_BCTL_UIP | \ + ENET_DMA_BCTL_AA) +#else + #define ENET_DMA_BCTL_SET_MASK (ENET_DMA_BCTL_DPSL(0) | \ + ENET_DMA_BCTL_PGBL(32) | \ + ENET_ARBITRATION_RXTX_2_1 | \ + ENET_DMA_BCTL_FB | \ + ENET_DMA_BCTL_RXDP(32) | \ + ENET_DMA_BCTL_UIP | \ + ENET_DMA_BCTL_AA) +#endif + +/* Interrupt bit sets *******************************************************/ + +/* All interrupts in the normal and abnormal interrupt summary. Early + * transmit interrupt (ETIE) is excluded from the abnormal set because it + * causes too many interrupts and is not interesting. + */ + +#define ENET_DMAINT_NORMAL (ENET_DMA_INTEN_TIE | \ + ENET_DMA_INTEN_TBUIE | \ + ENET_DMA_INTEN_RIE | \ + ENET_DMA_INTEN_ERIE) + +#define ENET_DMAINT_ABNORMAL (ENET_DMA_INTEN_TPSIE | \ + ENET_DMA_INTEN_TJTIE | \ + ENET_DMA_INTEN_ROIE | \ + ENET_DMA_INTEN_TUIE | \ + ENET_DMA_INTEN_RBUIE | \ + ENET_DMA_INTEN_RPSIE | \ + ENET_DMA_INTEN_RWTIE | \ + /* ENET_DMA_INTEN_ETIE | */ \ + ENET_DMA_INTEN_FBEIE) + +/* Normal receive, transmit, error interrupt enable bit sets */ + +#define ENET_DMA_INTEN_RECV_ENABLE (ENET_DMA_INTEN_NIE | ENET_DMA_INTEN_RIE) +#define ENET_DMA_INTEN_XMIT_ENABLE (ENET_DMA_INTEN_NIE | ENET_DMA_INTEN_TIE) +#define ENET_DMA_INTEN_XMIT_DISABLE (ENET_DMA_INTEN_TIE) + +#ifdef CONFIG_DEBUG_NET +# define ENET_DMA_INTEN_ERROR_ENABLE (ENET_DMA_INTEN_AIE | ENET_DMAINT_ABNORMAL) +#else +# define ENET_DMA_INTEN_ERROR_ENABLE (0) +#endif + +/* Helpers ******************************************************************/ + +/* This is a helper pointer for accessing the contents of the Ethernet + * header + */ + +#define BUF ((struct eth_hdr_s *)priv->dev.d_buf) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The gd32_enet_mac_s encapsulates all state information for a single + * hardware interface + */ + +struct gd32_enet_mac_s +{ + uint8_t ifup : 1; /* true:ifup false:ifdown */ + uint8_t mbps100 : 1; /* 100MBps operation (vs 10 MBps) */ + uint8_t fduplex : 1; /* Full (vs. half) duplex */ + struct wdog_s txpoll; /* TX poll timer */ + struct wdog_s txtimeout; /* TX timeout timer */ + struct work_s irqwork; /* For deferring interrupt work to the work queue */ + struct work_s pollwork; /* For deferring poll work to the work queue */ + + /* This holds the information visible to the NuttX network */ + + struct net_driver_s dev; /* Interface understood by the network */ + + /* Used to track transmit and receive descriptors */ + + struct enet_txdesc_s *txhead; /* Next available TX descriptor */ + struct enet_rxdesc_s *rxhead; /* Next available RX descriptor */ + + struct enet_txdesc_s *txtail; /* First "in_flight" TX descriptor */ + struct enet_rxdesc_s *rxcurr; /* First RX descriptor of the segment */ + uint16_t segments; /* RX segment count */ + uint16_t inflight; /* Number of TX transfers "in_flight" */ + sq_queue_t freeb; /* The free buffer list */ + + /* Descriptor allocations */ + + struct enet_rxdesc_s rxtable[CONFIG_GD32F4_ENET_NRXDESC]; + struct enet_txdesc_s txtable[CONFIG_GD32F4_ENET_NTXDESC]; + + /* Buffer allocations */ + + uint8_t rxbuffer[CONFIG_GD32F4_ENET_NRXDESC * + CONFIG_GD32F4_ENET_BUFSIZE]; + uint8_t alloc[GD32_ENET_NFREEBUFFERS * CONFIG_GD32F4_ENET_BUFSIZE]; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct gd32_enet_mac_s g_enet_mac[GD32_NETHERNET]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Register operations ******************************************************/ + +static void gd32_enet_clock_enable(void); + +#define gd32_reg_read(addr) getreg32(addr) +#define gd32_reg_write(val,addr) putreg32(val,addr) + +/* Free buffer management */ + +static void gd32_buf_init(struct gd32_enet_mac_s *priv); +static inline uint8_t *gd32_buf_alloc(struct gd32_enet_mac_s *priv); +static inline void gd32_buf_free(struct gd32_enet_mac_s *priv, + uint8_t *buffer); +static inline bool gd32_is_free_buf(struct gd32_enet_mac_s *priv); + +/* Common TX logic */ + +static int gd32_transmit(struct gd32_enet_mac_s *priv); +static int gd32_tx_poll(struct net_driver_s *dev); +static void gd32_do_poll(struct gd32_enet_mac_s *priv); + +/* Interrupt handling */ + +static void gd32_interrupt_enable(struct gd32_enet_mac_s *priv, + uint32_t ierbit); +static void gd32_interrupt_disable(struct gd32_enet_mac_s *priv, + uint32_t ierbit); + +static void gd32_free_segment(struct gd32_enet_mac_s *priv, + struct enet_rxdesc_s *rxfirst, + int segments); +static int gd32_receive_frame(struct gd32_enet_mac_s *priv); +static void gd32_receive(struct gd32_enet_mac_s *priv); +static void gd32_freeframe(struct gd32_enet_mac_s *priv); +static void gd32_tx_done(struct gd32_enet_mac_s *priv); + +static void gd32_interrupt_work(void *arg); +static int gd32_interrupt(int irq, void *context, void *arg); + +/* Watchdog timer expirations */ + +static void gd32_txtimeout_work(void *arg); +static void gd32_tx_timeout_expiry(wdparm_t arg); + +static void gd32_poll_work(void *arg); +static void gd32_poll_expiry(wdparm_t arg); + +/* NuttX callback functions */ + +static int gd32_ifup(struct net_driver_s *dev); +static int gd32_ifdown(struct net_driver_s *dev); + +static void gd32_txavail_work(void *arg); +static int gd32_txavail(struct net_driver_s *dev); + +#if defined(CONFIG_NET_MCASTGROUP) +static int gd32_add_mac(struct net_driver_s *dev, const uint8_t *mac); +#endif +#ifdef CONFIG_NET_MCASTGROUP +static int gd32_remove_mac(struct net_driver_s *dev, + const uint8_t *mac); +#endif +#ifdef CONFIG_NETDEV_IOCTL +static int gd32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); +#endif + +/* Descriptor Initialization */ + +static void gd32_txdes_chain_init(struct gd32_enet_mac_s *priv); +static void gd32_rxdes_chain_init(struct gd32_enet_mac_s *priv); + +/* PHY Initialization */ + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int gd32_phy_interrupt_enable(struct gd32_enet_mac_s *priv); +#endif +#if defined(CONFIG_GD32F4_AUTO_NEGOTIATION) || defined(CONFIG_NETDEV_PHY_IOCTL) +static int gd32_phy_read(uint16_t phydevaddr, uint16_t phyregaddr, + uint16_t *value); +#endif +static int gd32_phy_write(uint16_t phydevaddr, uint16_t phyregaddr, + uint16_t value); +static int gd32_phy_init(struct gd32_enet_mac_s *priv); + +/* MAC/DMA Initialization */ + +#ifdef CONFIG_GD32F4_MII +static inline void gd32_select_mii(void); +#endif +#ifdef CONFIG_GD32F4_RMII +static inline void gd32_select_rmii(void); +#endif +static inline void gd32_enet_gpio_config(struct gd32_enet_mac_s *priv); +static int gd32_enet_reset(struct gd32_enet_mac_s *priv); +static int gd32_mac_config(struct gd32_enet_mac_s *priv); +static void gd32_mac_address(struct gd32_enet_mac_s *priv); +static int gd32_mac_enable(struct gd32_enet_mac_s *priv); +static int gd32_enet_config(struct gd32_enet_mac_s *priv); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: gd32_enet_clock_enable + * + * Description: + * + * Enable ENET clock + * + ****************************************************************************/ + +static void gd32_enet_clock_enable(void) +{ + uint32_t rcu_en; + uint32_t regaddr; + + rcu_en = RCU_AHB1EN_ENETEN | RCU_AHB1EN_ENETTXEN | RCU_AHB1EN_ENETRXEN; + +#ifdef CONFIG_GD32F4_ENET_PTP + /* Enable PTP clock */ + + rcu_en |= RCU_AHB1EN_ENETPTPEN; +#endif + + regaddr = GD32_RCU_AHB1EN; + + /* Check clock if alreay enable. */ + + if (rcu_en != (rcu_en & getreg32(regaddr))) + { + /* Enable/disable AHB clock for ENET */ + + modifyreg32(regaddr, 0, rcu_en); + } +} + +/**************************************************************************** + * Function: gd32_buf_init + * + * Description: + * Initialize the free buffer list. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called during early driver initialization before Ethernet interrupts + * are enabled. + * + ****************************************************************************/ + +static void gd32_buf_init(struct gd32_enet_mac_s *priv) +{ + uint8_t *buffer; + int i; + + /* Initialize the head of the free buffer list */ + + sq_init(&priv->freeb); + + /* Add all of the pre-allocated buffers to the free buffer list */ + + for (i = 0, buffer = priv->alloc; + i < GD32_ENET_NFREEBUFFERS; + i++, buffer += CONFIG_GD32F4_ENET_BUFSIZE) + { + sq_addlast((sq_entry_t *)buffer, &priv->freeb); + } +} + +/**************************************************************************** + * Function: gd32_buf_alloc + * + * Description: + * Allocate one buffer from the free buffer list. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * Pointer to the allocated buffer on success; NULL on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static inline uint8_t *gd32_buf_alloc(struct gd32_enet_mac_s *priv) +{ + /* Allocate a buffer by returning the head of the free buffer list */ + + return (uint8_t *)sq_remfirst(&priv->freeb); +} + +/**************************************************************************** + * Function: gd32_buf_free + * + * Description: + * Return a buffer to the free buffer list. + * + * Input Parameters: + * priv - Reference to the driver state structure + * buffer - A pointer to the buffer to be freed + * + * Returned Value: + * None + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static inline void gd32_buf_free(struct gd32_enet_mac_s *priv, + uint8_t *buffer) +{ + /* Free the buffer by adding it to the end of the free buffer list */ + + sq_addlast((sq_entry_t *)buffer, &priv->freeb); +} + +/**************************************************************************** + * Function: gd32_is_free_buf + * + * Description: + * Return TRUE if the free buffer list is not empty. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * True if there are one or more buffers in the free buffer list; + * false if the free buffer list is empty + * + * Assumptions: + * None. + * + ****************************************************************************/ + +static inline bool gd32_is_free_buf(struct gd32_enet_mac_s *priv) +{ + /* Return TRUE if the free buffer list is not empty */ + + return !sq_empty(&priv->freeb); +} + +/**************************************************************************** + * Function: gd32_transmit + * + * Description: + * Start hardware transmission. Called either from the txdone interrupt + * handling or from watchdog based polling. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int gd32_transmit(struct gd32_enet_mac_s *priv) +{ + struct enet_txdesc_s *txdesc; + struct enet_txdesc_s *txfirst; + + /* The internal (optimal) network buffer size may be configured to be + * larger than the Ethernet buffer size. + */ + +#if OPTIMAL_ENET_BUFSIZE > CONFIG_GD32F4_ENET_BUFSIZE + uint8_t *buffer; + int bufcount; + int lastsize; + int i; +#endif + + /* Verify that the hardware is ready to send another packet. If we get + * here, then we are committed to sending a packet; Higher level logic + * must have assured that there is no transmission in progress. + */ + + txdesc = priv->txhead; + txfirst = txdesc; + + ninfo("d_len: %d d_buf: %p txhead: %p tdes0: %08" PRIx32 "\n", + priv->dev.d_len, priv->dev.d_buf, txdesc, txdesc->tdes0); + + DEBUGASSERT(txdesc && (txdesc->tdes0 & ENET_TDES0_DAV) == 0); + + /* Is the size to be sent greater than the size of the Ethernet buffer? */ + + DEBUGASSERT(priv->dev.d_len > 0 && priv->dev.d_buf != NULL); + +#if OPTIMAL_ENET_BUFSIZE > CONFIG_GD32F4_ENET_BUFSIZE + if (priv->dev.d_len > CONFIG_GD32F4_ENET_BUFSIZE) + { + /* Yes... how many buffers will be need to send the packet? */ + + bufcount = (priv->dev.d_len + (CONFIG_GD32F4_ENET_BUFSIZE - 1)) / + CONFIG_GD32F4_ENET_BUFSIZE; + lastsize = priv->dev.d_len - (bufcount - 1) * + CONFIG_GD32F4_ENET_BUFSIZE; + + ninfo("bufcount: %d lastsize: %d\n", bufcount, lastsize); + + /* Set the first segment bit in the first TX descriptor */ + + txdesc->tdes0 |= ENET_TDES0_FSG; + + /* Set up all but the last TX descriptor */ + + buffer = priv->dev.d_buf; + + for (i = 0; i < bufcount; i++) + { + /* This could be a normal event but the design does not handle it */ + + DEBUGASSERT((txdesc->tdes0 & ENET_TDES0_DAV) == 0); + + /* Set the Buffer1 address pointer */ + + txdesc->tdes2 = (uint32_t)buffer; + + /* Set the buffer size in all TX descriptors */ + + if (i == (bufcount - 1)) + { + /* This is the last segment. Set the last segment bit in the + * last TX descriptor and ask for an interrupt when this + * segment transfer completes. + */ + + txdesc->tdes0 |= (ENET_TDES0_LSG | ENET_TDES0_INTC); + + /* This segment is, most likely, of fractional buffersize */ + + txdesc->tdes1 = lastsize; + buffer += lastsize; + } + else + { + /* This is not the last segment. We don't want an interrupt + * when this segment transfer completes. + */ + + txdesc->tdes0 &= ~ENET_TDES0_INTC; + + /* The size of the transfer is the whole buffer */ + + txdesc->tdes1 = CONFIG_GD32F4_ENET_BUFSIZE; + buffer += CONFIG_GD32F4_ENET_BUFSIZE; + } + + /* Give the descriptor to DMA */ + + txdesc->tdes0 |= ENET_TDES0_DAV; + txdesc = (struct enet_txdesc_s *)txdesc->tdes3; + } + } + else +#endif + { + /* The single descriptor is both the first and last segment. And we do + * want an interrupt when the transfer completes. + */ + + txdesc->tdes0 |= (ENET_TDES0_FSG | ENET_TDES0_LSG | ENET_TDES0_INTC); + + /* Set frame size */ + + DEBUGASSERT(priv->dev.d_len <= CONFIG_NET_ETH_PKTSIZE); + txdesc->tdes1 = priv->dev.d_len; + + /* Set the Buffer1 address pointer */ + + txdesc->tdes2 = (uint32_t)priv->dev.d_buf; + + /* Set DAV bit of the TX descriptor tdes0. This gives the buffer to + * Ethernet DMA + */ + + txdesc->tdes0 |= ENET_TDES0_DAV; + + /* Point to the next available TX descriptor */ + + txdesc = (struct enet_txdesc_s *)txdesc->tdes3; + } + + /* Remember where we left off in the TX descriptor chain */ + + priv->txhead = txdesc; + + /* Detach the buffer from priv->dev structure. That buffer is now + * "in-flight". + */ + + priv->dev.d_buf = NULL; + priv->dev.d_len = 0; + + /* If there is no other TX buffer, in flight, then remember the location + * of the TX descriptor. This is the location to check for TX done events. + */ + + if (!priv->txtail) + { + DEBUGASSERT(priv->inflight == 0); + priv->txtail = txfirst; + } + + /* Increment the number of TX transfer in-flight */ + + priv->inflight++; + + ninfo("txhead: %p txtail: %p inflight: %d\n", + priv->txhead, priv->txtail, priv->inflight); + + /* If all TX descriptors are in-flight, then we have to disable receive + * interrupts too. This is because receive events can trigger more + * un-stoppable transmit events. + */ + + if (priv->inflight >= CONFIG_GD32F4_ENET_NTXDESC) + { + gd32_interrupt_disable(priv, ENET_DMA_INTEN_RIE); + } + + /* Check if the TX Buffer unavailable flag is set */ + + if ((gd32_reg_read(GD32_ENET_DMA_STAT) & ENET_DMA_INTEN_TBUIE) != 0) + { + /* Clear TX Buffer unavailable flag */ + + gd32_reg_write(ENET_DMA_INTEN_TBUIE, GD32_ENET_DMA_STAT); + + /* Resume DMA transmission */ + + gd32_reg_write(1, GD32_ENET_DMA_TPEN); + } + + /* Enable TX interrupts */ + + gd32_interrupt_enable(priv, ENET_DMA_INTEN_TIE); + + /* Setup the TX timeout watchdog (perhaps restarting the timer) */ + + wd_start(&priv->txtimeout, GD32_TXTIMEOUT, + gd32_tx_timeout_expiry, (wdparm_t)priv); + return OK; +} + +/**************************************************************************** + * Function: gd32_tx_poll + * + * Description: + * The transmitter is available, check if the network has any outgoing + * packets ready to send. This is a callback from devif_poll(). + * devif_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. When the preceding TX packet send timesout and the interface is reset + * 3. During normal TX polling + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int gd32_tx_poll(struct net_driver_s *dev) +{ + struct gd32_enet_mac_s *priv = + (struct gd32_enet_mac_s *)dev->d_private; + + DEBUGASSERT(priv->dev.d_buf != NULL); + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + /* Look up the destination MAC address and add it to the Ethernet + * header. + */ + +#ifdef CONFIG_NET_IPv4 + + arp_out(&priv->dev); + +#endif /* CONFIG_NET_IPv4 */ + + if (!devif_loopback(&priv->dev)) + { + /* Send the packet */ + + gd32_transmit(priv); + DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL); + + /* Check if the next TX descriptor is owned by the Ethernet DMA or + * CPU. We cannot perform the TX poll if we are unable to accept + * another packet for transmission. + * + * In a race condition, ENET_TDES0_DAV may be cleared BUT still + * not available because gd32_freeframe() has not yet run. If + * gd32_freeframe() has run, the buffer1 pointer (tdes2) will be + * nullified (and inflight should be < CONFIG_gd32_ETH_NTXDESC). + */ + + if ((priv->txhead->tdes0 & ENET_TDES0_DAV) != 0 || + priv->txhead->tdes2 != 0) + { + /* We have to terminate the poll if we have no more descriptors + * available for another transfer. + */ + + return -EBUSY; + } + + /* We have the descriptor, we can continue the poll. Allocate a new + * buffer for the poll. + */ + + dev->d_buf = gd32_buf_alloc(priv); + + /* We can't continue the poll if we have no buffers */ + + if (dev->d_buf == NULL) + { + /* Terminate the poll. */ + + return -ENOMEM; + } + } + } + + /* If zero is returned, the polling will continue until all connections + * have been examined. + */ + + return 0; +} + +/**************************************************************************** + * Function: gd32_do_poll + * + * Description: + * The function is called in order to perform an out-of-sequence TX poll. + * This is done: + * + * 1. After completion of a transmission (gd32_tx_done), + * 2. When new TX data is available (gd32_txavail_process), and + * 3. After a TX timeout to restart the sending process + * (gd32_txtimeout_process). + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void gd32_do_poll(struct gd32_enet_mac_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + + /* Check if the next TX descriptor is owned by the Ethernet DMA or + * CPU. We cannot perform the TX poll if we are unable to accept + * another packet for transmission. + * + * In a race condition, ENET_TDES0_DAV may be cleared BUT still + * not available because gd32_freeframe() has not yet run. If + * gd32_freeframe() has run, the buffer1 pointer (tdes2) will be + * nullified (and inflight should be < CONFIG_gd32_ETH_NTXDESC). + */ + + if ((priv->txhead->tdes0 & ENET_TDES0_DAV) == 0 && + priv->txhead->tdes2 == 0) + { + /* If we have the descriptor, then poll the network for new XMIT data. + * Allocate a buffer for the poll. + */ + + DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL); + dev->d_buf = gd32_buf_alloc(priv); + + /* We can't poll if we have no buffers */ + + if (dev->d_buf) + { + devif_poll(dev, gd32_tx_poll); + + /* We will, most likely end up with a buffer to be freed. But it + * might not be the same one that we allocated above. + */ + + if (dev->d_buf) + { + DEBUGASSERT(dev->d_len == 0); + gd32_buf_free(priv, dev->d_buf); + dev->d_buf = NULL; + } + } + } +} + +/**************************************************************************** + * Function: gd32_interrupt_enable + * + * Description: + * Enable a "normal" interrupt + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void gd32_interrupt_enable(struct gd32_enet_mac_s *priv, + uint32_t ierbit) +{ + uint32_t regval; + + /* Enable the specified "normal" interrupt */ + + regval = gd32_reg_read(GD32_ENET_DMA_INTEN); + regval |= (ENET_DMA_INTEN_NIE | ierbit); + gd32_reg_write(regval, GD32_ENET_DMA_INTEN); +} + +/**************************************************************************** + * Function: gd32_interrupt_disable + * + * Description: + * Disable a normal interrupt. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void gd32_interrupt_disable(struct gd32_enet_mac_s *priv, + uint32_t ierbit) +{ + uint32_t regval; + + /* Disable the "normal" interrupt */ + + regval = gd32_reg_read(GD32_ENET_DMA_INTEN); + regval &= ~ierbit; + + /* Are all "normal" interrupts now disabled? */ + + if ((regval & ENET_DMAINT_NORMAL) == 0) + { + /* Yes.. disable normal interrupts */ + + regval &= ~ENET_DMA_INTEN_NIE; + } + + gd32_reg_write(regval, GD32_ENET_DMA_INTEN); +} + +/**************************************************************************** + * Function: gd32_free_segment + * + * Description: + * The function is called when a frame is received using the DMA receive + * interrupt. It scans the RX descriptors to the received frame. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void gd32_free_segment(struct gd32_enet_mac_s *priv, + struct enet_rxdesc_s *rxfirst, + int segments) +{ + struct enet_rxdesc_s *rxdesc; + int i; + + ninfo("rxfirst: %p segments: %d\n", rxfirst, segments); + + /* Set DAV bit in RX descriptors. This gives the buffers back to DMA */ + + rxdesc = rxfirst; + for (i = 0; i < segments; i++) + { + rxdesc->rdes0 = ENET_RDES0_DAV; + rxdesc = (struct enet_rxdesc_s *)rxdesc->rdes3; + } + + /* Reset the segment management logic */ + + priv->rxcurr = NULL; + priv->segments = 0; + + /* Check if the RX Buffer unavailable flag is set */ + + if ((gd32_reg_read(GD32_ENET_DMA_STAT) & ENET_DMA_INTEN_RBUIE) != 0) + { + /* Clear RBUS Ethernet DMA flag */ + + gd32_reg_write(ENET_DMA_INTEN_RBUIE, GD32_ENET_DMA_STAT); + + /* Resume DMA reception */ + + gd32_reg_write(1, GD32_ENET_DMA_RPEN); + } +} + +/**************************************************************************** + * Function: gd32_receive_frame + * + * Description: + * The function is called when a frame is received using the DMA receive + * interrupt. It scans the RX descriptors of the received frame. + * + * NOTE: This function will silently discard any packets containing errors. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * OK if a packet was successfully returned; -EAGAIN if there are no + * further packets available + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static int gd32_receive_frame(struct gd32_enet_mac_s *priv) +{ + struct enet_rxdesc_s *rxdesc; + struct enet_rxdesc_s *rxcurr; + uint8_t *buffer; + int i; + + ninfo("rxhead: %p rxcurr: %p segments: %d\n", + priv->rxhead, priv->rxcurr, priv->segments); + + /* Check if there are free buffers. We cannot receive new frames in this + * design unless there is at least one free buffer. + */ + + if (!gd32_is_free_buf(priv)) + { + nerr("ERROR: No free buffers\n"); + return -ENOMEM; + } + + /* Scan descriptors owned by the CPU. Scan until: + * + * 1) We find a descriptor still owned by the DMA, + * 2) We have examined all of the RX descriptors, or + * 3) All of the TX descriptors are in flight. + * + * This last case is obscure. It is due to that fact that each packet + * that we receive can generate an unstoppable transmisson. So we have + * to stop receiving when we can not longer transmit. In this case, the + * transmit logic should also have disabled further RX interrupts. + */ + + rxdesc = priv->rxhead; + for (i = 0; + (rxdesc->rdes0 & ENET_RDES0_DAV) == 0 && + i < CONFIG_GD32F4_ENET_NRXDESC && + priv->inflight < CONFIG_GD32F4_ENET_NTXDESC; + i++) + { + /* Check if this is the first segment in the frame */ + + if ((rxdesc->rdes0 & ENET_RDES0_FDES) != 0 && + (rxdesc->rdes0 & ENET_RDES0_LDES) == 0) + { + priv->rxcurr = rxdesc; + priv->segments = 1; + } + + /* Check if this is an intermediate segment in the frame */ + + else if (((rxdesc->rdes0 & ENET_RDES0_LDES) == 0) && + ((rxdesc->rdes0 & ENET_RDES0_FDES) == 0)) + { + priv->segments++; + } + + /* Otherwise, it is the last segment in the frame */ + + else + { + priv->segments++; + + /* Check if there is only one segment in the frame */ + + if (priv->segments == 1) + { + rxcurr = rxdesc; + } + else + { + rxcurr = priv->rxcurr; + } + + ninfo("rxhead: %p rxcurr: %p segments: %d\n", + priv->rxhead, priv->rxcurr, priv->segments); + + /* Check if any errors are reported in the frame */ + + if ((rxdesc->rdes0 & ENET_RDES0_ERRS) == 0) + { + struct net_driver_s *dev = &priv->dev; + + /* Get the Frame Length of the received packet: substruct 4 + * bytes of the CRC + */ + + dev->d_len = ((rxdesc->rdes0 & ENET_RDES0_FRML_MASK) >> + ENET_RDES0_FRML_SHIFT) - 4; + + if (priv->segments > 1 || + dev->d_len > CONFIG_GD32F4_ENET_BUFSIZE) + { + /* The Frame is to big, it spans segments */ + + nerr("ERROR: Dropped, RX descriptor Too big: %d in %d " + "segments\n", dev->d_len, priv->segments); + + gd32_free_segment(priv, rxcurr, priv->segments); + } + + else + { + /* Get a buffer from the free list. We don't even check if + * this is successful because we already assure the free + * list is not empty above. + */ + + buffer = gd32_buf_alloc(priv); + + /* Take the buffer from the RX descriptor of the first free + * segment, put it into the network device structure, then + * replace the buffer in the RX descriptor with the newly + * allocated buffer. + */ + + DEBUGASSERT(dev->d_buf == NULL); + dev->d_buf = (uint8_t *)rxcurr->rdes2; + rxcurr->rdes2 = (uint32_t)buffer; + + /* Return success, remembering where we should re-start + * scanning and resetting the segment scanning logic + */ + + priv->rxhead = (struct enet_rxdesc_s *)rxdesc->rdes3; + gd32_free_segment(priv, rxcurr, priv->segments); + + ninfo("rxhead: %p d_buf: %p d_len: %d\n", + priv->rxhead, dev->d_buf, dev->d_len); + + return OK; + } + } + else + { + /* Drop the frame that contains the errors, reset the segment + * scanning logic, and continue scanning with the next frame. + */ + + nerr("ERROR: Dropped, RX descriptor errors: %08" PRIx32 "\n", + rxdesc->rdes0); + gd32_free_segment(priv, rxcurr, priv->segments); + } + } + + /* Try the next descriptor */ + + rxdesc = (struct enet_rxdesc_s *)rxdesc->rdes3; + } + + /* We get here after all of the descriptors have been scanned or when + * rxdesc points to the first descriptor owned by the DMA. Remember + * where we left off. + */ + + priv->rxhead = rxdesc; + + ninfo("rxhead: %p rxcurr: %p segments: %d\n", + priv->rxhead, priv->rxcurr, priv->segments); + + return -EAGAIN; +} + +/**************************************************************************** + * Function: gd32_receive + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void gd32_receive(struct gd32_enet_mac_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + + /* Loop while while gd32_receive_frame() successfully retrieves valid + * Ethernet frames. + */ + + while (gd32_receive_frame(priv) == OK) + { +#ifdef CONFIG_NET_PKT + /* When packet sockets are enabled, feed the frame into the tap */ + + pkt_input(&priv->dev); +#endif + + /* Check if the packet is a valid size for the network buffer + * configuration (this should not happen) + */ + + if (dev->d_len > CONFIG_NET_ETH_PKTSIZE) + { + nwarn("WARNING: DROPPED Too big: %d\n", dev->d_len); + + /* Free dropped packet buffer */ + + if (dev->d_buf) + { + gd32_buf_free(priv, dev->d_buf); + dev->d_buf = NULL; + dev->d_len = 0; + } + + continue; + } + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv4 + if (BUF->type == HTONS(ETHTYPE_IP)) + { + ninfo("IPv4 frame\n"); + + /* Handle ARP on input then give the IPv4 packet to the network + * layer + */ + + arp_ipin(&priv->dev); + ipv4_input(&priv->dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, d_len field will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + /* Update the Ethernet header with the correct MAC address */ + + arp_out(&priv->dev); + + /* And send the packet */ + + gd32_transmit(priv); + } + } + else +#endif + +#ifdef CONFIG_NET_ARP + if (BUF->type == HTONS(ETHTYPE_ARP)) + { + ninfo("ARP frame\n"); + + /* Handle ARP packet */ + + arp_arpin(&priv->dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, d_len field will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + gd32_transmit(priv); + } + } + else +#endif + { + nerr("ERROR: Dropped, Unknown type: %04x\n", BUF->type); + } + + /* We are finished with the RX buffer. NOTE: If the buffer is + * re-used for transmission, the dev->d_buf field will have been + * nullified. + */ + + if (dev->d_buf) + { + /* Free the receive packet buffer */ + + gd32_buf_free(priv, dev->d_buf); + dev->d_buf = NULL; + dev->d_len = 0; + } + } +} + +/**************************************************************************** + * Function: gd32_freeframe + * + * Description: + * Scans the TX descriptors and frees the buffers of completed transfers. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void gd32_freeframe(struct gd32_enet_mac_s *priv) +{ + struct enet_txdesc_s *txdesc; + int i; + + ninfo("txhead: %p txtail: %p inflight: %d\n", + priv->txhead, priv->txtail, priv->inflight); + + /* Scan for "in-flight" descriptors owned by the CPU */ + + txdesc = priv->txtail; + if (txdesc) + { + DEBUGASSERT(priv->inflight > 0); + + for (i = 0; (txdesc->tdes0 & ENET_TDES0_DAV) == 0; i++) + { + /* There should be a buffer assigned to all in-flight + * TX descriptors. + */ + + ninfo("txtail: %p tdes0: %08" PRIx32 + " tdes2: %08" PRIx32 " tdes3: %08" PRIx32 "\n", + txdesc, txdesc->tdes0, txdesc->tdes2, txdesc->tdes3); + + DEBUGASSERT(txdesc->tdes2 != 0); + + /* Check if this is the first segment of a TX frame. */ + + if ((txdesc->tdes0 & ENET_TDES0_FSG) != 0) + { + /* Yes.. Free the buffer */ + + gd32_buf_free(priv, (uint8_t *)txdesc->tdes2); + } + + /* In any event, make sure that TDES2 is nullified. */ + + txdesc->tdes2 = 0; + + /* Check if this is the last segment of a TX frame */ + + if ((txdesc->tdes0 & ENET_TDES0_LSG) != 0) + { + /* Yes.. Decrement the number of frames "in-flight". */ + + priv->inflight--; + + /* If all of the TX descriptors were in-flight, + * then RX interrupts may have been disabled... + * we can re-enable them now. + */ + + gd32_interrupt_enable(priv, ENET_DMA_INTEN_RIE); + + /* If there are no more frames in-flight, then bail. */ + + if (priv->inflight <= 0) + { + priv->txtail = NULL; + priv->inflight = 0; + return; + } + } + + /* Try the next descriptor in the TX chain */ + + txdesc = (struct enet_txdesc_s *)txdesc->tdes3; + } + + /* We get here if (1) there are still frames "in-flight". Remember + * where we left off. + */ + + priv->txtail = txdesc; + + ninfo("txhead: %p txtail: %p inflight: %d\n", + priv->txhead, priv->txtail, priv->inflight); + } +} + +/**************************************************************************** + * Function: gd32_tx_done + * + * Description: + * An interrupt was received indicating that the last TX packet + * transfer(s) are complete. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void gd32_tx_done(struct gd32_enet_mac_s *priv) +{ + DEBUGASSERT(priv->txtail != NULL); + + /* Scan the TX descriptor change, returning buffers to free list */ + + gd32_freeframe(priv); + + /* If no further xmits are pending, then cancel the TX timeout */ + + if (priv->inflight <= 0) + { + /* Cancel the TX timeout */ + + wd_cancel(&priv->txtimeout); + + /* And disable further TX interrupts. */ + + gd32_interrupt_disable(priv, ENET_DMA_INTEN_TIE); + } + + /* Then poll the network for new XMIT data */ + + gd32_do_poll(priv); +} + +/**************************************************************************** + * Function: gd32_interrupt_work + * + * Description: + * Perform interrupt related work from the worker thread + * + * Input Parameters: + * arg - The argument passed when work_queue() was called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * Ethernet interrupts are disabled + * + ****************************************************************************/ + +static void gd32_interrupt_work(void *arg) +{ + struct gd32_enet_mac_s *priv = (struct gd32_enet_mac_s *)arg; + uint32_t dma_reg; + + DEBUGASSERT(priv); + + /* Process pending Ethernet interrupts */ + + net_lock(); + + /* Get the DMA interrupt status bits (no MAC interrupts are expected) */ + + dma_reg = gd32_reg_read(GD32_ENET_DMA_STAT); + + /* Mask only enabled interrupts. This depends on the fact that the + * interrupt related bits (0-16) correspond in these two registers. + */ + + dma_reg &= gd32_reg_read(GD32_ENET_DMA_INTEN); + + /* Check if there are pending "normal" interrupts */ + + if ((dma_reg & ENET_DMA_INTEN_NIE) != 0) + { + /* Yes.. Check if we received an incoming packet, if so, call + * gd32_receive() + */ + + if ((dma_reg & ENET_DMA_INTEN_RIE) != 0) + { + /* Clear the pending receive interrupt */ + + gd32_reg_write(ENET_DMA_INTEN_RIE, GD32_ENET_DMA_STAT); + + /* Handle the received package */ + + gd32_receive(priv); + } + + /* Check if a packet transmission just completed. If so, call + * gd32_tx_done(). This may disable further TX interrupts if there + * are no pending transmissions. + */ + + if ((dma_reg & ENET_DMA_INTEN_TIE) != 0) + { + /* Clear the pending receive interrupt */ + + gd32_reg_write(ENET_DMA_INTEN_TIE, GD32_ENET_DMA_STAT); + + /* Check if there are pending transmissions */ + + gd32_tx_done(priv); + } + + /* Clear the pending normal summary interrupt */ + + gd32_reg_write(ENET_DMA_INTEN_NIE, GD32_ENET_DMA_STAT); + } + + /* Handle error interrupt only if CONFIG_DEBUG_NET is eanbled */ + +#ifdef CONFIG_DEBUG_NET + + /* Check if there are pending "anormal" interrupts */ + + if ((dma_reg & ENET_DMA_STAT_AI) != 0) + { + /* Just let the user know what happened */ + + nerr("ERROR: Abormal event(s): %08x\n", dma_reg); + + /* Clear all pending abnormal events */ + + gd32_reg_write(ENET_DMAINT_ABNORMAL, GD32_ENET_DMA_STAT); + + /* Clear the pending abnormal summary interrupt */ + + gd32_reg_write(ENET_DMA_STAT_AI, GD32_ENET_DMA_STAT); + } +#endif + + net_unlock(); + + /* Re-enable Ethernet interrupts at the NVIC */ + + up_enable_irq(GD32_IRQ_ENET); +} + +/**************************************************************************** + * Function: gd32_interrupt + * + * Description: + * Hardware interrupt handler + * + * Input Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success + * + * Assumptions: + * + ****************************************************************************/ + +static int gd32_interrupt(int irq, void *context, void *arg) +{ + struct gd32_enet_mac_s *priv = &g_enet_mac[0]; + uint32_t dma_reg; + + /* Get the DMA interrupt status bits (no MAC interrupts are expected) */ + + dma_reg = gd32_reg_read(GD32_ENET_DMA_STAT); + if (dma_reg != 0) + { + /* Disable further Ethernet interrupts. Because Ethernet interrupts + * are also disabled if the TX timeout event occurs, there can be no + * race condition here. + */ + + up_disable_irq(GD32_IRQ_ENET); + + /* Check if a packet transmission just completed. */ + + if ((dma_reg & ENET_DMA_INTEN_TIE) != 0) + { + /* If a TX transfer just completed, then cancel the TX timeout so + * there will be no race condition between any subsequent timeout + * expiration and the deferred interrupt processing. + */ + + wd_cancel(&priv->txtimeout); + } + + /* Schedule to perform the interrupt processing on the worker thread. */ + + work_queue(ENET_WORK, &priv->irqwork, gd32_interrupt_work, priv, 0); + } + + return OK; +} + +/**************************************************************************** + * Function: gd32_txtimeout_work + * + * Description: + * Perform TX timeout related work from the worker thread + * + * Input Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * Ethernet interrupts are disabled + * + ****************************************************************************/ + +static void gd32_txtimeout_work(void *arg) +{ + struct gd32_enet_mac_s *priv = (struct gd32_enet_mac_s *)arg; + + /* Reset the hardware. Just take the interface down, then back up again. */ + + net_lock(); + gd32_ifdown(&priv->dev); + gd32_ifup(&priv->dev); + + /* Then poll for new XMIT data */ + + gd32_do_poll(priv); + net_unlock(); +} + +/**************************************************************************** + * Function: gd32_tx_timeout_expiry + * + * Description: + * Our TX watchdog timed out. Called from the timer interrupt handler. + * The last TX never completed. Reset the hardware and start again. + * + * Input Parameters: + * arg - The argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void gd32_tx_timeout_expiry(wdparm_t arg) +{ + struct gd32_enet_mac_s *priv = (struct gd32_enet_mac_s *)arg; + + nerr("ERROR: Timeout!\n"); + + /* Disable further Ethernet interrupts. This will prevent some race + * conditions with interrupt work. There is still a potential race + * condition with interrupt work that is already queued and in progress. + * + * Interrupts will be re-enabled when gd32_ifup() is called. + */ + + up_disable_irq(GD32_IRQ_ENET); + + /* Schedule to perform the TX timeout processing on the worker thread, + * perhaps canceling any pending IRQ processing. + */ + + work_queue(ENET_WORK, &priv->irqwork, gd32_txtimeout_work, priv, 0); +} + +/**************************************************************************** + * Function: gd32_poll_work + * + * Description: + * Perform periodic polling from the worker thread + * + * Input Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * Ethernet interrupts are disabled + * + ****************************************************************************/ + +static void gd32_poll_work(void *arg) +{ + struct gd32_enet_mac_s *priv = (struct gd32_enet_mac_s *)arg; + struct net_driver_s *dev = &priv->dev; + + /* Check if the next TX descriptor is owned by the Ethernet DMA or + * CPU. We cannot perform the TX poll if we are unable to accept + * another packet for transmission. + * + * In a race condition, ENET_TDES0_DAV may be cleared BUT still + * not available because gd32_freeframe() has not yet run. If + * gd32_freeframe() has run, the buffer1 pointer (tdes2) will be + * nullified (and inflight should be < CONFIG_gd32_ETH_NTXDESC). + */ + + net_lock(); + if ((priv->txhead->tdes0 & ENET_TDES0_DAV) == 0 && + priv->txhead->tdes2 == 0) + { + /* If we have the descriptor, then perform the timer poll. Allocate a + * buffer for the poll. + */ + + DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL); + dev->d_buf = gd32_buf_alloc(priv); + + /* We can't poll if we have no buffers */ + + if (dev->d_buf) + { + /* Update TCP timing states and poll the network for + * new XMIT data. + */ + + devif_poll(dev, gd32_tx_poll); + + /* We will, most likely end up with a buffer to be freed. But it + * might not be the same one that we allocated above. + */ + + if (dev->d_buf) + { + DEBUGASSERT(dev->d_len == 0); + gd32_buf_free(priv, dev->d_buf); + dev->d_buf = NULL; + } + } + } + + /* Setup the watchdog poll timer again */ + + wd_start(&priv->txpoll, GD32_WDDELAY, + gd32_poll_expiry, (wdparm_t)priv); + net_unlock(); +} + +/**************************************************************************** + * Function: gd32_poll_expiry + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * Input Parameters: + * arg - The argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void gd32_poll_expiry(wdparm_t arg) +{ + struct gd32_enet_mac_s *priv = (struct gd32_enet_mac_s *)arg; + + /* Schedule to perform the interrupt processing on the worker thread. */ + + work_queue(ENET_WORK, &priv->pollwork, gd32_poll_work, priv, 0); +} + +/**************************************************************************** + * Function: gd32_ifup + * + * Description: + * NuttX Callback: Bring up the Ethernet interface when an IP address is + * provided + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int gd32_ifup(struct net_driver_s *dev) +{ + struct gd32_enet_mac_s *priv = + (struct gd32_enet_mac_s *)dev->d_private; + int ret; + +#ifdef CONFIG_NET_IPv4 + ninfo("Bringing up: %d.%d.%d.%d\n", + (int)(dev->d_ipaddr & 0xff), + (int)((dev->d_ipaddr >> 8) & 0xff), + (int)((dev->d_ipaddr >> 16) & 0xff), + (int)(dev->d_ipaddr >> 24)); +#endif + + /* Configure the Ethernet interface for DMA operation. */ + + ret = gd32_enet_config(priv); + if (ret < 0) + { + return ret; + } + + /* Set and activate a timer process */ + + wd_start(&priv->txpoll, GD32_WDDELAY, + gd32_poll_expiry, (wdparm_t)priv); + + /* Enable the Ethernet interrupt */ + + priv->ifup = true; + up_enable_irq(GD32_IRQ_ENET); + + return OK; +} + +/**************************************************************************** + * Function: gd32_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * Returns zero on success; a negated errno value is returned on any + * failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int gd32_ifdown(struct net_driver_s *dev) +{ + struct gd32_enet_mac_s *priv = + (struct gd32_enet_mac_s *)dev->d_private; + irqstate_t flags; + int ret = OK; + + ninfo("Taking the network down\n"); + + /* Disable the Ethernet interrupt */ + + flags = enter_critical_section(); + up_disable_irq(GD32_IRQ_ENET); + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(&priv->txpoll); + wd_cancel(&priv->txtimeout); + + /* Put the ENET_MAC in its reset, non-operational state. This should be + * a known configuration that will guarantee the gd32_ifup() always + * successfully brings the interface back up. + */ + + ret = gd32_enet_reset(priv); + if (ret < 0) + { + nerr("ERROR: gd32_enet_reset failed (timeout), " + "still assuming it's going down.\n"); + } + + /* Mark the device "down" */ + + priv->ifup = false; + leave_critical_section(flags); + return ret; +} + +/**************************************************************************** + * Function: gd32_txavail_work + * + * Description: + * Perform an out-of-cycle poll on the worker thread. + * + * Input Parameters: + * arg - Reference to the NuttX driver state structure (cast to void*) + * + * Returned Value: + * None + * + * Assumptions: + * Called on the higher priority worker thread. + * + ****************************************************************************/ + +static void gd32_txavail_work(void *arg) +{ + struct gd32_enet_mac_s *priv = (struct gd32_enet_mac_s *)arg; + + ninfo("ifup: %d\n", priv->ifup); + + /* Ignore the notification if the interface is not yet up */ + + net_lock(); + if (priv->ifup) + { + /* Poll the network for new XMIT data */ + + gd32_do_poll(priv); + } + + net_unlock(); +} + +/**************************************************************************** + * Function: gd32_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int gd32_txavail(struct net_driver_s *dev) +{ + struct gd32_enet_mac_s *priv = + (struct gd32_enet_mac_s *)dev->d_private; + + /* Is our single work structure available? It may not be if there are + * pending interrupt actions and we will have to ignore the Tx + * availability action. + */ + + if (work_available(&priv->pollwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(ENET_WORK, &priv->pollwork, gd32_txavail_work, priv, 0); + } + + return OK; +} + +/**************************************************************************** + * Function: gd32_calcethcrc + * + * Description: + * Function to calculate the CRC used by gd32 to check an ethernet frame + * + * Input Parameters: + * data - the data to be checked + * length - length of the data + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_NET_MCASTGROUP) +static uint32_t gd32_calcethcrc(const uint8_t *data, size_t length) +{ + uint32_t crc = 0xffffffff; + size_t i; + int j; + + for (i = 0; i < length; i++) + { + for (j = 0; j < 8; j++) + { + if (((crc >> 31) ^ (data[i] >> j)) & 0x01) + { + /* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */ + + crc = (crc << 1) ^ 0x04c11db7; + } + else + { + crc = crc << 1; + } + } + } + + return ~crc; +} +#endif + +/**************************************************************************** + * Function: gd32_add_mac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_NET_MCASTGROUP) +static int gd32_add_mac(struct net_driver_s *dev, const uint8_t *mac) +{ + uint32_t crc; + uint32_t hashindex; + uint32_t temp; + uint32_t registeraddress; + + ninfo("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + /* Add the MAC address to the hardware multicast hash table */ + + crc = gd32_calcethcrc(mac, 6); + + hashindex = (crc >> 26) & 0x3f; + + if (hashindex > 31) + { + registeraddress = GD32_ENET_MAC_HLH; + hashindex -= 32; + } + else + { + registeraddress = GD32_ENET_MAC_HLL; + } + + temp = gd32_reg_read(registeraddress); + temp |= 1 << hashindex; + gd32_reg_write(temp, registeraddress); + + temp = gd32_reg_read(GD32_ENET_MAC_FRMF); + temp |= (ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT); + gd32_reg_write(temp, GD32_ENET_MAC_FRMF); + + return OK; +} +#endif /* CONFIG_NET_MCASTGROUP */ + +/**************************************************************************** + * Function: gd32_remove_mac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware + * multicast address filtering + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_MCASTGROUP +static int gd32_remove_mac(struct net_driver_s *dev, const uint8_t *mac) +{ + uint32_t crc; + uint32_t hashindex; + uint32_t temp; + uint32_t registeraddress; + + ninfo("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + /* Remove the MAC address to the hardware multicast hash table */ + + crc = gd32_calcethcrc(mac, 6); + + hashindex = (crc >> 26) & 0x3f; + + if (hashindex > 31) + { + registeraddress = GD32_ENET_MAC_HLH; + hashindex -= 32; + } + else + { + registeraddress = GD32_ENET_MAC_HLL; + } + + temp = gd32_reg_read(registeraddress); + temp &= ~(1 << hashindex); + gd32_reg_write(temp, registeraddress); + + /* If there is no address registered any more, delete multicast filtering */ + + if (gd32_reg_read(GD32_ENET_MAC_HLH) == 0 && + gd32_reg_read(GD32_ENET_MAC_HLL) == 0) + { + temp = gd32_reg_read(GD32_ENET_MAC_FRMF); + temp &= ~(ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT); + gd32_reg_write(temp, GD32_ENET_MAC_FRMF); + } + + return OK; +} +#endif + +/**************************************************************************** + * Function: gd32_txdes_chain_init + * + * Description: + * Initializes the DMA TX descriptors in chain mode. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void gd32_txdes_chain_init(struct gd32_enet_mac_s *priv) +{ + struct enet_txdesc_s *txdesc; + int i; + + /* priv->txhead point to the first, available TX descriptor in the chain. + * Set the priv->txhead pointer to the first descriptor in the table. + */ + + priv->txhead = priv->txtable; + + /* priv->txtail will point to the first segment of the oldest pending + * "in-flight" TX transfer. NULL means that there are no active TX + * transfers. + */ + + priv->txtail = NULL; + priv->inflight = 0; + + /* Initialize each TX descriptor */ + + for (i = 0; i < CONFIG_GD32F4_ENET_NTXDESC; i++) + { + txdesc = &priv->txtable[i]; + + /* Set Second Address Chained bit */ + + txdesc->tdes0 = ENET_TDES0_TCHM; + +#ifdef CHECKSUM_BY_HARDWARE + /* Enable the checksum insertion for the TX frames */ + + txdesc->tdes0 |= ENET_CHECKSUM_TCPUDPICMP_FULL; +#endif + + /* Clear Buffer1 address pointer (buffers will be assigned as they + * are used) + */ + + txdesc->tdes2 = 0; + + /* Initialize the next descriptor with + * the Next Descriptor Polling Enable + */ + + if (i < (CONFIG_GD32F4_ENET_NTXDESC - 1)) + { + /* Set next descriptor address register with next descriptor base + * address + */ + + txdesc->tdes3 = (uint32_t)&priv->txtable[i + 1]; + } + else + { + /* For last descriptor, set next descriptor address register equal + * to the first descriptor base address + */ + + txdesc->tdes3 = (uint32_t)priv->txtable; + } + } + + /* Set Transmit Descriptor List Address Register */ + + gd32_reg_write((uint32_t)priv->txtable, GD32_ENET_DMA_TDTADDR); +} + +/**************************************************************************** + * Function: gd32_rxdes_chain_init + * + * Description: + * Initializes the DMA RX descriptors in chain mode. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void gd32_rxdes_chain_init(struct gd32_enet_mac_s *priv) +{ + struct enet_rxdesc_s *rxdesc; + int i; + + /* priv->rxhead will point to the first, RX descriptor in the chain. + * This will be where we receive the first incomplete frame. + */ + + priv->rxhead = priv->rxtable; + + /* If we accumulate the frame in segments, priv->rxcurr points to the + * RX descriptor of the first segment in the current TX frame. + */ + + priv->rxcurr = NULL; + priv->segments = 0; + + /* Initialize each TX descriptor */ + + for (i = 0; i < CONFIG_GD32F4_ENET_NRXDESC; i++) + { + rxdesc = &priv->rxtable[i]; + + /* Set DAV bit of the RX descriptor rdes0 */ + + rxdesc->rdes0 = ENET_RDES0_DAV; + + /* Set Buffer1 size and Second Address Chained bit and enabled DMA + * RX desc receive interrupt + */ + + rxdesc->rdes1 = ENET_RDES1_RCHM | (uint32_t)CONFIG_GD32F4_ENET_BUFSIZE; + + /* Set Buffer1 address pointer */ + + rxdesc->rdes2 = (uint32_t)&priv->rxbuffer[i * + CONFIG_GD32F4_ENET_BUFSIZE]; + + /* Initialize the next descriptor with + * the Next Descriptor Polling Enable + */ + + if (i < (CONFIG_GD32F4_ENET_NRXDESC - 1)) + { + /* Set next descriptor address register with next descriptor base + * address + */ + + rxdesc->rdes3 = (uint32_t)&priv->rxtable[i + 1]; + } + else + { + /* For last descriptor, set next descriptor address register equal + * to the first descriptor base address + */ + + rxdesc->rdes3 = (uint32_t)priv->rxtable; + } + } + + /* Set Receive Descriptor List Address Register */ + + gd32_reg_write((uint32_t)priv->rxtable, GD32_ENET_DMA_RDTADDR); +} + +/**************************************************************************** + * Function: gd32_ioctl + * + * Description: + * Executes the SIOCxMIIxxx command and responds using the request struct + * that must be provided as its 2nd parameter. + * + * When called with SIOCGMIIPHY it will get the PHY address for the device + * and write it to the req->phy_id field of the request struct. + * + * When called with SIOCGMIIREG it will read a register of the PHY that is + * specified using the req->reg_no struct field and then write its output + * to the req->val_out field. + * + * When called with SIOCSMIIREG it will write to a register of the PHY that + * is specified using the req->reg_no struct field and use req->val_in as + * its input. + * + * Input Parameters: + * dev - Ethernet device structure + * cmd - SIOCxMIIxxx command code + * arg - Request structure also used to return values + * + * Returned Value: Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_IOCTL +static int gd32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) +{ +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) + struct gd32_enet_mac_s *priv = + (struct gd32_enet_mac_s *)dev->d_private; +#endif + int ret; + + switch (cmd) + { +#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_ARCH_PHY_INTERRUPT + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ + { + struct mii_ioctl_notify_s *req = + (struct mii_ioctl_notify_s *)((uintptr_t)arg); + + ret = phy_notify_subscribe(dev->d_ifname, req->pid, &req->event); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = gd32_phy_interrupt_enable(priv); + } + } + break; +#endif + + case SIOCGMIIPHY: /* Get MII PHY address */ + { + struct mii_ioctl_data_s *req = + (struct mii_ioctl_data_s *)((uintptr_t)arg); + req->phy_id = CONFIG_GD32F4_PHY_ADDR; + ret = OK; + } + break; + + case SIOCGMIIREG: /* Get register from MII PHY */ + { + struct mii_ioctl_data_s *req = + (struct mii_ioctl_data_s *)((uintptr_t)arg); + ret = gd32_phy_read(req->phy_id, req->reg_num, &req->val_out); + } + break; + + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = + (struct mii_ioctl_data_s *)((uintptr_t)arg); + ret = gd32_phy_write(req->phy_id, req->reg_num, req->val_in); + } + break; +#endif /* CONFIG_NETDEV_PHY_IOCTL */ + + default: + ret = -ENOTTY; + break; + } + + return ret; +} +#endif /* CONFIG_NETDEV_IOCTL */ + +/**************************************************************************** + * Function: gd32_phy_interrupt_enable + * + * Description: + * Enable link up/down PHY interrupts. The interrupt protocol is like this: + * + * - Interrupt status is cleared when the interrupt is enabled. + * - Interrupt occurs. Interrupt is disabled (at the processor level) when + * is received. + * - Interrupt status is cleared when the interrupt is re-enabled. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno (-ETIMEDOUT) on failure. + * + ****************************************************************************/ + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int gd32_phy_interrupt_enable(struct gd32_enet_mac_s *priv) +{ + uint16_t phyval; + int ret; + + ret = gd32_phy_read(CONFIG_GD32F4_PHY_ADDR, MII_INT_REG, &phyval); + if (ret == OK) + { + /* Enable link up/down interrupts */ + + ret = gd32_phy_write(CONFIG_GD32F4_PHY_ADDR, MII_INT_REG, + (phyval & ~MII_INT_CLREN) | MII_INT_SETEN); + } + + return ret; +} +#endif + +/**************************************************************************** + * Function: gd32_phy_read + * + * Description: + * Read a PHY register. + * + * Input Parameters: + * phydevaddr - The PHY device address + * phyregaddr - The PHY register address + * value - The location to return the 16-bit PHY register value. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_GD32F4_AUTO_NEGOTIATION) || defined(CONFIG_NETDEV_PHY_IOCTL) +static int gd32_phy_read(uint16_t phydevaddr, + uint16_t phyregaddr, uint16_t *value) +{ + volatile uint32_t timeout; + uint32_t regval; + + /* Configure the MAC_PHY_CTL register, + * preserving CSR Clock Range CR[2:0] bits + */ + + regval = gd32_reg_read(GD32_ENET_MAC_PHY_CTL); + regval &= ENET_MAC_PHY_CTL_CLR_MASK; + + /* Set the PHY device address, PHY register address, and set the busy bit. + * the ENET_MAC_PHY_CTL_PW is clear, indicating a read operation. + */ + + regval |= (phydevaddr << ENET_MAC_PHY_CTL_PA_SHIFT) & + ENET_MAC_PHY_CTL_PA_MASK; + regval |= (phyregaddr << ENET_MAC_PHY_CTL_PR_SHIFT) & + ENET_MAC_PHY_CTL_PR_MASK; + regval |= ENET_MAC_PHY_CTL_PB; + + gd32_reg_write(regval, GD32_ENET_MAC_PHY_CTL); + + /* Wait for the transfer to complete */ + + for (timeout = 0; timeout < PHY_READ_TIMEOUT; timeout++) + { + if ((gd32_reg_read(GD32_ENET_MAC_PHY_CTL) & ENET_MAC_PHY_CTL_PB) == 0) + { + *value = (uint16_t)gd32_reg_read(GD32_ENET_MAC_PHY_DATA); + return OK; + } + } + + nerr("ERROR: MII transfer timed out: phydevaddr: %04x phyregaddr: %04x\n", + phydevaddr, phyregaddr); + + return -ETIMEDOUT; +} +#endif + +/**************************************************************************** + * Function: gd32_phy_write + * + * Description: + * Write to a PHY register. + * + * Input Parameters: + * phydevaddr - The PHY device address + * phyregaddr - The PHY register address + * value - The 16-bit value to write to the PHY register value. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int gd32_phy_write(uint16_t phydevaddr, + uint16_t phyregaddr, uint16_t value) +{ + volatile uint32_t timeout; + uint32_t regval; + + /* Configure the MAC_PHY_CTL register, + * preserving CSR Clock Range CR[2:0] bits + */ + + regval = gd32_reg_read(GD32_ENET_MAC_PHY_CTL); + regval &= ENET_MAC_PHY_CTL_CLR_MASK; + + /* Set the PHY device address, PHY register address, and set the busy bit. + * the ENET_MAC_PHY_CTL_PW is set, indicating a write operation. + */ + + regval |= (phydevaddr << ENET_MAC_PHY_CTL_PA_SHIFT) & + ENET_MAC_PHY_CTL_PA_MASK; + regval |= (phyregaddr << ENET_MAC_PHY_CTL_PR_SHIFT) & + ENET_MAC_PHY_CTL_PR_MASK; + regval |= (ENET_MAC_PHY_CTL_PB | ENET_MAC_PHY_CTL_PW); + + /* Write the value into the MAC_PHY_DATA register before setting the new + * MAC_PHY_CTL register value. + */ + + gd32_reg_write(value, GD32_ENET_MAC_PHY_DATA); + gd32_reg_write(regval, GD32_ENET_MAC_PHY_CTL); + + /* Wait for the transfer to complete */ + + for (timeout = 0; timeout < PHY_WRITE_TIMEOUT; timeout++) + { + if ((gd32_reg_read(GD32_ENET_MAC_PHY_CTL) & ENET_MAC_PHY_CTL_PB) == 0) + { + return OK; + } + } + + nerr("ERROR: MII transfer timed out: " + "phydevaddr: %04x phyregaddr: %04x value: %04x\n", + phydevaddr, phyregaddr, value); + + return -ETIMEDOUT; +} + +/**************************************************************************** + * Function: gd32_phy_init + * + * Description: + * Configure the PHY and determine the link speed/duplex. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int gd32_phy_init(struct gd32_enet_mac_s *priv) +{ +#ifdef CONFIG_GD32F4_AUTO_NEGOTIATION + volatile uint32_t timeout; +#endif + + uint32_t regval; + uint16_t phyval; + int ret; + + /* Assume 10MBps and half duplex */ + + priv->mbps100 = 0; + priv->fduplex = 0; + + /* Setup up PHY clocking by setting the SR field in + * the MAC_PHY_CTL register + */ + + regval = gd32_reg_read(GD32_ENET_MAC_PHY_CTL); + regval &= ~ENET_MAC_PHY_CTL_CLR_MASK; + regval |= ENET_MAC_PHY_CTL_CLR; + gd32_reg_write(regval, GD32_ENET_MAC_PHY_CTL); + + /* Put the PHY in reset mode */ + + ret = gd32_phy_write(CONFIG_GD32F4_PHY_ADDR, MII_MCR, MII_MCR_RESET); + if (ret < 0) + { + nerr("ERROR: Failed to reset the PHY: %d\n", ret); + return ret; + } + + up_mdelay(PHY_RESET_DELAY); + + /* Perform any necessary, board-specific PHY initialization */ + +#ifdef CONFIG_GD32F4_PHY_INIT + ret = gd32_phy_boardinitialize(0); + if (ret < 0) + { + nerr("ERROR: Failed to initialize the PHY: %d\n", ret); + return ret; + } +#endif + + /* Perform auto-negotiation if so configured */ + +#ifdef CONFIG_GD32F4_AUTO_NEGOTIATION + /* Wait for link status */ + + for (timeout = 0; timeout < PHY_RETRY_TIMEOUT; timeout++) + { + ret = gd32_phy_read(CONFIG_GD32F4_PHY_ADDR, MII_MSR, &phyval); + if (ret < 0) + { + nerr("ERROR: Failed to read the PHY MSR: %d\n", ret); + return ret; + } + else if ((phyval & MII_MSR_LINKSTATUS) != 0) + { + break; + } + } + + if (timeout >= PHY_RETRY_TIMEOUT) + { + nerr("ERROR: Timed out waiting for link status: %04x\n", phyval); + return -ETIMEDOUT; + } + + /* Enable auto-negotiation */ + + ret = gd32_phy_write(CONFIG_GD32F4_PHY_ADDR, MII_MCR, MII_MCR_ANENABLE); + if (ret < 0) + { + nerr("ERROR: Failed to enable auto-negotiation: %d\n", ret); + return ret; + } + + /* Wait until auto-negotiation completes */ + + for (timeout = 0; timeout < PHY_RETRY_TIMEOUT; timeout++) + { + ret = gd32_phy_read(CONFIG_GD32F4_PHY_ADDR, MII_MSR, &phyval); + if (ret < 0) + { + nerr("ERROR: Failed to read the PHY MSR: %d\n", ret); + return ret; + } + else if ((phyval & MII_MSR_ANEGCOMPLETE) != 0) + { + break; + } + } + + if (timeout >= PHY_RETRY_TIMEOUT) + { + nerr("ERROR: Timed out waiting for auto-negotiation\n"); + return -ETIMEDOUT; + } + + /* Read the result of the auto-negotiation from the PHY-specific register */ + + ret = gd32_phy_read(CONFIG_GD32F4_PHY_ADDR, CONFIG_GD32F4_PHY_SR, &phyval); + if (ret < 0) + { + nerr("ERROR: Failed to read PHY status register\n"); + return ret; + } + + /* Remember the selected speed and duplex modes */ + + ninfo("PHYSR[%d]: %04x\n", CONFIG_GD32F4_PHY_SR, phyval); + + /* Different PHYs present speed and mode information in different ways. + * IF This CONFIG_gd32_PHYSR_ALTCONFIG is selected, this indicates that + * the PHY represents speed and mode information are combined, for example, + * with separate bits for 10HD, 100HD, 10FD and 100FD. + */ + +#ifdef CONFIG_GD32F4_PHY_SR_ALTCONFIG + switch (phyval & CONFIG_GD32F4_PHY_SR_ALTMODE) + { + default: + case CONFIG_GD32F4_PHY_SR_10HD: + priv->fduplex = 0; + priv->mbps100 = 0; + break; + + case CONFIG_GD32F4_PHY_SR_100HD: + priv->fduplex = 0; + priv->mbps100 = 1; + break; + + case CONFIG_GD32F4_PHY_SR_10FD: + priv->fduplex = 1; + priv->mbps100 = 0; + break; + + case CONFIG_GD32F4_PHY_SR_100FD: + priv->fduplex = 1; + priv->mbps100 = 1; + break; + } + + /* Different PHYs present speed and mode information in different ways. + * Some will present separate information for speed and mode (this is the + * default). Those PHYs, for example, may provide a 10/100 Mbps indication + * and a separate full/half duplex indication. + */ + +#else + if ((phyval & CONFIG_GD32F4_PHY_SR_MODE) == + CONFIG_GD32F4_PHY_SR_FULLDUPLEX) + { + priv->fduplex = 1; + } + + if ((phyval & CONFIG_GD32F4_PHY_SR_SPEED) == CONFIG_GD32F4_PHY_SR_100M) + { + priv->mbps100 = 1; + } +#endif + +#else /* Auto-negotiation not selected */ + + phyval = 0; +#ifdef CONFIG_GD32F4_ENET_MODE_FULLDUPLEX + phyval |= MII_MCR_FULLDPLX; +#endif +#ifdef CONFIG_GD32F4_ENET_SPEEDMODE_100M + phyval |= MII_MCR_SPEED100; +#endif + + ret = gd32_phy_write(CONFIG_GD32F4_PHY_ADDR, MII_MCR, phyval); + if (ret < 0) + { + nerr("ERROR: Failed to write the PHY MCR: %d\n", ret); + return ret; + } + + up_mdelay(PHY_CONFIG_DELAY); + + /* Remember the selected speed and duplex modes */ + +#ifdef CONFIG_GD32F4_ENET_MODE_FULLDUPLEX + priv->fduplex = 1; +#endif +#ifdef CONFIG_GD32F4_ENET_SPEEDMODE_100M + priv->mbps100 = 1; +#endif +#endif + + ninfo("Duplex: %s Speed: %d MBps\n", + priv->fduplex ? "FULL" : "HALF", + priv->mbps100 ? 100 : 10); + + return OK; +} + +/**************************************************************************** + * Name: gd32_select_mii + * + * Description: + * Selects the MII interface. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_GD32F4_MII +static inline void gd32_select_mii(void) +{ + uint32_t regval; + + regval = getreg32(GD32_SYSCFG_CFG1); + regval &= ~SYSCFG_CFG1_ENET_PHY_SEL_MASK; + putreg32(regval, GD32_SYSCFG_CFG1); +} +#endif + +/**************************************************************************** + * Name: gd32_select_rmii + * + * Description: + * Selects the RMII interface. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void gd32_select_rmii(void) +{ + gd32_syscfg_clock_enable(); + gd32_syscfg_enet_phy_interface_config(SYSCFG_ENET_PHY_RMII); +} + +/**************************************************************************** + * Function: gd32_enet_gpio_config + * + * Description: + * Configure GPIOs for the ENET interface. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +static inline void gd32_enet_gpio_config(struct gd32_enet_mac_s *priv) +{ + /* Configure GPIO pins to support ENET */ + +#if defined(CONFIG_GD32F4_MII) || defined(CONFIG_GD32F4_RMII) + + /* MDC and MDIO are common to both modes */ + + gd32_gpio_config(GPIO_ENET_MDC); + gd32_gpio_config(GPIO_ENET_MDIO); + + /* Set up the MII interface */ + +#if defined(CONFIG_GD32F4_MII) + + /* Select the MII interface */ + + gd32_syscfg_enet_phy_interface_config(SYSCFG_ENET_PHY_MII); + + /* Provide clocking via CKOUT0 or CKOUT1: + * + * "CKOUT0, used to output CK_IRC16M, CK_LXTAL, CK_HXTAL or + * CK_PLLP clock (through a configurable prescaler) on PA8 pin." + * + * "CKOUT1, used to output CK_SYS, CK_PLL2SR, CK_HXTAL or + * CK_PLLP clock (through a configurable prescaler) on PC9 pin." + */ + +# if defined(CONFIG_GD32F4_MII_CKOUT0) + /* Configure CKOUT0 to drive the PHY. Board logic must provide + * CKOUT0 clocking info. + */ + + gd32_gpio_config(GPIO_CKOUT0); + gd32_rcu_ckout0_config(BOARD_CFG_CKOUT0_SOURCE, BOARD_CFG_CKOUT0_DIVIDER); + +# elif defined(CONFIG_GD32F4_MII_CKOUT1) + /* Configure CKOUT1 to drive the PHY. Board logic must provide + * CKOUT1 clocking info. + */ + + gd32_gpio_config(GPIO_CKOUT1); + gd32_rcu_ckout1_config(BOARD_CFG_CKOUT1_SOURCE, BOARD_CFG_CKOUT1_DIVIDER); +# endif + + /* MII interface pins (17): + * + * MII_TX_CLK, MII_TXD[3:0], MII_TX_EN, MII_RX_CLK, MII_RXD[3:0], + * MII_RX_ER, MII_RX_DV, MII_CRS, MII_COL, MDC, MDIO + */ + + gd32_gpio_config(GPIO_ENET_MII_COL); + gd32_gpio_config(GPIO_ENET_MII_CRS); + gd32_gpio_config(GPIO_ENET_MII_RXD0); + gd32_gpio_config(GPIO_ENET_MII_RXD1); + gd32_gpio_config(GPIO_ENET_MII_RXD2); + gd32_gpio_config(GPIO_ENET_MII_RXD3); + gd32_gpio_config(GPIO_ENET_MII_RX_CLK); + gd32_gpio_config(GPIO_ENET_MII_RX_DV); + gd32_gpio_config(GPIO_ENET_MII_RX_ER); + gd32_gpio_config(GPIO_ENET_MII_TXD0); + gd32_gpio_config(GPIO_ENET_MII_TXD1); + gd32_gpio_config(GPIO_ENET_MII_TXD2); + gd32_gpio_config(GPIO_ENET_MII_TXD3); + gd32_gpio_config(GPIO_ENET_MII_TX_CLK); + gd32_gpio_config(GPIO_ENET_MII_TX_EN); + + /* Set up the RMII interface. */ + +#elif defined(CONFIG_GD32F4_RMII) + + /* Select the RMII interface */ + + gd32_select_rmii(); + + /* Provide clocking via CKOUT0 or CKOUT1: + * + * "CKOUT0, used to output CK_IRC16M, CK_LXTAL, CK_HXTAL or + * CK_PLLP clock (through a configurable prescaler) on PA8 pin." + * + * "CKOUT1, used to output CK_SYS, CK_PLL2SR, CK_HXTAL or + * CK_PLLP clock (through a configurable prescaler) on PC9 pin." + */ + +# if defined(CONFIG_GD32F4_RMII_CKOUT0) + /* Configure CKOUT0 to drive the PHY. Board logic must provide + * CKOUT0 clocking info. + */ + + gd32_gpio_config(GPIO_CKOUT0); + gd32_rcu_ckout0_config(BOARD_CFG_CKOUT0_SOURCE, BOARD_CFG_CKOUT0_DIV); + +# elif defined(CONFIG_GD32F4_RMII_CKOUT1) + /* Configure CKOUT1 to drive the PHY. Board logic must provide + * CKOUT1 clocking info. + */ + + gd32_gpio_config(GPIO_CKOUT1); + gd32_rcu_ckout1_config(BOARD_CFG_CKOUT1_SOURCE, BOARD_CFG_CKOUT1_DIVIDER); + +# endif + + /* RMII interface pins (7): + * + * RMII_TXD[1:0], RMII_TX_EN, RMII_RXD[1:0], RMII_CRS_DV, MDC, MDIO, + * RMII_REF_CLK + */ + + gd32_gpio_config(GPIO_ENET_RMII_CRS_DV); + gd32_gpio_config(GPIO_ENET_RMII_REF_CLK); + gd32_gpio_config(GPIO_ENET_RMII_RXD0); + gd32_gpio_config(GPIO_ENET_RMII_RXD1); + gd32_gpio_config(GPIO_ENET_RMII_TX_EN); + gd32_gpio_config(GPIO_ENET_RMII_TXD0); + gd32_gpio_config(GPIO_ENET_RMII_TXD1); + +#endif +#endif + +#ifdef CONFIG_GD32F4_ENET_PTP + /* Enable pulse-per-second (PPS) output signal */ + + gd32_gpio_config(GPIO_ENET_PPS_OUT); +#endif +} + +/**************************************************************************** + * Function: gd32_enet_reset + * + * Description: + * Reset the ENET block. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * Zero on success, or a negated errno value on any failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int gd32_enet_reset(struct gd32_enet_mac_s *priv) +{ + uint32_t regval; + uint32_t retries; + + /* Reset the ENET on the AHB1 bus */ + + regval = gd32_reg_read(GD32_RCU_AHB1RST); + regval |= RCU_AHB1RST_ENETRST; + gd32_reg_write(regval, GD32_RCU_AHB1RST); + + regval &= ~RCU_AHB1RST_ENETRST; + gd32_reg_write(regval, GD32_RCU_AHB1RST); + + /* Perform a software reset by setting the SR bit in the DMA_BCTL register. + * This Resets all MAC subsystem internal registers and logic. After this + * reset all the registers holds their reset values. + */ + + regval = gd32_reg_read(GD32_ENET_DMA_BCTL); + regval |= ENET_DMA_BCTL_SWR; + gd32_reg_write(regval, GD32_ENET_DMA_BCTL); + + /* Wait for software reset to complete. The SWR bit is cleared + * automatically after the reset operation has completed + * in all core clock domains. + */ + + retries = 10; + while (((gd32_reg_read(GD32_ENET_DMA_BCTL) & ENET_DMA_BCTL_SWR) != 0) && + retries > 0) + { + retries--; + up_mdelay(10); + } + + if (retries == 0) + { + return -ETIMEDOUT; + } + + return 0; +} + +/**************************************************************************** + * Function: gd32_mac_config + * + * Description: + * Configure the ENET MAC for DMA operation. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int gd32_mac_config(struct gd32_enet_mac_s *priv) +{ + uint32_t regval; + + /* Set up the MAC_CFG register */ + + regval = gd32_reg_read(GD32_ENET_MAC_CFG); + regval &= ~ENET_MAC_CFG_CLEAR_BITS; + regval |= ENET_MAC_CFG_SET_BITS; + + if (priv->fduplex) + { + /* Set the DPM bit for full duplex support */ + + regval |= ENET_MAC_CFG_DPM; + } + + if (priv->mbps100) + { + /* Set the SPD bit for 100Mbps fast ENET support */ + + regval |= ENET_MAC_CFG_SPD; + } + + gd32_reg_write(regval, GD32_ENET_MAC_CFG); + + /* Set up the MAC_FRMF register */ + + regval = gd32_reg_read(GD32_ENET_MAC_FRMF); + regval &= ~ENET_MAC_FRMF_CLEAR_BITS; + regval |= ENET_MAC_FRMF_SET_BITS; + gd32_reg_write(regval, GD32_ENET_MAC_FRMF); + + /* Set up the MAC_HLH and MAC_HLL registers */ + + gd32_reg_write(0, GD32_ENET_MAC_HLH); + gd32_reg_write(0, GD32_ENET_MAC_HLL); + + /* Setup up the MAC_FCTL register */ + + regval = gd32_reg_read(GD32_ENET_MAC_FCTL); + regval &= ~ENET_MAC_FCTL_CLEAR_MASK; + regval |= ENET_MAC_FCTL_SET_MASK; + gd32_reg_write(regval, GD32_ENET_MAC_FCTL); + + /* Setup up the MAC_VLT register */ + + gd32_reg_write(0, GD32_ENET_MAC_VLT); + + /* DMA Configuration */ + + /* Set up the DMA_CTL register */ + + regval = gd32_reg_read(GD32_ENET_DMA_CTL); + regval &= ~ENET_DMA_CTL_CLEAR_MASK; + regval |= ENET_DMA_CTL_SET_MASK; + gd32_reg_write(regval, GD32_ENET_DMA_CTL); + + /* Set up the DMA_BCTL register */ + + regval = gd32_reg_read(GD32_ENET_DMA_BCTL); + regval &= ~ENET_DMA_BCTL_CLEAR_MASK; + regval |= ENET_DMA_BCTL_SET_MASK; + gd32_reg_write(regval, GD32_ENET_DMA_BCTL); + + return OK; +} + +/**************************************************************************** + * Function: gd32_mac_address + * + * Description: + * Configure the selected MAC address. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static void gd32_mac_address(struct gd32_enet_mac_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + uint32_t regval; + + ninfo("%s MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->d_ifname, + dev->d_mac.ether.ether_addr_octet[0], + dev->d_mac.ether.ether_addr_octet[1], + dev->d_mac.ether.ether_addr_octet[2], + dev->d_mac.ether.ether_addr_octet[3], + dev->d_mac.ether.ether_addr_octet[4], + dev->d_mac.ether.ether_addr_octet[5]); + + /* Set the MAC address high register */ + + regval = ((uint32_t)dev->d_mac.ether.ether_addr_octet[5] << 8) | + (uint32_t)dev->d_mac.ether.ether_addr_octet[4]; + gd32_reg_write(regval, GD32_ENET_MAC_ADDR0H); + + /* Set the MAC address low register */ + + regval = ((uint32_t)dev->d_mac.ether.ether_addr_octet[3] << 24) | + ((uint32_t)dev->d_mac.ether.ether_addr_octet[2] << 16) | + ((uint32_t)dev->d_mac.ether.ether_addr_octet[1] << 8) | + (uint32_t)dev->d_mac.ether.ether_addr_octet[0]; + gd32_reg_write(regval, GD32_ENET_MAC_ADDR0L); +} + +/**************************************************************************** + * Function: gd32_mac_enable + * + * Description: + * Enable normal MAC operation. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int gd32_mac_enable(struct gd32_enet_mac_s *priv) +{ + uint32_t regval; + + /* Set the MAC address */ + + gd32_mac_address(priv); + + /* Enable transmit state machine of the MAC for transmission on the MII */ + + regval = gd32_reg_read(GD32_ENET_MAC_CFG); + regval |= ENET_MAC_CFG_TEN; + gd32_reg_write(regval, GD32_ENET_MAC_CFG); + + /* Flush Transmit FIFO */ + + regval = gd32_reg_read(GD32_ENET_DMA_CTL); + regval |= ENET_DMA_CTL_FTF; + gd32_reg_write(regval, GD32_ENET_DMA_CTL); + + /* Enable receive state machine of the MAC for reception from the MII */ + + /* Enables or disables the MAC reception. */ + + regval = gd32_reg_read(GD32_ENET_MAC_CFG); + regval |= ENET_MAC_CFG_REN; + gd32_reg_write(regval, GD32_ENET_MAC_CFG); + + /* Start DMA transmission */ + + regval = gd32_reg_read(GD32_ENET_DMA_CTL); + regval |= ENET_DMA_CTL_STE; + gd32_reg_write(regval, GD32_ENET_DMA_CTL); + + /* Start DMA reception */ + + regval = gd32_reg_read(GD32_ENET_DMA_CTL); + regval |= ENET_DMA_CTL_SRE; + gd32_reg_write(regval, GD32_ENET_DMA_CTL); + + /* Enable ENET DMA interrupts. + * + * The gd32 hardware supports two interrupts: (1) one dedicated to normal + * ENET operations and the other, used only for the ENET wakeup + * event. The wake-up interrupt is not used by this driver. + * + * The first ENET vector is reserved for interrupts generated by the + * MAC and the DMA. The MAC provides PMT and time stamp trigger interrupts, + * neither of which are used by this driver. + */ + + gd32_reg_write(ENET_MAC_INTMSK_ALLINTS, GD32_ENET_MAC_INTMSK); + + /* ENET DMA supports two classes of interrupts: Normal interrupt + * summary (NIS) and Abnormal interrupt summary (AIS) with a variety + * individual normal and abnormal interrupting events. Here only + * the normal receive event is enabled (unless DEBUG is enabled). Transmit + * events will only be enabled when a transmit interrupt is expected. + */ + + gd32_reg_write(ENET_DMA_INTEN_RECV_ENABLE | ENET_DMA_INTEN_ERROR_ENABLE, + GD32_ENET_DMA_INTEN); + return OK; +} + +/**************************************************************************** + * Function: gd32_enet_config + * + * Description: + * Configure the ENET interface for DMA operation. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int gd32_enet_config(struct gd32_enet_mac_s *priv) +{ + int ret; + + /* NOTE: The ENET clocks were initialized early in the boot-up + * sequence in gd32f4xx_rcu.c. + */ + + /* Enable ENET clocks */ + + gd32_enet_clock_enable(); + + /* Reset the ENET block */ + + ninfo("Reset the ENET block\n"); + ret = gd32_enet_reset(priv); + if (ret < 0) + { + nerr("ERROR: Reset of ENET block failed\n"); + return ret; + } + + /* Initialize the PHY */ + + ninfo("Initialize the PHY\n"); + ret = gd32_phy_init(priv); + if (ret < 0) + { + return ret; + } + + /* Initialize the MAC and DMA */ + + ninfo("Initialize the MAC and DMA\n"); + ret = gd32_mac_config(priv); + if (ret < 0) + { + return ret; + } + + /* Initialize the free buffer list */ + + gd32_buf_init(priv); + + /* Initialize TX Descriptors list: Chain Mode */ + + gd32_txdes_chain_init(priv); + + /* Initialize RX Descriptors list: Chain Mode */ + + gd32_rxdes_chain_init(priv); + + /* Enable normal MAC operation */ + + ninfo("Enable normal operation\n"); + return gd32_mac_enable(priv); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: gd32_enet_init + * + * Description: + * Initialize the ENET driver for one interface. If the gd32 chip + * supports multiple ENET controllers, then board specific logic + * must implement arm_netinitialize() and call this function to initialize + * the desired interfaces. + * + * Input Parameters: + * intf - In the case where there are multiple ENET_MACs, this value + * identifies which ENET_MAC is to be initialized. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +#if GD32_NETHERNET == 1 || defined(CONFIG_NETDEV_LATEINIT) +static inline +#endif +int gd32_enet_init(int intf) +{ + struct gd32_enet_mac_s *priv; + int ret; + + ninfo("intf: %d\n", intf); + + /* Get the interface structure associated with this interface number. */ + + DEBUGASSERT(intf < GD32_NETHERNET); + priv = &g_enet_mac[intf]; + + /* Initialize the driver structure */ + + memset(priv, 0, sizeof(struct gd32_enet_mac_s)); + priv->dev.d_ifup = gd32_ifup; /* I/F up (new IP address) callback */ + priv->dev.d_ifdown = gd32_ifdown; /* I/F down callback */ + priv->dev.d_txavail = gd32_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_MCASTGROUP + priv->dev.d_addmac = gd32_add_mac; /* Add multicast MAC address */ + priv->dev.d_rmmac = gd32_remove_mac; /* Remove multicast MAC address */ +#endif +#ifdef CONFIG_NETDEV_IOCTL + priv->dev.d_ioctl = gd32_ioctl; /* Support PHY ioctl() calls */ +#endif + priv->dev.d_private = g_enet_mac; /* Used to recover private state from dev */ + + /* Configure GPIO pins to support ENET */ + + gd32_enet_gpio_config(priv); + + /* Attach the IRQ to the driver */ + + if (irq_attach(GD32_IRQ_ENET, gd32_interrupt, NULL)) + { + /* We could not attach the ISR to the interrupt */ + + return -EAGAIN; + } + + /* Put the interface in the down state. */ + + ret = gd32_ifdown(&priv->dev); + if (ret < 0) + { + nerr("ERROR: Initialization of ENET block failed: %d\n", ret); + return ret; + } + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + netdev_register(&priv->dev, NET_LL_ETHERNET); + return OK; +} + +/**************************************************************************** + * Function: arm_netinitialize + * + * Description: + * This is the "standard" network initialization logic called from the + * low-level initialization logic in arm_initialize.c. If GD32_NETHERNET + * greater than one, then board specific logic will have to supply a + * version of arm_netinitialize() that calls gd32_enet_init() with + * the appropriate interface number. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +#if GD32_NETHERNET == 1 && !defined(CONFIG_NETDEV_LATEINIT) +void arm_netinitialize(void) +{ + gd32_enet_init(0); +} +#endif + +#endif /* GD32_NETHERNET > 0 */ +#endif /* CONFIG_NET && CONFIG_GD32F4_ENETMAC */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_enet.h b/arch/arm/src/gd32f4/gd32f4xx_enet.h new file mode 100644 index 0000000000..a3e66ef9cc --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_enet.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_enet.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_ENET_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_ENET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +#if GD32_NETHERNET > 0 +#include "hardware/gd32f4xx_enet.h" +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Function: gd32_phy_boardinitialize + * + * Description: + * Some boards require specialized initialization of the PHY before it can + * be used. This may include such things as configuring GPIOs, resetting + * the PHY, etc. If CONFIG_GD32F4_PHYINIT is defined in the + * configuration then the board specific logic must provide + * gd32_phyinitialize(); The GD32F4 Ethernet driver will call this + * function one time before it first uses the PHY. + * + * Input Parameters: + * intf - Always zero for now. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_GD32F4_PHY_INIT +int gd32_phy_boardinitialize(int intf); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* GD32_NETHERNET > 0 */ +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_ENET_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_exti.c b/arch/arm/src/gd32f4/gd32f4xx_exti.c new file mode 100644 index 0000000000..715ff25cb8 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_exti.c @@ -0,0 +1,621 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_exti.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "chip.h" +#include "gd32f4xx_exti.h" +#include "gd32f4xx.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct gd32_gpio_irq_s +{ + xcpt_t irqhandler; + void *arg; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t g_exti_gpio_irqs[16] = +{ + GD32_IRQ_EXTI0, GD32_IRQ_EXTI1, GD32_IRQ_EXTI2, GD32_IRQ_EXTI3, + GD32_IRQ_EXTI4, GD32_IRQ_EXTI5_9, GD32_IRQ_EXTI5_9, GD32_IRQ_EXTI5_9, + GD32_IRQ_EXTI5_9, GD32_IRQ_EXTI5_9, GD32_IRQ_EXTI10_15, GD32_IRQ_EXTI10_15, + GD32_IRQ_EXTI10_15, GD32_IRQ_EXTI10_15, GD32_IRQ_EXTI10_15, + GD32_IRQ_EXTI10_15 +}; + +/* Interrupt handlers attached to each EXTI */ + +static struct gd32_gpio_irq_s g_gpio_irq_s[16]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * GPIO EXTI linex interrupt handler + ****************************************************************************/ + +static int gd32_exti0_irqhandler(int irq, void *context, void *arg) +{ + int ret = OK; + + /* Clear EXTI line0 pend flag */ + + gd32_exti_interrupt_flag_clear(EXTI_0); + + if (g_gpio_irq_s[0].irqhandler != NULL) + { + xcpt_t irqhandler = g_gpio_irq_s[0].irqhandler; + void *cbarg = g_gpio_irq_s[0].arg; + + ret = irqhandler(irq, context, cbarg); + } + + return ret; +} + +static int gd32_exti1_irqhandler(int irq, void *context, void *arg) +{ + int ret = OK; + + /* Clear EXTI line1 pend flag */ + + gd32_exti_interrupt_flag_clear(EXTI_1); + + if (g_gpio_irq_s[1].irqhandler != NULL) + { + xcpt_t irqhandler = g_gpio_irq_s[1].irqhandler; + void *cbarg = g_gpio_irq_s[1].arg; + + ret = irqhandler(irq, context, cbarg); + } + + return ret; +} + +static int gd32_exti2_irqhandler(int irq, void *context, void *arg) +{ + int ret = OK; + + /* Clear EXTI line2 pend flag */ + + gd32_exti_interrupt_flag_clear(EXTI_2); + + if (g_gpio_irq_s[2].irqhandler != NULL) + { + xcpt_t irqhandler = g_gpio_irq_s[2].irqhandler; + void *cbarg = g_gpio_irq_s[2].arg; + + ret = irqhandler(irq, context, cbarg); + } + + return ret; +} + +static int gd32_exti3_irqhandler(int irq, void *context, void *arg) +{ + int ret = OK; + + /* Clear EXTI line0 pend flag */ + + gd32_exti_interrupt_flag_clear(EXTI_3); + + if (g_gpio_irq_s[3].irqhandler != NULL) + { + xcpt_t irqhandler = g_gpio_irq_s[3].irqhandler; + void *cbarg = g_gpio_irq_s[3].arg; + + ret = irqhandler(irq, context, cbarg); + } + + return ret; +} + +static int gd32_exti4_irqhandler(int irq, void *context, void *arg) +{ + int ret = OK; + + /* Clear EXTI line0 pend flag */ + + gd32_exti_interrupt_flag_clear(EXTI_4); + + if (g_gpio_irq_s[4].irqhandler != NULL) + { + xcpt_t irqhandler = g_gpio_irq_s[4].irqhandler; + void *cbarg = g_gpio_irq_s[4].arg; + + ret = irqhandler(irq, context, cbarg); + } + + return ret; +} + +static int gd32_exti5_9_irqhandler(int irq, void *context, void *arg) +{ + int ret = OK; + uint32_t pd_flag; + uint8_t irq_pin; + + pd_flag = getreg32(GD32_EXTI_PD); + + for (irq_pin = 5; irq_pin <= 9; irq_pin++) + { + /* Check interrupt pend bit */ + + uint32_t pd_bit = (1 << irq_pin); + + if ((pd_flag & pd_bit) != 0) + { + /* Clear interrupt pend bit */ + + gd32_exti_interrupt_flag_clear(pd_bit); + + /* Handle the interrupt */ + + if (g_gpio_irq_s[irq_pin].irqhandler != NULL) + { + xcpt_t irqhandler = g_gpio_irq_s[irq_pin].irqhandler; + void *cbarg = g_gpio_irq_s[irq_pin].arg; + + ret = irqhandler(irq, context, cbarg); + } + } + } + + return ret; +} + +static int gd32_exti10_15_irqhandler(int irq, void *context, void *arg) +{ + int ret = OK; + uint32_t pd_flag = getreg32(GD32_EXTI_PD); + uint8_t irq_pin; + + for (irq_pin = 10; irq_pin <= 15; irq_pin++) + { + /* Check interrupt pend bit */ + + uint32_t pd_bit = (1 << irq_pin); + + if ((pd_flag & pd_bit) != 0) + { + /* Clear interrupt pend bit */ + + gd32_exti_interrupt_flag_clear(pd_bit); + + /* Handle the interrupt */ + + if (g_gpio_irq_s[irq_pin].irqhandler != NULL) + { + xcpt_t irqhandler = g_gpio_irq_s[irq_pin].irqhandler; + void *cbarg = g_gpio_irq_s[irq_pin].arg; + + ret = irqhandler(irq, context, cbarg); + } + } + } + + return ret; +} + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_exti_gpioirq_init + * + * Description: + * Initialize the EXTI gpio irq. + * + * Input Parameters: + * - cfgset: GPIO pin + * - exti_mode: interrupt or event mode + * - trig_type: interrupt trigger type + * - irqnum: pointer to GPIO pin irq + * + ****************************************************************************/ + +int gd32_exti_gpioirq_init(uint32_t cfgset, uint8_t exti_mode, + uint8_t trig_type, uint8_t *irqnum) +{ + uint32_t exti_linex; + uint8_t port; + uint8_t pin; + + /* Verify that this hardware supports the select GPIO port */ + + port = (cfgset & GPIO_CFG_PORT_MASK) >> GPIO_CFG_PORT_SHIFT; + if (port >= GD32_NGPIO_PORTS) + { + return -EINVAL; + } + + /* Get the exti line number */ + + pin = (cfgset & GPIO_CFG_PIN_MASK) >> GPIO_CFG_PIN_SHIFT; + + if (irqnum != NULL) + { + *irqnum = pin; + } + + exti_linex = (1 << pin); + + gd32_syscfg_clock_enable(); + + /* Connect key EXTI line to key GPIO pin */ + + gd32_syscfg_exti_line_config(port, pin); + + /* Configure the interrupt */ + + gd32_exti_init(exti_linex, exti_mode, trig_type); + + gd32_exti_interrupt_flag_clear(exti_linex); + + return OK; +} + +/**************************************************************************** + * Name: gd32_exti_gpio_irq_attach + * + * Description: + * Attach the EXTI gpio irq handler. + * + * Input Parameters: + * - irqpin: GPIO irq pin + * - irqhandler: irq handler + * - arg: Argument passed to the interrupt callback + * + ****************************************************************************/ + +int gd32_exti_gpio_irq_attach(uint8_t irqpin, xcpt_t irqhandler, + void *arg) +{ + switch (g_exti_gpio_irqs[irqpin]) + { + case GD32_IRQ_EXTI0: + irq_attach(GD32_IRQ_EXTI0, gd32_exti0_irqhandler, NULL); + break; + case GD32_IRQ_EXTI1: + irq_attach(GD32_IRQ_EXTI1, gd32_exti1_irqhandler, NULL); + break; + case GD32_IRQ_EXTI2: + irq_attach(GD32_IRQ_EXTI2, gd32_exti2_irqhandler, NULL); + break; + case GD32_IRQ_EXTI3: + irq_attach(GD32_IRQ_EXTI3, gd32_exti3_irqhandler, NULL); + break; + case GD32_IRQ_EXTI4: + irq_attach(GD32_IRQ_EXTI4, gd32_exti4_irqhandler, NULL); + break; + case GD32_IRQ_EXTI5_9: + irq_attach(GD32_IRQ_EXTI5_9, gd32_exti5_9_irqhandler, NULL); + break; + case GD32_IRQ_EXTI10_15: + irq_attach(GD32_IRQ_EXTI10_15, gd32_exti10_15_irqhandler, NULL); + break; + default: + break; + } + + /* Get the old GPIO pin irq handler and set the new GPIO pin irq handler */ + + g_gpio_irq_s[irqpin].irqhandler = irqhandler; + g_gpio_irq_s[irqpin].arg = arg; + + return OK; +} + +/**************************************************************************** + * Name: gd32_exti_init + * + * Description: + * Initialize the EXTI. + * + * Input Parameters: + * - linex: EXTI line number + * - exti_mode: interrupt or event mode + * - trig_type: interrupt trigger type + * + ****************************************************************************/ + +void gd32_exti_init(uint32_t linex, uint8_t exti_mode, uint8_t trig_type) +{ + modifyreg32(GD32_EXTI_INTEN, linex, 0); + modifyreg32(GD32_EXTI_EVEN, linex, 0); + modifyreg32(GD32_EXTI_RTEN, linex, 0); + modifyreg32(GD32_EXTI_FTEN, linex, 0); + + /* set the EXTI mode and enable the interrupts or events from + * EXTI line x + */ + + switch (exti_mode) + { + case EXTI_INTERRUPT: + modifyreg32(GD32_EXTI_INTEN, 0, linex); + break; + case EXTI_EVENT: + modifyreg32(GD32_EXTI_EVEN, 0, linex); + break; + default: + break; + } + + /* set the EXTI trigger type */ + + switch (trig_type) + { + case EXTI_TRIG_RISING: + modifyreg32(GD32_EXTI_RTEN, 0, linex); + break; + case EXTI_TRIG_FALLING: + modifyreg32(GD32_EXTI_FTEN, 0, linex); + break; + case EXTI_TRIG_BOTH: + modifyreg32(GD32_EXTI_RTEN, 0, linex); + modifyreg32(GD32_EXTI_FTEN, 0, linex); + break; + case EXTI_TRIG_NONE: + default: + break; + } +} + +/**************************************************************************** + * Name: gd32_gpio_exti_linex_get + * + * Description: + * Get EXTI GPIO port and linex from GPIO pin. + * + ****************************************************************************/ + +int gd32_gpio_exti_linex_get(uint32_t cfgset, uint32_t *linex) +{ + uint8_t port; + uint8_t pin; + + /* Verify that this hardware supports the select GPIO port */ + + port = (cfgset & GPIO_CFG_PORT_MASK) >> GPIO_CFG_PORT_SHIFT; + if (port >= GD32_NGPIO_PORTS) + { + return -EINVAL; + } + + /* Get the pin number */ + + pin = (cfgset & GPIO_CFG_PIN_MASK) >> GPIO_CFG_PIN_SHIFT; + + *linex = (1 << pin); + + return OK; +} + +/**************************************************************************** + * Name: gd32_gpio_exti_irqnum_get + * + * Description: + * Get EXTI GPIO irq number from GPIO pin. + * + ****************************************************************************/ + +int gd32_gpio_exti_irqnum_get(uint32_t cfgset, uint8_t *irqnum) +{ + uint8_t port; + uint8_t pin; + + /* Verify that this hardware supports the select GPIO port */ + + port = (cfgset & GPIO_CFG_PORT_MASK) >> GPIO_CFG_PORT_SHIFT; + if (port >= GD32_NGPIO_PORTS) + { + return -EINVAL; + } + + /* Get the pin number */ + + pin = (cfgset & GPIO_CFG_PIN_MASK) >> GPIO_CFG_PIN_SHIFT; + + *irqnum = g_exti_gpio_irqs[pin]; + + return OK; +} + +/**************************************************************************** + * Name: gd32_exti_interrupt_enable + * + * Description: + * Enable the interrupts from EXTI line x. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_interrupt_enable(uint32_t linex) +{ + modifyreg32(GD32_EXTI_INTEN, 0, linex); +} + +/**************************************************************************** + * Name: gd32_exti_interrupt_disable + * + * Description: + * Disable the interrupts from EXTI line x. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_interrupt_disable(uint32_t linex) +{ + modifyreg32(GD32_EXTI_INTEN, linex, 0); +} + +/**************************************************************************** + * Name: gd32_exti_event_enable + * + * Description: + * Enable the events from EXTI line x. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_event_enable(uint32_t linex) +{ + modifyreg32(GD32_EXTI_EVEN, 0, linex); +} + +/**************************************************************************** + * Name: gd32_exti_event_disable + * + * Description: + * Disable the events from EXTI line x. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_event_disable(uint32_t linex) +{ + modifyreg32(GD32_EXTI_EVEN, linex, 0); +} + +/**************************************************************************** + * Name: gd32_exti_software_interrupt_enable + * + * Description: + * Enable EXTI software interrupt event. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_software_interrupt_enable(uint32_t linex) +{ + modifyreg32(GD32_EXTI_SWIEV, 0, linex); +} + +/**************************************************************************** + * Name: gd32_exti_software_interrupt_disable + * + * Description: + * Disable EXTI software interrupt event. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_software_interrupt_disable(uint32_t linex) +{ + modifyreg32(GD32_EXTI_SWIEV, linex, 0); +} + +/**************************************************************************** + * Name: gd32_exti_interrupt_flag_get + * + * Description: + * Get EXTI lines flag when the interrupt flag is set. + * + * Input Parameters: + * - linex: EXTI line number + * + * Returned Value: + * status of flag (false or true) + * + ****************************************************************************/ + +bool gd32_exti_interrupt_flag_get(uint32_t linex) +{ + uint32_t regval0; + uint32_t regval1; + + regval0 = (getreg32(GD32_EXTI_PD) & linex); + regval1 = (getreg32(GD32_EXTI_INTEN) & linex); + + if ((regval0 & regval1)) + { + return true; + } + else + { + return false; + } +} + +/**************************************************************************** + * Name: gd32_exti_interrupt_flag_clear + * + * Description: + * Clear EXTI lines pending flag. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_interrupt_flag_clear(uint32_t linex) +{ + putreg32(linex, GD32_EXTI_PD); +} + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_exti.h b/arch/arm/src/gd32f4/gd32f4xx_exti.h new file mode 100644 index 0000000000..4ffaeae300 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_exti.h @@ -0,0 +1,235 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_exti.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_EXTI_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_EXTI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "chip.h" +#include "hardware/gd32f4xx_exti.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_exti_gpioirq_init + * + * Description: + * Initialize the EXTI gpio irq. + * + * Input Parameters: + * - cfgset: GPIO pin + * - exti_mode: interrupt or event mode + * - trig_type: interrupt trigger type + * - irqnum: pointer to GPIO pin irq number + * + ****************************************************************************/ + +int gd32_exti_gpioirq_init(uint32_t cfgset, uint8_t exti_mode, + uint8_t trig_type, uint8_t *irqnum); + +/**************************************************************************** + * Name: gd32_exti_gpio_irq_attach + * + * Description: + * Attach the EXTI gpio irq handler. + * + * Input Parameters: + * - irqpin: GPIO irq pin + * - irqhandler: irq handler + * - arg: Argument passed to the interrupt callback + * + ****************************************************************************/ + +int gd32_exti_gpio_irq_attach(uint8_t irqpin, xcpt_t irqhandler, + void *arg); + +/**************************************************************************** + * Name: gd32_exti_init + * + * Description: + * Initialize the EXTI. + * + * Input Parameters: + * - linex: EXTI line number + * - exti_mode: interrupt or event mode + * - trig_type: interrupt trigger type + * + ****************************************************************************/ + +void gd32_exti_init(uint32_t linex, uint8_t exti_mode, uint8_t trig_type); + +/**************************************************************************** + * Name: gd32_gpio_exti_linex_get + * + * Description: + * Get EXTI GPIO port and linex from GPIO pin. + * + ****************************************************************************/ + +int gd32_gpio_exti_linex_get(uint32_t cfgset, uint32_t *linex); + +/**************************************************************************** + * Name: gd32_gpio_exti_linex_get + * + * Description: + * Get EXTI GPIO port and linex from GPIO pin. + * + ****************************************************************************/ + +int gd32_gpio_exti_irqnum_get(uint32_t cfgset, uint8_t *irqnum); + +/**************************************************************************** + * Name: gd32_exti_interrupt_enable + * + * Description: + * Enable the interrupts from EXTI line x. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_interrupt_enable(uint32_t linex); + +/**************************************************************************** + * Name: gd32_exti_interrupt_disable + * + * Description: + * Disable the interrupts from EXTI line x. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_interrupt_enable(uint32_t linex); + +/**************************************************************************** + * Name: gd32_exti_event_enable + * + * Description: + * Enable the events from EXTI line x. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_event_enable(uint32_t linex); + +/**************************************************************************** + * Name: gd32_exti_event_disable + * + * Description: + * Disable the events from EXTI line x. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_event_disable(uint32_t linex); + +/**************************************************************************** + * Name: gd32_exti_software_interrupt_enable + * + * Description: + * Enable EXTI software interrupt event. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_software_interrupt_enable(uint32_t linex); + +/**************************************************************************** + * Name: gd32_exti_software_interrupt_disable + * + * Description: + * Disable EXTI software interrupt event. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_software_interrupt_disable(uint32_t linex); + +/**************************************************************************** + * Name: gd32_exti_interrupt_flag_get + * + * Description: + * Get EXTI lines flag when the interrupt flag is set. + * + * Input Parameters: + * - linex: EXTI line number + * + * Returned Value: + * status of flag (false or true) + * + ****************************************************************************/ + +bool gd32_exti_interrupt_flag_get(uint32_t linex); + +/**************************************************************************** + * Name: gd32_exti_interrupt_flag_clear + * + * Description: + * Clear EXTI lines pending flag. + * + * Input Parameters: + * - linex: EXTI line number + * + ****************************************************************************/ + +void gd32_exti_interrupt_flag_clear(uint32_t linex); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_EXTI_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_fmc.c b/arch/arm/src/gd32f4/gd32f4xx_fmc.c new file mode 100644 index 0000000000..2716f02b6d --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_fmc.c @@ -0,0 +1,702 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_fmc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include "gd32f4xx_fmc.h" +#include "gd32f4xx.h" + +#if defined(CONFIG_GD32F4_FLASH_CONFIG_DEFAULTT) +# warning "Default Flash Configuration Used - See Override Flash Size Designator" +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static sem_t g_gd32_fmc_sem = SEM_INITIALIZER(1); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_fmc_sem_lock + * + * Description: + * Lock semaphore + * + * Return Value: + * Zero(OK) - On success + * EINVAL - Invalid attempt to get the semaphore + * ECANCELED - May be returned if the thread is canceled while waiting + * + ****************************************************************************/ + +static int gd32_fmc_sem_lock(void) +{ + return nxsem_wait_uninterruptible(&g_gd32_fmc_sem); +} + +/**************************************************************************** + * Name: gd32_fmc_sem_unlock + * + * Description: + * Lock semaphore + * + ****************************************************************************/ + +static void gd32_fmc_sem_unlock(void) +{ + nxsem_post(&g_gd32_fmc_sem); +} + +/**************************************************************************** + * Name: gd32_fmc_state_get + * + * Description: + * Get the FMC state + * + * Returned Value: + * State of FMC + * + ****************************************************************************/ + +static gd32_fmc_state_enum gd32_fmc_state_get(void) +{ + gd32_fmc_state_enum fmc_state = FMC_READY; + + if (getreg32(GD32_FMC_STAT) & FMC_STAT_BUSY) + { + fmc_state = FMC_BUSY; + } + else if (getreg32(GD32_FMC_STAT) & FMC_STAT_RDDERR) + { + fmc_state = FMC_RDDERR; + } + else if (getreg32(GD32_FMC_STAT) & FMC_STAT_PGSERR) + { + fmc_state = FMC_PGSERR; + } + else if (getreg32(GD32_FMC_STAT) & FMC_STAT_PGMERR) + { + fmc_state = FMC_PGMERR; + } + else if (getreg32(GD32_FMC_STAT) & FMC_STAT_WPERR) + { + fmc_state = FMC_WPERR; + } + else if (getreg32(GD32_FMC_STAT) & FMC_STAT_OPERR) + { + fmc_state = FMC_OPERR; + } + else + { + fmc_state = FMC_READY; + } + + /* Return the FMC state */ + + return fmc_state; +} + +/**************************************************************************** + * Name: gd32_fmc_ready_wait + * + * Description: + * Check whether FMC is ready or not + * + * Returned Value: + * State of FMC + * + ****************************************************************************/ + +static gd32_fmc_state_enum gd32_fmc_ready_wait(uint32_t timeout) +{ + gd32_fmc_state_enum fmc_state = FMC_BUSY; + + /* Wait for FMC ready */ + + do + { + /* Get FMC state */ + + fmc_state = gd32_fmc_state_get(); + timeout--; + } + while ((FMC_BUSY == fmc_state) && (timeout > 0)); + + if (0 == timeout) + { + fmc_state = FMC_TOERR; + } + + /* Return the FMC state */ + + return fmc_state; +} + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_fmc_wscnt_set + * + * Description: + * Set the wait state counter value + * + * Parameters: + * wscnt - Wait state counter value + * + ****************************************************************************/ + +void gd32_fmc_wscnt_set(uint32_t wscnt) +{ + uint32_t regval; + + regval = getreg32(GD32_FMC_WS); + + /* set the wait state counter value */ + + regval &= ~FMC_WS_WSCNT_MASK; + regval |= wscnt; + putreg32(regval, GD32_FMC_WS); +} + +/**************************************************************************** + * Name: gd32_fmc_unlock + * + * Description: + * Unlock the main FMC operation + * + ****************************************************************************/ + +int gd32_fmc_unlock(void) +{ + int ret; + + ret = gd32_fmc_sem_lock(); + if (ret < 0) + { + return ret; + } + + if (getreg32(GD32_FMC_CTL) & FMC_CTL_LK) + { + /* Write the FMC key */ + + putreg32(FMC_UNLOCK_KEY0, GD32_FMC_KEY); + putreg32(FMC_UNLOCK_KEY1, GD32_FMC_KEY); + } + + gd32_fmc_sem_unlock(); + + return ret; +} + +/**************************************************************************** + * Name: gd32_fmc_lock + * + * Description: + * Lock the main FMC operation + * + ****************************************************************************/ + +int gd32_fmc_lock(void) +{ + int ret; + + ret = gd32_fmc_sem_lock(); + if (ret < 0) + { + return ret; + } + + /* Set the LK bit */ + + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_LK); + + gd32_fmc_sem_unlock(); + + return ret; +} + +/**************************************************************************** + * Name: gd32_fmc_sector_erase + * + * Description: + * Erase sector + * + * Parameters: + * fmc_sector - Select the sector to erase + * + * Return Value: + * State of FMC + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_sector_erase(uint32_t fmc_sector) +{ + gd32_fmc_state_enum fmc_state = FMC_READY; + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if (FMC_READY == fmc_state) + { + /* Start sector erase */ + + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_SER); + modifyreg32(GD32_FMC_CTL, FMC_CTL_SN_MASK, fmc_sector); + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_START); + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + /* Reset the SER bit */ + + modifyreg32(GD32_FMC_CTL, FMC_CTL_SER, 0); + modifyreg32(GD32_FMC_CTL, FMC_CTL_SN_MASK, 0); + } + + /* return the FMC state */ + + return fmc_state; +} + +/**************************************************************************** + * Name: gd32_fmc_mass_erase + * + * Description: + * Erase whole chip + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_mass_erase(void) +{ + gd32_fmc_state_enum fmc_state = FMC_READY; + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if (FMC_READY == fmc_state) + { + /* Start whole chip erase */ + + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_MER0); + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_MER1); + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_START); + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + /* Reset the MER bits */ + + modifyreg32(GD32_FMC_CTL, FMC_CTL_MER0, 0); + modifyreg32(GD32_FMC_CTL, FMC_CTL_MER1, 0); + } + + /* Return the fmc state */ + + return fmc_state; +} + +/**************************************************************************** + * Name: gd32_fmc_bank0_erase + * + * Description: + * Erase whole bank0 + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_bank0_erase(void) +{ + gd32_fmc_state_enum fmc_state = FMC_READY; + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if (FMC_READY == fmc_state) + { + /* Start FMC bank0 erase */ + + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_MER0); + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_START); + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + /* Reset the MER0 bit */ + + modifyreg32(GD32_FMC_CTL, FMC_CTL_MER0, 0); + } + + /* Return the fmc state */ + + return fmc_state; +} + +/**************************************************************************** + * Name: gd32_fmc_bank1_erase + * + * Description: + * Erase whole bank1 + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_bank1_erase(void) +{ + gd32_fmc_state_enum fmc_state = FMC_READY; + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if (FMC_READY == fmc_state) + { + /* Start FMC bank1 erase */ + + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_MER1); + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_START); + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + /* Reset the MER1 bit */ + + modifyreg32(GD32_FMC_CTL, FMC_CTL_MER1, 0); + } + + /* Return the fmc state */ + + return fmc_state; +} + +/**************************************************************************** + * Name: gd32_fmc_word_program + * + * Description: + * Program a word at the corresponding address + * + * Parameters: + * address - Address to program + * data - Word to program(0x00000000 - 0xFFFFFFFF) + * + * Return Value: + * State of FMC + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_word_program(uint32_t address, uint32_t data) +{ + gd32_fmc_state_enum fmc_state = FMC_READY; + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if (FMC_READY == fmc_state) + { + /* Set the PG bit to start program */ + + modifyreg32(GD32_FMC_CTL, FMC_CTL_PSZ_MASK, FMC_CTL_PSZ_WORD); + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_PG); + + putreg32(data, address); + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + /* Reset the PG bit */ + + modifyreg32(GD32_FMC_CTL, FMC_CTL_PG, 0); + } + + /* Return the FMC state */ + + return fmc_state; +} + +/**************************************************************************** + * Name: gd32_fmc_halfword_program + * + * Description: + * Program a half word at the corresponding address + * + * Parameters: + * address - Address to program + * data - Word to program(0x0000 - 0xFFFF) + * + * Return Value: + * State of FMC + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_halfword_program(uint32_t address, + uint16_t data) +{ + gd32_fmc_state_enum fmc_state = FMC_READY; + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if (FMC_READY == fmc_state) + { + /* Set the PG bit to start program */ + + modifyreg32(GD32_FMC_CTL, FMC_CTL_PSZ_MASK, FMC_CTL_PSZ_HALF_WORD); + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_PG); + + putreg16(data, address); + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + /* Reset the PG bit */ + + modifyreg32(GD32_FMC_CTL, FMC_CTL_PG, 0); + } + + /* Return the FMC state */ + + return fmc_state; +} + +/**************************************************************************** + * Name: gd32_fmc_byte_program + * + * Description: + * Program a byte at the corresponding address + * + * Parameters: + * address - Address to program + * data - Byte to program(0x00 - 0xFF) + * + * Return Value: + * State of FMC + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_byte_program(uint32_t address, uint8_t data) +{ + gd32_fmc_state_enum fmc_state = FMC_READY; + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if (FMC_READY == fmc_state) + { + /* Set the PG bit to start program */ + + modifyreg32(GD32_FMC_CTL, FMC_CTL_PSZ_MASK, FMC_CTL_PSZ_BYTE); + modifyreg32(GD32_FMC_CTL, 0, FMC_CTL_PG); + + putreg8(data, address); + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + /* Reset the PG bit */ + + modifyreg32(GD32_FMC_CTL, FMC_CTL_PG, 0); + } + + /* Return the FMC state */ + + return fmc_state; +} + +/**************************************************************************** + * Name: gd32_ob_unlock + * + * Description: + * Unlock the option byte operation + * + ****************************************************************************/ + +void gd32_ob_unlock(void) +{ + if (getreg32(GD32_FMC_OBCTL0) & FMC_OBCTL0_OB_LK) + { + /* Write the FMC key */ + + putreg32(FMC_OB_UNLOCK_KEY0, GD32_FMC_OBKEY); + putreg32(FMC_OB_UNLOCK_KEY1, GD32_FMC_OBKEY); + } +} + +/**************************************************************************** + * Name: gd32_ob_lock + * + * Description: + * Lock the option byte operation + * + ****************************************************************************/ + +void gd32_ob_lock(void) +{ + /* Reset the OB_LK bit */ + + modifyreg32(GD32_FMC_OBCTL0, 0, FMC_OBCTL0_OB_LK); +} + +/**************************************************************************** + * Name: gd32_ob_start + * + * Description: + * Send option byte change command + * + ****************************************************************************/ + +void gd32_ob_start(void) +{ + /* Set the OB_START bit in OBCTL0 register */ + + modifyreg32(GD32_FMC_OBCTL0, 0, FMC_OBCTL0_OB_START); +} + +/**************************************************************************** + * Name: gd32_ob_write_protection_enable + * + * Description: + * Enable write protection + * + * Parameters: + * ob_wp - Specify sector to be write protected + * + ****************************************************************************/ + +int gd32_ob_write_protection_enable(uint32_t ob_wp) +{ + uint32_t regval0; + uint32_t regval1; + + regval0 = getreg32(GD32_FMC_OBCTL0); + regval1 = getreg32(GD32_FMC_OBCTL1); + + gd32_fmc_state_enum fmc_state = FMC_READY; + if (regval0 & FMC_OBCTL0_DRP) + { + return -1; + } + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if (FMC_READY == fmc_state) + { + regval0 &= (~(uint32_t)ob_wp << 16U); + regval1 &= (~(ob_wp & 0xffff0000u)); + putreg32(regval0, GD32_FMC_OBCTL0); + putreg32(regval1, GD32_FMC_OBCTL1); + + return 0; + } + else + { + return -1; + } +} + +/**************************************************************************** + * Name: gd32_ob_write_protection_disable + * + * Description: + * Disable write protection + * + * Parameters: + * ob_wp - Specify sector to be write protected + * + ****************************************************************************/ + +int gd32_ob_write_protection_disable(uint32_t ob_wp) +{ + uint32_t regval0; + uint32_t regval1; + + regval0 = getreg32(GD32_FMC_OBCTL0); + regval1 = getreg32(GD32_FMC_OBCTL1); + + gd32_fmc_state_enum fmc_state = FMC_READY; + if (regval0 & FMC_OBCTL0_DRP) + { + return -1; + } + + /* Wait for the FMC ready */ + + fmc_state = gd32_fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if (FMC_READY == fmc_state) + { + regval0 |= ((uint32_t)(ob_wp << 16U)); + regval1 |= (ob_wp & 0xffff0000u); + putreg32(regval0, GD32_FMC_OBCTL0); + putreg32(regval1, GD32_FMC_OBCTL1); + + return 0; + } + else + { + return -1; + } +} + +/**************************************************************************** + * Name: gd32_fmc_flag_clear + * + * Description: + * Clear the FMC pending flag + * + * Parameters: + * fmc_flag - FMC flag + * + ****************************************************************************/ + +void gd32_fmc_flag_clear(uint32_t fmc_flag) +{ + /* Clear the flags */ + + modifyreg32(GD32_FMC_STAT, fmc_flag, 0); +} diff --git a/arch/arm/src/gd32f4/gd32f4xx_fmc.h b/arch/arm/src/gd32f4/gd32f4xx_fmc.h new file mode 100644 index 0000000000..3df6d1f7ff --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_fmc.h @@ -0,0 +1,253 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_fmc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_FMC_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_FMC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" +#include "hardware/gd32f4xx_fmc.h" + +/* FMC state */ + +typedef enum +{ + FMC_READY, /* the operation has been completed */ + FMC_BUSY, /* the operation is in progress */ + FMC_RDDERR, /* read D-bus protection error */ + FMC_PGSERR, /* program sequence error */ + FMC_PGMERR, /* program size not match error */ + FMC_WPERR, /* erase/program protection error */ + FMC_OPERR, /* operation error */ + FMC_PGERR, /* program error */ + FMC_TOERR /* timeout error */ +} gd32_fmc_state_enum; + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_fmc_wscnt_set + * + * Description: + * Set the wait state counter value + * + * Parameters: + * wscnt - Wait state counter value + * + ****************************************************************************/ + +void gd32_fmc_wscnt_set(uint32_t wscnt); + +/**************************************************************************** + * Name: gd32_fmc_unlock + * + * Description: + * Unlock the main FMC operation + * + ****************************************************************************/ + +int gd32_fmc_unlock(void); + +/**************************************************************************** + * Name: gd32_fmc_lock + * + * Description: + * Lock the main FMC operation + * + ****************************************************************************/ + +int gd32_fmc_lock(void); + +/**************************************************************************** + * Name: gd32_fmc_sector_erase + * + * Description: + * Erase sector + * + * Parameters: + * fmc_sector - Select the sector to erase + * + * Return Value: + * State of FMC + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_sector_erase(uint32_t fmc_sector); + +/**************************************************************************** + * Name: gd32_fmc_mass_erase + * + * Description: + * Erase whole chip + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_mass_erase(void); + +/**************************************************************************** + * Name: gd32_fmc_bank0_erase + * + * Description: + * Erase whole bank0 + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_bank0_erase(void); + +/**************************************************************************** + * Name: gd32_fmc_bank1_erase + * + * Description: + * Erase whole bank1 + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_bank1_erase(void); + +/**************************************************************************** + * Name: gd32_fmc_word_program + * + * Description: + * Program a word at the corresponding address + * + * Parameters: + * address - Address to program + * data - Word to program(0x00000000 - 0xFFFFFFFF) + * + * Return Value: + * State of FMC + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_word_program(uint32_t address, uint32_t data); + +/**************************************************************************** + * Name: gd32_fmc_word_program + * + * Description: + * Program a half word at the corresponding address + * + * Parameters: + * address - Address to program + * data - Word to program(0x0000 - 0xFFFF) + * + * Return Value: + * State of FMC + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_halfword_program(uint32_t address, + uint16_t data); + +/**************************************************************************** + * Name: gd32_fmc_byte_program + * + * Description: + * Program a byte at the corresponding address + * + * Parameters: + * address - Address to program + * data - Byte to program(0x00 - 0xFF) + * + * Return Value: + * State of FMC + * + ****************************************************************************/ + +gd32_fmc_state_enum gd32_fmc_byte_program(uint32_t address, uint8_t data); + +/**************************************************************************** + * Name: gd32_ob_unlock + * + * Description: + * Unlock the option byte operation + * + ****************************************************************************/ + +void gd32_ob_unlock(void); + +/**************************************************************************** + * Name: gd32_ob_lock + * + * Description: + * Lock the option byte operation + * + ****************************************************************************/ + +void gd32_ob_lock(void); + +/**************************************************************************** + * Name: gd32_ob_start + * + * Description: + * Send option byte change command + * + ****************************************************************************/ + +void gd32_ob_start(void); + +/**************************************************************************** + * Name: gd32_ob_write_protection_enable + * + * Description: + * Enable write protection + * + * Parameters: + * ob_wp - Specify sector to be write protected + * + ****************************************************************************/ + +int gd32_ob_write_protection_enable(uint32_t ob_wp); + +/**************************************************************************** + * Name: gd32_ob_write_protection_disable + * + * Description: + * Disable write protection + * + * Parameters: + * ob_wp - Specify sector to be write protected + * + ****************************************************************************/ + +int gd32_ob_write_protection_disable(uint32_t ob_wp); + +/**************************************************************************** + * Name: gd32_fmc_flag_clear + * + * Description: + * Clear the FMC pending flag + * + * Parameters: + * fmc_flag - FMC flag + * + ****************************************************************************/ + +void gd32_fmc_flag_clear(uint32_t fmc_flag); + +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_FMC_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_gpio.c b/arch/arm/src/gd32f4/gd32f4xx_gpio.c new file mode 100644 index 0000000000..37017fd69b --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_gpio.c @@ -0,0 +1,558 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_gpio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "chip.h" +#include "gd32f4xx_syscfg.h" +#include "gd32f4xx_gpio.h" +#include "gd32f4xx.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Base addresses for each GPIO block */ + +const uint32_t g_gpio_base[GD32_NGPIO_PORTS] = +{ +#if GD32_NGPIO_PORTS > 0 + GD32_GPIOA, +#endif +#if GD32_NGPIO_PORTS > 1 + GD32_GPIOB, +#endif +#if GD32_NGPIO_PORTS > 2 + GD32_GPIOC, +#endif +#if GD32_NGPIO_PORTS > 3 + GD32_GPIOD, +#endif +#if GD32_NGPIO_PORTS > 4 + GD32_GPIOE, +#endif +#if GD32_NGPIO_PORTS > 5 + GD32_GPIOF, +#endif +#if GD32_NGPIO_PORTS > 6 + GD32_GPIOG, +#endif +#if GD32_NGPIO_PORTS > 7 + GD32_GPIOH, +#endif +#if GD32_NGPIO_PORTS > 8 + GD32_GPIOI, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: gd32_gpio_clock_enable + * + * Description: + * + * Enable GPIO clock + * + ****************************************************************************/ + +static void gd32_gpio_clock_enable(uint32_t port_base) +{ + uint32_t rcu_en; + uint32_t regaddr; + + /* Determine which GPIO port to configure */ + + switch (port_base) + { + default: + return; +#if GD32_NGPIO_PORTS > 0 + case GD32_GPIOA: + rcu_en = RCU_AHB1EN_PAEN; + break; +#endif +#if GD32_NGPIO_PORTS > 1 + case GD32_GPIOB: + rcu_en = RCU_AHB1EN_PBEN; + break; +#endif +#if GD32_NGPIO_PORTS > 2 + case GD32_GPIOC: + rcu_en = RCU_AHB1EN_PCEN; + break; +#endif +#if GD32_NGPIO_PORTS > 3 + case GD32_GPIOD: + rcu_en = RCU_AHB1EN_PDEN; + break; +#endif +#if GD32_NGPIO_PORTS > 4 + case GD32_GPIOE: + rcu_en = RCU_AHB1EN_PEEN; + break; +#endif +#if GD32_NGPIO_PORTS > 5 + case GD32_GPIOF: + rcu_en = RCU_AHB1EN_PFEN; + break; +#endif +#if GD32_NGPIO_PORTS > 6 + case GD32_GPIOG: + rcu_en = RCU_AHB1EN_PGEN; + break; +#endif +#if GD32_NGPIO_PORTS > 7 + case GD32_GPIOH: + rcu_en = RCU_AHB1EN_PHEN; + break; +#endif +#if GD32_NGPIO_PORTS > 8 + case GD32_GPIOI: + rcu_en = RCU_AHB1EN_PIEN; + break; +#endif + } + + regaddr = GD32_RCU_AHB1EN; + + /* Check clock if alreay enable. */ + + if (rcu_en != (rcu_en & getreg32(regaddr))) + { + /* Enable/disable AHB clock for GPIO */ + + modifyreg32(regaddr, 0, rcu_en); + } +} + +/**************************************************************************** + * Function: gd32_gpio_output_set + * + * Description: + * + * Set GPIO output + * + ****************************************************************************/ + +static void gd32_gpio_output_set(uint32_t port_base, uint32_t pin, + bool value) +{ + uintptr_t regaddr; + uint32_t regval; + + if (value) + { + regval = GPIO_BOP_SET(pin); + regaddr = GD32_GPIO_BOP(port_base); + } + else + { + regval = GPIO_BC_SET(pin); + regaddr = GD32_GPIO_BC(port_base); + } + + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Function: gd32_gpio_input_get + * + * Description: + * + * Get GPIO input status + * + ****************************************************************************/ + +static inline bool gd32_gpio_input_get(uint32_t port_base, uint32_t pin) +{ + uintptr_t regaddr; + uint32_t regval; + + regaddr = GD32_GPIO_ISTAT(port_base); + regval = getreg32(regaddr); + + return ((regval & GPIO_PIN(pin)) != 0); +} + +/**************************************************************************** + * Name: gd32_gpio_af_config + * + * Description: + * Configure a GPIO pin as the Alternative function. + ****************************************************************************/ + +static void gd32_gpio_af_config(uint32_t cfgset, uint32_t port_base, + uint32_t pin) +{ + uint32_t af_sel; + uint32_t regaddr; + uint32_t regval; + uint32_t pos; + + af_sel = (cfgset & GPIO_CFG_AF_MASK) >> GPIO_CFG_AF_SHIFT; + if (pin < 8) + { + regaddr = GD32_GPIO_AFSEL0(port_base); + pos = pin; + } + else + { + regaddr = GD32_GPIO_AFSEL1(port_base); + pos = pin - 8; + } + + regval = getreg32(regaddr); + regval &= ~GPIO_AF_MASK(pos); + regval |= (af_sel << GPIO_AF_SHIFT(pos)); + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Name: gd32_gpio_af_unconfig + * + * Description: + * Configure a GPIO pin's Alternative function as reset value. + ****************************************************************************/ + +static void gd32_gpio_af_unconfig(uint32_t cfgset, uint32_t port_base, + uint32_t pin) +{ + uint32_t regaddr; + uint32_t regval; + uint32_t pos; + + if (pin < 8) + { + regaddr = GD32_GPIO_AFSEL0(port_base); + pos = pin; + } + else + { + regaddr = GD32_GPIO_AFSEL1(port_base); + pos = pin - 8; + } + + regval = getreg32(regaddr); + regval &= ~GPIO_AF_MASK(pos); + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_gpio_config + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * + * Return value: + * OK on success + * A negated errno value on invalid port or mode. + * + ****************************************************************************/ + +int gd32_gpio_config(uint32_t cfgset) +{ + uint32_t port_base; + uint32_t regval; + uint32_t setting; + uint32_t port; + uint32_t pin; + uint32_t pinmode; + irqstate_t flags; + + /* Interrupts must be disabled from here on out so that we have mutually + * exclusive access to all of the GPIO configuration registers. + */ + + flags = enter_critical_section(); + + /* Verify that this hardware supports the select GPIO port */ + + port = (cfgset & GPIO_CFG_PORT_MASK) >> GPIO_CFG_PORT_SHIFT; + if (port >= GD32_NGPIO_PORTS) + { + return -EINVAL; + } + + /* Get the port base address */ + + port_base = g_gpio_base[port]; + + /* Eable the GPIO port clock */ + + gd32_gpio_clock_enable(port_base); + + /* Get the pin number and select the port configuration register for that + * pin + */ + + pin = (cfgset & GPIO_CFG_PIN_MASK) >> GPIO_CFG_PIN_SHIFT; + + /* Set up the mode register (and remember whether the pin mode) */ + + switch (cfgset & GPIO_CFG_MODE_MASK) + { + /* Input mode */ + + case GPIO_CFG_MODE_INPUT: + pinmode = GPIO_MODE_INPUT; + break; + + /* General purpose output mode */ + + case GPIO_CFG_MODE_OUTPUT: + + /* Set the initial output value */ + + gd32_gpio_write(cfgset, (cfgset & GPIO_CFG_OUTPUT_SET) != 0); + pinmode = GPIO_MODE_OUTPUT; + break; + + /* Alternate function mode */ + + case GPIO_CFG_MODE_AF: + gd32_gpio_af_config(cfgset, port_base, pin); + pinmode = GPIO_MODE_AF; + break; + + /* Analog mode */ + + case GPIO_CFG_MODE_ANALOG: + pinmode = GPIO_MODE_ANALOG; + break; + + default: + return -EINVAL; + break; + } + + regval = getreg32(GD32_GPIO_CTL(port_base)); + regval &= ~GPIO_MODE_MASK(pin); + regval |= ((uint32_t)pinmode << GPIO_MODE_SHIFT(pin)); + putreg32(regval, GD32_GPIO_CTL(port_base)); + + /* Unconfigure alternate function */ + + if (pinmode != GPIO_MODE_AF) + { + gd32_gpio_af_unconfig(cfgset, port_base, pin); + } + + /* Set up the mode register (and remember whether the pin mode) */ + + switch (cfgset & GPIO_CFG_PUPD_MASK) + { + default: + + /* No pull-up, pull-down */ + + case GPIO_CFG_PUPD_NONE: + setting = GPIO_PUPD_NONE; + break; + + /* With pull-up resistor */ + + case GPIO_CFG_PUPD_PULLUP: + setting = GPIO_PUPD_PULLUP; + break; + + /* With pull-down resistor */ + + case GPIO_CFG_PUPD_PULLDOWN: + setting = GPIO_PUPD_PULLDOWN; + break; + } + + regval = getreg32(GD32_GPIO_PUD(port_base)); + regval &= ~GPIO_PUPD_MASK(pin); + regval |= ((uint32_t)setting << GPIO_MODE_SHIFT(pin)); + putreg32(regval, GD32_GPIO_PUD(port_base)); + + /* Set push-pull/open-drain (Only outputs and alternate function pins) */ + + setting = GPIO_OTYPE_OD(pin); + regval = getreg32(GD32_GPIO_OMODE(port_base)); + + if ((pinmode == GPIO_MODE_OUTPUT || pinmode == GPIO_MODE_AF) && + (cfgset & GPIO_CFG_ODPP_MASK) == GPIO_CFG_OD) + { + regval |= setting; + } + else + { + regval &= ~setting; + } + + putreg32(regval, GD32_GPIO_OMODE(port_base)); + + /* Set speed (Only outputs and alternate function pins) */ + + setting = 0; + if (pinmode == GPIO_MODE_OUTPUT || pinmode == GPIO_MODE_AF) + { + switch (cfgset & GPIO_CFG_SPEED_MASK) + { + default: + + /* 2 MHz Low speed output */ + + case GPIO_CFG_SPEED_2MHZ: + setting = GPIO_OSPEED_2MHZ; + break; + + /* 25 MHz Medium speed output */ + + case GPIO_CFG_SPEED_25MHZ: + setting = GPIO_OSPEED_25MHZ; + break; + + /* 50 MHz Fast speed output */ + + case GPIO_CFG_SPEED_50MHZ: + setting = GPIO_OSPEED_50MHZ; + break; + + /* 200 MHz High speed output */ + + case GPIO_CFG_SPEED_200MHZ: + setting = GPIO_OSPEED_200MHZ; + break; + } + } + + regval = getreg32(GD32_GPIO_OSPD(port_base)); + regval &= ~GPIO_OSPEED_MASK(pin); + regval |= (setting << GPIO_OSPEED_SHIFT(pin)); + putreg32(regval, GD32_GPIO_OSPD(port_base)); + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: gd32_gpio_unconfig + * + * Description: + * Unconfigure a GPIO pin based on bit-encoded description of the pin, set + * it into default HiZ state. + * + ****************************************************************************/ + +int gd32_gpio_unconfig(uint32_t cfgset) +{ + /* Reuse port and pin number */ + + cfgset &= GPIO_CFG_PORT_MASK | GPIO_CFG_PIN_MASK; + + /* Set GPIO in floating input mode */ + + cfgset |= GPIO_CFG_MODE_INPUT | GPIO_CFG_PUPD_NONE; + + /* To-Do: Mark its unuse for automatic power saving options */ + + return gd32_gpio_config(cfgset); +} + +/**************************************************************************** + * Name: gd32_gpio_write + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void gd32_gpio_write(uint32_t pinset, bool value) +{ + irqstate_t flags; + uint32_t port_base; + uint32_t port; + uint32_t pin; + + flags = enter_critical_section(); + + port = (pinset & GPIO_CFG_PORT_MASK) >> GPIO_CFG_PORT_SHIFT; + + /* Get the port base address */ + + port_base = g_gpio_base[port]; + + /* Get the pin number */ + + pin = (pinset & GPIO_CFG_PIN_MASK) >> GPIO_CFG_PIN_SHIFT; + + /* Set or clear the output on the pin */ + + gd32_gpio_output_set(port_base, pin, value); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: gd32_gpio_read + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool gd32_gpio_read(uint32_t pinset) +{ + irqstate_t flags; + uint32_t port_base; + uint32_t port; + uint32_t pin; + bool value; + + flags = enter_critical_section(); + + port = (pinset & GPIO_CFG_PORT_MASK) >> GPIO_CFG_PORT_SHIFT; + + /* Get the port base address */ + + port_base = g_gpio_base[port]; + + /* Get the pin number and return the input state of that pin */ + + pin = (pinset & GPIO_CFG_PIN_MASK) >> GPIO_CFG_PIN_SHIFT; + + value = gd32_gpio_input_get(port_base, pin); + + leave_critical_section(flags); + + return value; +} diff --git a/arch/arm/src/gd32f4/gd32f4xx_gpio.h b/arch/arm/src/gd32f4/gd32f4xx_gpio.h new file mode 100644 index 0000000000..b819b77d6a --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_gpio.h @@ -0,0 +1,312 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_gpio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_GPIO_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +# include +#endif + +#include + +#include "chip.h" + +#include "hardware/gd32f4xx_gpio.h" + +/**************************************************************************** + * Pre-Processor Declarations + ****************************************************************************/ + +/* Bit-encoded input to gd32_configgpio() */ + +#if defined(CONFIG_GD32F4_GD32F4XX) +/* Each pin of the general-purpose I/O (GPIO) ports can be individually + * configured by software in several modes. The following definitions provide + * the bit encoding that used to define the pin mode. + * + * 20-bit Encoding: 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ENCODING MMUU OVSS AAAA PPPP BBBB + * GPIO_MODE_INPUT: 00UU .X.. .... PPPP BBBB + * GPIO_MODE_OUTPUT: 01UU OVSS .... PPPP BBBB + * GPIO_MODE_AF: 10UU O.SS AAAA PPPP BBBB + * GPIO_MODE_ANALOG: 11UU .... .... PPPP BBBB + */ + +/* Mode configuration: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * MM.. .... .... .... .... + */ + +#define GPIO_CFG_MODE_SHIFT (18) /* Bits 18-19: GPIO pin mode */ +#define GPIO_CFG_MODE_MASK (3 << GPIO_CFG_MODE_SHIFT) +# define GPIO_CFG_MODE_INPUT (0 << GPIO_CFG_MODE_SHIFT) /* Input mode */ +# define GPIO_CFG_MODE_OUTPUT (1 << GPIO_CFG_MODE_SHIFT) /* General purpose output mode */ +# define GPIO_CFG_MODE_AF (2 << GPIO_CFG_MODE_SHIFT) /* Alternate function mode */ +# define GPIO_CFG_MODE_ANALOG (3 << GPIO_CFG_MODE_SHIFT) /* Analog mode */ + +/* Pull-up/ pull-down definitions: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * ..UU .... .... .... .... + */ + +#define GPIO_CFG_PUPD_SHIFT (16) /* Bits 16-17: Pull-up and pull-down resistors */ +#define GPIO_CFG_PUPD_MASK (3 << GPIO_CFG_PUPD_SHIFT) +# define GPIO_CFG_PUPD_NONE (0 << GPIO_CFG_PUPD_SHIFT) /* No pull-up, pull-down */ +# define GPIO_CFG_PUPD_PULLUP (1 << GPIO_CFG_PUPD_SHIFT) /* With pull-up resistor */ +# define GPIO_CFG_PUPD_PULLDOWN (2 << GPIO_CFG_PUPD_SHIFT) /* With pull-down resistor */ + +/* GPIO output type: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... O... .... .... .... + */ + +#define GPIO_CFG_ODPP_SHIFT (15) /* Bit15: Open drain and push pull mode */ +#define GPIO_CFG_ODPP_MASK (1 << GPIO_CFG_ODPP_SHIFT) +#define GPIO_CFG_OD (1 << GPIO_CFG_ODPP_SHIFT) /* Open drain mode */ +#define GPIO_CFG_PP (0) /* Push pull mode */ + +/* If the pin is a GPIO digital output, then this identifies the initial + * output value. + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .V.. .... .... .... + */ + +#define GPIO_CFG_OUTPUT_SHIFT (14) /* Bit 14: If output, output value */ +#define GPIO_CFG_OUTPUT_MASK (1 << GPIO_CFG_OUTPUT_SHIFT) +#define GPIO_CFG_OUTPUT_SET (1 << GPIO_CFG_OUTPUT_SHIFT) +#define GPIO_CFG_OUTPUT_RESET (0) + +/* External interrupt selection (GPIO inputs only): + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .X.. .... .... .... + */ + +#define GPIO_CFG_EXTI (1 << 14) /* Bit 14: If input, configure as EXTI interrupt */ + +/* GPIO output max speed value: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... SS.. .... .... + */ + +#define GPIO_CFG_SPEED_SHIFT (12) /* Bits 12-13: GPIO speed selection */ +#define GPIO_CFG_SPEED_MASK (3 << GPIO_CFG_SPEED_SHIFT) +# define GPIO_CFG_SPEED_2MHZ (0 << GPIO_CFG_SPEED_SHIFT) /* 2 MHZ Low speed output */ +# define GPIO_CFG_SPEED_25MHZ (1 << GPIO_CFG_SPEED_SHIFT) /* 25 MHZ Medium speed output */ +# define GPIO_CFG_SPEED_50MHZ (2 << GPIO_CFG_SPEED_SHIFT) /* 50 MHZ Fast speed output */ +# define GPIO_CFG_SPEED_200MHZ (3 << GPIO_CFG_SPEED_SHIFT) /* 100 MHZ High speed output */ + +/* GPIO alternate function: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... AAAA .... .... + */ + +#define GPIO_CFG_AF_SHIFT (8) /* Bits 8-11: Alternate function */ +#define GPIO_CFG_AF_MASK (15 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF(n) ((n) << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_0 (0 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_1 (1 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_2 (2 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_3 (3 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_4 (4 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_5 (5 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_6 (6 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_7 (7 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_8 (8 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_9 (9 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_10 (10 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_11 (11 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_12 (12 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_13 (13 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_14 (14 << GPIO_CFG_AF_SHIFT) +# define GPIO_CFG_AF_15 (15 << GPIO_CFG_AF_SHIFT) + +/* This identifies the GPIO port: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... .... PPPP .... + */ + +#define GPIO_CFG_PORT_SHIFT (4) /* Bit 4-7: Port number */ +#define GPIO_CFG_PORT_MASK (15 << GPIO_CFG_PORT_SHIFT) +# define GPIO_CFG_PORT_A (0 << GPIO_CFG_PORT_SHIFT) /* GPIOA */ +# define GPIO_CFG_PORT_B (1 << GPIO_CFG_PORT_SHIFT) /* GPIOB */ +# define GPIO_CFG_PORT_C (2 << GPIO_CFG_PORT_SHIFT) /* GPIOC */ +# define GPIO_CFG_PORT_D (3 << GPIO_CFG_PORT_SHIFT) /* GPIOD */ +# define GPIO_CFG_PORT_E (4 << GPIO_CFG_PORT_SHIFT) /* GPIOE */ +# define GPIO_CFG_PORT_F (5 << GPIO_CFG_PORT_SHIFT) /* GPIOF */ +# define GPIO_CFG_PORT_G (6 << GPIO_CFG_PORT_SHIFT) /* GPIOG */ +# define GPIO_CFG_PORT_H (7 << GPIO_CFG_PORT_SHIFT) /* GPIOH */ +# define GPIO_CFG_PORT_I (8 << GPIO_CFG_PORT_SHIFT) /* GPIOI */ + +/* This identifies the bit in the port: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... .... .... BBBB + */ + +#define GPIO_CFG_PIN_SHIFT (0) /* Bits 0-3: GPIO number: 0-15 */ +#define GPIO_CFG_PIN_MASK (15 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_0 (0 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_1 (1 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_2 (2 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_3 (3 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_4 (4 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_5 (5 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_6 (6 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_7 (7 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_8 (8 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_9 (9 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_10 (10 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_11 (11 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_12 (12 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_13 (13 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_14 (14 << GPIO_CFG_PIN_SHIFT) +# define GPIO_CFG_PIN_15 (15 << GPIO_CFG_PIN_SHIFT) + +#else +# error "Unknown GD32 chip" +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* Base addresses for each GPIO block */ + +EXTERN const uint32_t g_gpio_base[GD32_NGPIO_PORTS]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_gpio_config + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * + * Return value: + * OK on success + * A negated errno value on invalid port or mode. + ****************************************************************************/ + +int gd32_gpio_config(uint32_t cfgset); + +/**************************************************************************** + * Name: gd32_gpio_unconfig + * + * Description: + * Unconfigure a GPIO pin based on bit-encoded description of the pin, set + * it into default HiZ state. + * + * Returned Value: + * OK on success + * A negated errno value on invalid port or mode + ****************************************************************************/ + +int gd32_gpio_unconfig(uint32_t cfgset); + +/**************************************************************************** + * Name: gd32_gpiowrite + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void gd32_gpio_write(uint32_t pinset, bool value); + +/**************************************************************************** + * Name: gd32_gpio_read + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool gd32_gpio_read(uint32_t pinset); + +/**************************************************************************** + * Function: gd32_dump_gpio + * + * Description: + * Dump all GPIO registers associated with the base address of the provided + * pinset. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +int gd32_dump_gpio(uint32_t pinset, const char *msg); +#else +# define gd32_dump_gpio(p,m) +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_GPIO_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_idle.c b/arch/arm/src/gd32f4/gd32f4xx_idle.c new file mode 100644 index 0000000000..2ca4fbcb06 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_idle.c @@ -0,0 +1,173 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_idle.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include + +#include "chip.h" +#include "gd32f4xx_pmu.h" +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Does the board support an IDLE LED to indicate that the board is in the + * IDLE state? + */ + +#if defined(CONFIG_ARCH_LEDS) && defined(LED_IDLE) +# define BEGIN_IDLE() board_autoled_on(LED_IDLE) +# define END_IDLE() board_autoled_off(LED_IDLE) +#else +# define BEGIN_IDLE() +# define END_IDLE() +#endif + +#define PM_IDLE_DOMAIN 0 /* Revisit */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idlepm + * + * Description: + * Perform IDLE state power management. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void up_idlepm(void) +{ + static enum pm_state_e oldstate = PM_NORMAL; + enum pm_state_e newstate; + irqstate_t flags; + int ret; + + /* Decide, which power saving level can be obtained */ + + newstate = pm_checkstate(PM_IDLE_DOMAIN); + + /* Check for state changes */ + + if (newstate != oldstate) + { + flags = enter_critical_section(); + + /* Perform board-specific, state-dependent logic here */ + + _info("newstate= %d oldstate=%d\n", newstate, oldstate); + + /* Then force the global state change */ + + ret = pm_changestate(PM_IDLE_DOMAIN, newstate); + if (ret < 0) + { + /* The new state change failed, revert to the preceding state */ + + pm_changestate(PM_IDLE_DOMAIN, oldstate); + } + else + { + /* Save the new state */ + + oldstate = newstate; + } + + /* MCU-specific power management logic */ + + switch (newstate) + { + case PM_NORMAL: + break; + + case PM_IDLE: + break; + + case PM_STANDBY: + gd32_pmstop(true); + break; + + case PM_SLEEP: + gd32_pmstandby(); + break; + + default: + break; + } + + leave_critical_section(flags); + } +} +#else +# define up_idlepm() +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when there is no other + * ready-to-run task. This is processor idle time and will continue until + * some interrupt occurs to cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., this is where + * power management operations might be performed. + * + ****************************************************************************/ + +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, then process + * "fake" timer interrupts. Hopefully, something will wake up. + */ + + nxsched_process_timer(); +#else + + /* Perform IDLE mode power management */ + + up_idlepm(); + +#if !defined(CONFIG_DEBUG_SYMBOLS) + BEGIN_IDLE(); + asm("WFI"); + END_IDLE(); +#endif +#endif +} diff --git a/arch/arm/src/gd32f4/gd32f4xx_irq.c b/arch/arm/src/gd32f4/gd32f4xx_irq.c new file mode 100644 index 0000000000..70b79319b3 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_irq.c @@ -0,0 +1,556 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_irq.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "nvic.h" +#ifdef CONFIG_ARCH_RAMVECTORS +# include "ram_vectors.h" +#endif +#include "arm_internal.h" +#include "gd32f4xx.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Get a 32-bit version of the default priority */ + +#define DEFPRIORITY32 \ + (NVIC_SYSH_PRIORITY_DEFAULT << 24 | \ + NVIC_SYSH_PRIORITY_DEFAULT << 16 | \ + NVIC_SYSH_PRIORITY_DEFAULT << 8 | \ + NVIC_SYSH_PRIORITY_DEFAULT) + +/* Given the address of a NVIC ENABLE register, this is the offset to + * the corresponding CLEAR ENABLE register. + */ + +#define NVIC_ENA_OFFSET (0) +#define NVIC_CLRENA_OFFSET (NVIC_IRQ0_31_CLEAR - NVIC_IRQ0_31_ENABLE) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* g_current_regs[] holds a references to the current interrupt level + * register storage structure. If is non-NULL only during interrupt + * processing. Access to g_current_regs[] must be through the macro + * CURRENT_REGS for portability. + */ + +volatile uint32_t *g_current_regs[1]; + +/* This is the address of the exception vector table (determined by the + * linker script). + */ + +extern uint32_t _vectors[]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_dumpnvic + * + * Description: + * Dump some interesting NVIC registers + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_IRQ_INFO) +static void gd32_dumpnvic(const char *msg, int irq) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + irqinfo("NVIC (%s, irq=%d):\n", msg, irq); + irqinfo(" INTCTRL: %08x VECTAB: %08x\n", + getreg32(NVIC_INTCTRL), getreg32(NVIC_VECTAB)); +#if 0 + irqinfo(" SYSH ENABLE MEMFAULT: %08x BUSFAULT: %08x USGFAULT: %08x " + "SYSTICK: %08x\n", + getreg32(NVIC_SYSHCON_MEMFAULTENA), + getreg32(NVIC_SYSHCON_BUSFAULTENA), + getreg32(NVIC_SYSHCON_USGFAULTENA), + getreg32(NVIC_SYSTICK_CTRL_ENABLE)); +#endif + irqinfo(" IRQ ENABLE: %08x %08x %08x\n", + getreg32(NVIC_IRQ0_31_ENABLE), + getreg32(NVIC_IRQ32_63_ENABLE), + getreg32(NVIC_IRQ64_95_ENABLE)); + irqinfo(" SYSH_PRIO: %08x %08x %08x\n", + getreg32(NVIC_SYSH4_7_PRIORITY), + getreg32(NVIC_SYSH8_11_PRIORITY), + getreg32(NVIC_SYSH12_15_PRIORITY)); + irqinfo(" IRQ PRIO: %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ0_3_PRIORITY), + getreg32(NVIC_IRQ4_7_PRIORITY), + getreg32(NVIC_IRQ8_11_PRIORITY), + getreg32(NVIC_IRQ12_15_PRIORITY)); + irqinfo(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ16_19_PRIORITY), + getreg32(NVIC_IRQ20_23_PRIORITY), + getreg32(NVIC_IRQ24_27_PRIORITY), + getreg32(NVIC_IRQ28_31_PRIORITY)); + irqinfo(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ32_35_PRIORITY), + getreg32(NVIC_IRQ36_39_PRIORITY), + getreg32(NVIC_IRQ40_43_PRIORITY), + getreg32(NVIC_IRQ44_47_PRIORITY)); + irqinfo(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ48_51_PRIORITY), + getreg32(NVIC_IRQ52_55_PRIORITY), + getreg32(NVIC_IRQ56_59_PRIORITY), + getreg32(NVIC_IRQ60_63_PRIORITY)); + irqinfo(" %08x\n", + getreg32(NVIC_IRQ64_67_PRIORITY), + getreg32(NVIC_IRQ68_71_PRIORITY), + getreg32(NVIC_IRQ72_75_PRIORITY), + getreg32(NVIC_IRQ76_79_PRIORITY)); +#if GD32_IRQ_NEXTINT > 80 + irqinfo(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ80_83_PRIORITY), + getreg32(NVIC_IRQ84_87_PRIORITY), + getreg32(NVIC_IRQ88_91_PRIORITY), + getreg32(NVIC_IRQ92_95_PRIORITY)); +#endif + + leave_critical_section(flags); +} +#else +# define gd32_dumpnvic(msg, irq) +#endif + +/**************************************************************************** + * Name: gd32_nmi, gd32_busfault, gd32_usagefault, gd32_pendsv, + * gd32_dbgmonitor, gd32_pendsv, gd32_reserved + * + * Description: + * Handlers for various exceptions. None are handled and all are fatal + * error conditions. The only advantage these provided over the default + * unexpected interrupt handler is that they provide a diagnostic output. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +static int gd32_nmi(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! NMI received\n"); + PANIC(); + return 0; +} + +static int gd32_busfault(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! Bus fault received: %08" PRIx32 "\n", + getreg32(NVIC_CFAULTS)); + PANIC(); + return 0; +} + +static int gd32_usagefault(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! Usage fault received: %08" PRIx32 "\n", + getreg32(NVIC_CFAULTS)); + PANIC(); + return 0; +} + +static int gd32_pendsv(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! PendSV received\n"); + PANIC(); + return 0; +} + +static int gd32_dbgmonitor(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! Debug Monitor received\n"); + PANIC(); + return 0; +} + +static int gd32_reserved(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! Reserved interrupt\n"); + PANIC(); + return 0; +} +#endif + +/**************************************************************************** + * Name: gd32_prioritize_syscall + * + * Description: + * Set the priority of an exception. This function may be needed + * internally even if support for prioritized interrupts is not enabled. + * + ****************************************************************************/ + +#ifdef CONFIG_ARMV7M_USEBASEPRI +static inline void gd32_prioritize_syscall(int priority) +{ + uint32_t regval; + + /* SVCALL is system handler 11 */ + + regval = getreg32(NVIC_SYSH8_11_PRIORITY); + regval &= ~NVIC_SYSH_PRIORITY_PR11_MASK; + regval |= (priority << NVIC_SYSH_PRIORITY_PR11_SHIFT); + putreg32(regval, NVIC_SYSH8_11_PRIORITY); +} +#endif + +/**************************************************************************** + * Name: gd32_irqinfo + * + * Description: + * Given an IRQ number, provide the register and bit setting to enable or + * disable the irq. + * + ****************************************************************************/ + +static int gd32_irqinfo(int irq, uintptr_t *regaddr, uint32_t *bit, + uintptr_t offset) +{ + int n; + + DEBUGASSERT(irq >= GD32_IRQ_NMI && irq < NR_IRQS); + + /* Check for external interrupt */ + + if (irq >= GD32_IRQ_EXINT) + { + n = irq - GD32_IRQ_EXINT; + *regaddr = NVIC_IRQ_ENABLE(n) + offset; + *bit = (uint32_t)1 << (n & 0x1f); + } + + /* Handle processor exceptions. Only a few can be disabled */ + + else + { + *regaddr = NVIC_SYSHCON; + if (irq == GD32_IRQ_MEMFAULT) + { + *bit = NVIC_SYSHCON_MEMFAULTENA; + } + else if (irq == GD32_IRQ_BUSFAULT) + { + *bit = NVIC_SYSHCON_BUSFAULTENA; + } + else if (irq == GD32_IRQ_USAGEFAULT) + { + *bit = NVIC_SYSHCON_USGFAULTENA; + } + else if (irq == GD32_IRQ_SYSTICK) + { + *regaddr = NVIC_SYSTICK_CTRL; + *bit = NVIC_SYSTICK_CTRL_ENABLE; + } + else + { + return ERROR; /* Invalid or unsupported exception */ + } + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + ****************************************************************************/ + +void up_irqinitialize(void) +{ + uint32_t regaddr; + int num_priority_registers; + int i; + + /* Disable all interrupts */ + + for (i = 0; i < NR_IRQS - GD32_IRQ_EXINT; i += 32) + { + putreg32(0xffffffff, NVIC_IRQ_CLEAR(i)); + } + + /* Make sure that we are using the correct vector table. The default + * vector address is 0x0000:0000 but if we are executing code that is + * positioned in SRAM or in external FLASH, then we may need to reset + * the interrupt vector so that it refers to the table in SRAM or in + * external FLASH. + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + * vector table that requires special initialization. + */ + + arm_ramvec_initialize(); +#endif + + /* Set all interrupts (and exceptions) to the default priority */ + + putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY); + + /* The NVIC ICTR register (bits 0-4) holds the number of interrupt + * lines that the NVIC supports: + * + * 0 -> 32 interrupt lines, 8 priority registers + * 1 -> 64 " " " ", 16 priority registers + * 2 -> 96 " " " ", 32 priority registers + * ... + */ + + num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8; + + /* Now set all of the interrupt lines to the default priority */ + + regaddr = NVIC_IRQ0_3_PRIORITY; + while (num_priority_registers--) + { + putreg32(DEFPRIORITY32, regaddr); + regaddr += 4; + } + + /* currents_regs is non-NULL only while processing an interrupt */ + + CURRENT_REGS = NULL; + + /* Attach the SVCall and Hard Fault exception handlers. The SVCall + * exception is used for performing context switches; The Hard Fault + * must also be caught because a SVCall may show up as a Hard Fault + * under certain conditions. + */ + + irq_attach(GD32_IRQ_SVCALL, arm_svcall, NULL); + irq_attach(GD32_IRQ_HARDFAULT, arm_hardfault, NULL); + + /* Set the priority of the SVCall interrupt */ + +#ifdef CONFIG_ARCH_IRQPRIO + /* up_prioritize_irq(GD32_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); */ +#endif +#ifdef CONFIG_ARMV7M_USEBASEPRI + gd32_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY); +#endif + + /* If the MPU is enabled, then attach and enable the Memory Management + * Fault handler. + */ + +#ifdef CONFIG_ARM_MPU + irq_attach(GD32_IRQ_MEMFAULT, arm_memfault, NULL); + up_enable_irq(GD32_IRQ_MEMFAULT); +#endif + +#if defined(CONFIG_RTC) && !defined(CONFIG_RTC_EXTERNAL) +# error "RTC is not ready now!" + + /* RTC was initialized earlier but IRQs weren't ready at that time */ + + gd32_rtc_irqinitialize(); +#endif + + /* Attach all other processor exceptions (except reset and sys tick) */ + +#ifdef CONFIG_DEBUG_FEATURES + irq_attach(GD32_IRQ_NMI, gd32_nmi, NULL); +#ifndef CONFIG_ARM_MPU + irq_attach(GD32_IRQ_MEMFAULT, arm_memfault, NULL); +#endif + irq_attach(GD32_IRQ_BUSFAULT, gd32_busfault, NULL); + irq_attach(GD32_IRQ_USAGEFAULT, gd32_usagefault, NULL); + irq_attach(GD32_IRQ_PENDSV, gd32_pendsv, NULL); + irq_attach(GD32_IRQ_DBGMONITOR, gd32_dbgmonitor, NULL); + irq_attach(GD32_IRQ_RESERVED, gd32_reserved, NULL); +#endif + + gd32_dumpnvic("initial", NR_IRQS); + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + + /* And finally, enable interrupts */ + + up_irq_enable(); +#endif +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (gd32_irqinfo(irq, ®addr, &bit, NVIC_CLRENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to disable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Clear Enable register. For other exceptions, we need to + * clear the bit in the System Handler Control and State Register. + */ + + if (irq >= GD32_IRQ_EXINT) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval &= ~bit; + putreg32(regval, regaddr); + } + } +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (gd32_irqinfo(irq, ®addr, &bit, NVIC_ENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to enable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Set Enable register. For other exceptions, we need to + * set the bit in the System Handler Control and State Register. + */ + + if (irq >= GD32_IRQ_EXINT) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval |= bit; + putreg32(regval, regaddr); + } + } +} + +/**************************************************************************** + * Name: arm_ack_irq + * + * Description: + * Acknowledge the IRQ + * + ****************************************************************************/ + +void arm_ack_irq(int irq) +{ +} + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * Set the priority of an IRQ. + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQPRIO +int up_prioritize_irq(int irq, int priority) +{ + uint32_t regaddr; + uint32_t regval; + int shift; + + DEBUGASSERT(irq >= GD32_IRQ_MEMFAULT && irq < NR_IRQS && + (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); + + if (irq < GD32_IRQ_EXINT) + { + /* NVIC_SYSH_PRIORITY() maps {0..15} to one of three priority + * registers (0-3 are invalid) + */ + + regaddr = NVIC_SYSH_PRIORITY(irq); + irq -= 4; + } + else + { + /* NVIC_IRQ_PRIORITY() maps {0..} to one of many priority registers */ + + irq -= GD32_IRQ_EXINT; + regaddr = NVIC_IRQ_PRIORITY(irq); + } + + regval = getreg32(regaddr); + shift = ((irq & 3) << 3); + regval &= ~(0xff << shift); + regval |= (priority << shift); + putreg32(regval, regaddr); + + gd32_dumpnvic("prioritize", irq); + return OK; +} +#endif diff --git a/arch/arm/src/gd32f4/gd32f4xx_lowputc.c b/arch/arm/src/gd32f4/gd32f4xx_lowputc.c new file mode 100644 index 0000000000..fde3db1e30 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_lowputc.c @@ -0,0 +1,596 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_lowputc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "arm_internal.h" + +#include "chip.h" + +#include "gd32f4xx.h" +#include "gd32f4xx_rcu.h" +#include "gd32f4xx_gpio.h" +#include "gd32f4xx_usart.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Select USART parameters for the selected console */ + +#ifdef HAVE_CONSOLE +# if defined(CONFIG_USART0_SERIAL_CONSOLE) +# define GD32_CONSOLE_BASE GD32_USART0 +# define GD32_CONSOLE_APBEN_REG GD32_RCU_APB2EN +# define GD32_CONSOLE_APBEN RCU_APB2EN_USART0EN +# define GD32_CONSOLE_CLOCK GD32_PCLK2_FREQUENCY +# define GD32_CONSOLE_BAUD CONFIG_USART0_BAUD +# define GD32_CONSOLE_PARITY CONFIG_USART0_PARITY +# define GD32_CONSOLE_NBITS CONFIG_USART0_BITS +# define GD32_CONSOLE_2STOP CONFIG_USART0_2STOP +# define GD32_CONSOLE_TX GPIO_USART0_TX +# define GD32_CONSOLE_RX GPIO_USART0_RX +# ifdef CONFIG_USART0_RS485 +# define GD32_CONSOLE_RS485_DIR GPIO_USART0_RS485_DIR +# if (CONFIG_USART0_RS485_DIR_POLARITY == 0) +# define GD32_CONSOLE_RS485_DIR_POLARITY false +# else +# define GDM32_CONSOLE_RS485_DIR_POLARITY true +# endif +# endif +# elif defined(CONFIG_USART1_SERIAL_CONSOLE) +# define GD32_CONSOLE_BASE GD32_USART1 +# define GD32_CONSOLE_APBEN_REG GD32_RCU_APB1EN +# define GD32_CONSOLE_APBEN RCU_APB1EN_USART1EN +# define GD32_CONSOLE_CLOCK GD32_PCLK1_FREQUENCY +# define GD32_CONSOLE_BAUD CONFIG_USART1_BAUD +# define GD32_CONSOLE_PARITY CONFIG_USART1_PARITY +# define GD32_CONSOLE_NBITS CONFIG_USART1_BITS +# define GD32_CONSOLE_2STOP CONFIG_USART1_2STOP +# define GD32_CONSOLE_TX GPIO_USART1_TX +# define GD32_CONSOLE_RX GPIO_USART1_RX +# ifdef CONFIG_USART1_RS485 +# define GD32_CONSOLE_RS485_DIR GPIO_USART1_RS485_DIR +# if (CONFIG_USART1_RS485_DIR_POLARITY == 0) +# define GD32_CONSOLE_RS485_DIR_POLARITY false +# else +# define GD32_CONSOLE_RS485_DIR_POLARITY true +# endif +# endif +# elif defined(CONFIG_USART2_SERIAL_CONSOLE) +# define GD32_CONSOLE_BASE GD32_USART2 +# define GD32_CONSOLE_APBEN_REG GD32_RCU_APB1EN +# define GD32_CONSOLE_APBEN RCU_APB1ENR_USART3EN +# define GD32_CONSOLE_CLOCK GD32_PCLK1_FREQUENCY +# define GD32_CONSOLE_BAUD CONFIG_USART2_BAUD +# define GD32_CONSOLE_PARITY CONFIG_USART2_PARITY +# define GD32_CONSOLE_NBITS CONFIG_USART2_BITS +# define GD32_CONSOLE_2STOP CONFIG_USART2_2STOP +# define GD32_CONSOLE_TX GPIO_USART2_TX +# define GD32_CONSOLE_RX GPIO_USART2_RX +# ifdef CONFIG_USART2_RS485 +# define GD32_CONSOLE_RS485_DIR GPIO_USART2_RS485_DIR +# if (CONFIG_USART2_RS485_DIR_POLARITY == 0) +# define GD32_CONSOLE_RS485_DIR_POLARITY false +# else +# define GD32_CONSOLE_RS485_DIR_POLARITY true +# endif +# endif +# elif defined(CONFIG_UART3_SERIAL_CONSOLE) +# define GD32_CONSOLE_BASE GD32_UART3 +# define GD32_CONSOLE_APBEN_REG GD32_RCU_APB1EN +# define GD32_CONSOLE_APBEN RCU_APB1EN_UART3EN +# define GD32_CONSOLE_CLOCK GD32_PCLK1_FREQUENCY +# define GD32_CONSOLE_BAUD CONFIG_UART3_BAUD +# define GD32_CONSOLE_PARITY CONFIG_UART3_PARITY +# define GD32_CONSOLE_NBITS CONFIG_UART3_BITS +# define GD32_CONSOLE_2STOP CONFIG_UART3_2STOP +# define GD32_CONSOLE_TX GPIO_UART3_TX +# define GD32_CONSOLE_RX GPIO_UART3_RX +# ifdef CONFIG_UART3_RS485 +# define GD32_CONSOLE_RS485_DIR GPIO_UART3_RS485_DIR +# if (CONFIG_UART3_RS485_DIR_POLARITY == 0) +# define GD32_CONSOLE_RS485_DIR_POLARITY false +# else +# define GD32_CONSOLE_RS485_DIR_POLARITY true +# endif +# endif +# elif defined(CONFIG_UART4_SERIAL_CONSOLE) +# define GD32_CONSOLE_BASE GD32_UART4 +# define GD32_CONSOLE_APBEN_REG GD32_RCU_APB1EN +# define GD32_CONSOLE_APBEN RCU_APB1EN_UART4EN +# define GD32_CONSOLE_CLOCK GD32_PCLK1_FREQUENCY +# define GD32_CONSOLE_BAUD CONFIG_UART4_BAUD +# define GD32_CONSOLE_PARITY CONFIG_UART4_PARITY +# define GD32_CONSOLE_NBITS CONFIG_UART4_BITS +# define GD32_CONSOLE_2STOP CONFIG_UART4_2STOP +# define GD32_CONSOLE_TX GPIO_UART4_TX +# define GD32_CONSOLE_RX GPIO_UART4_RX +# ifdef CONFIG_UART4_RS485 +# define GD32_CONSOLE_RS485_DIR GPIO_UART4_RS485_DIR +# if (CONFIG_UART4_RS485_DIR_POLARITY == 0) +# define GD32_CONSOLE_RS485_DIR_POLARITY false +# else +# define GD32_CONSOLE_RS485_DIR_POLARITY true +# endif +# endif +# elif defined(CONFIG_USART5_SERIAL_CONSOLE) +# define GD32_CONSOLE_BASE GD32_USART5 +# define GD32_CONSOLE_APBEN_REG GD32_RCU_APB2EN +# define GD32_CONSOLE_APBEN RCU_APB2EN_USART5EN +# define GD32_CONSOLE_CLOCK GD32_PCLK2_FREQUENCY +# define GD32_CONSOLE_BAUD CONFIG_USART5_BAUD +# define GD32_CONSOLE_PARITY CONFIG_USART5_PARITY +# define GD32_CONSOLE_NBITS CONFIG_USART5_BITS +# define GD32_CONSOLE_2STOP CONFIG_USART5_2STOP +# define GD32_CONSOLE_TX GPIO_USART5_TX +# define GD32_CONSOLE_RX GPIO_USART5_RX +# ifdef CONFIG_USART5_RS485 +# define GD32_CONSOLE_RS485_DIR GPIO_USART5_RS485_DIR +# if (CONFIG_USART5_RS485_DIR_POLARITY == 0) +# define GD32_CONSOLE_RS485_DIR_POLARITY false +# else +# define GD32_CONSOLE_RS485_DIR_POLARITY true +# endif +# endif +# elif defined(CONFIG_UART6_SERIAL_CONSOLE) +# define GD32_CONSOLE_BASE GD32_UART6 +# define GD32_CONSOLE_APBEN_REG GD32_RCU_APB1EN +# define GD32_CONSOLE_APBEN RCU_APB1EN_UART6EN +# define GD32_CONSOLE_CLOCK GD32_PCLK1_FREQUENCY +# define GD32_CONSOLE_BAUD CONFIG_UART6_BAUD +# define GD32_CONSOLE_PARITY CONFIG_UART6_PARITY +# define GD32_CONSOLE_NBITS CONFIG_UART6_BITS +# define GD32_CONSOLE_2STOP CONFIG_UART6_2STOP +# define GD32_CONSOLE_TX GPIO_UART6_TX +# define GD32_CONSOLE_RX GPIO_UART6_RX +# ifdef CONFIG_UART6_RS485 +# define GD32_CONSOLE_RS485_DIR GPIO_UART6_RS485_DIR +# if (CONFIG_UART6_RS485_DIR_POLARITY == 0) +# define GD32_CONSOLE_RS485_DIR_POLARITY false +# else +# define GD32_CONSOLE_RS485_DIR_POLARITY true +# endif +# endif +# elif defined(CONFIG_UART7_SERIAL_CONSOLE) +# define GD32_CONSOLE_BASE GD32_UART7 +# define GD32_CONSOLE_APBEN_REG GD32_RCU_APB1EN +# define GD32_CONSOLE_APBEN RCU_APB1ENR_UART7EN +# define GD32_CONSOLE_CLOCK GD32_PCLK1_FREQUENCY +# define GD32_CONSOLE_BAUD CONFIG_UART7_BAUD +# define GD32_CONSOLE_PARITY CONFIG_UART7_PARITY +# define GD32_CONSOLE_NBITS CONFIG_UART7_BITS +# define GD32_CONSOLE_2STOP CONFIG_UART7_2STOP +# define GD32_CONSOLE_TX GPIO_UART7_TX +# define GD32_CONSOLE_RX GPIO_UART7_RX +# ifdef CONFIG_UART7_RS485 +# define GD32_CONSOLE_RS485_DIR GPIO_UART7_RS485_DIR +# if (CONFIG_UART7_RS485_DIR_POLARITY == 0) +# define GD32_CONSOLE_RS485_DIR_POLARITY false +# else +# define GD32_CONSOLE_RS485_DIR_POLARITY true +# endif +# endif +# endif + +/* CTL0 settings */ + +# if GD32_CONSOLE_NBITS == 9 +# define USART_CTL0_WL_VALUE USART_WL_9BIT +# else +# define USART_CTL0_WL_VALUE USART_WL_8BIT +# endif + +# if GD32_CONSOLE_PARITY == 1 +# define USART_CTL0_PARITY_VALUE USART_CTL0_PM_ODD +# elif GD32_CONSOLE_PARITY == 2 +# define USART_CTL0_PARITY_VALUE USART_CTL0_PM_EVEN +# else +# define USART_CTL0_PARITY_VALUE USART_CTL0_PM_NONE +# endif + +/* CTL1 settings */ + +# if GD32_CONSOLE_2STOP != 0 +# define USART_USART_CTL1_STB2BIT_VALUE USART_CTL1_STB2BIT +# else +# define USART_USART_CTL1_STB2BIT_VALUE USART_CTL1_STB1BIT +# endif + +#endif /* HAVE_CONSOLE */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_lowputc + * + * Description: + * Output one byte on the serial console + * + ****************************************************************************/ + +void arm_lowputc(char ch) +{ +#if defined (HAVE_CONSOLE) + /* Wait until the transmit data register is empty */ + + while ((getreg32(GD32_CONSOLE_BASE + GD32_USART_STAT0_OFFSET) & + USART_STAT0_TBE) == 0); +#ifdef GD32_CONSOLE_RS485_DIR + gd32_gpio_write(GD32_CONSOLE_RS485_DIR, + GD32_CONSOLE_RS485_DIR_POLARITY); +#endif + + /* Then send the character */ + + putreg32((uint32_t)(ch & USART_DATA_MASK), GD32_CONSOLE_BASE + + GD32_USART_DATA_OFFSET); + +#ifdef GD32_CONSOLE_RS485_DIR + while ((getreg32(GD32_CONSOLE_BASE + GD32_USART_STAT0_OFFSET) & + USART_STAT0_TC) == 0); + gd32_gpio_write(GD32_CONSOLE_RS485_DIR, + !GD32_CONSOLE_RS485_DIR_POLARITY); +#endif + +#endif /* HAVE_CONSOLE */ +} + +/**************************************************************************** + * Name: gd32_lowsetup + * + * Description: + * This performs basic initialization of the USART used for the serial + * console. Its purpose is to get the console output available as soon + * as possible. + * + ****************************************************************************/ + +void gd32_lowsetup(void) +{ +#if defined(HAVE_SERIALDRIVER) +#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) + uint32_t regval; + uint32_t udiv; + uint32_t intdiv; + uint32_t fradiv; +#endif + +#if defined(HAVE_CONSOLE) + /* Enable USART APB1/2 clock */ + + modifyreg32(GD32_CONSOLE_APBEN_REG, 0, GD32_CONSOLE_APBEN); +#endif + + /* Enable the console USART and configure TX, RX pins. */ + +#ifdef GD32_CONSOLE_TX + gd32_gpio_config(GD32_CONSOLE_TX); +#endif +#ifdef GD32_CONSOLE_RX + gd32_gpio_config(GD32_CONSOLE_RX); +#endif + +#ifdef GD32_CONSOLE_RS485_DIR + gd32_gpio_config(GD32_CONSOLE_RS485_DIR); + gd32_gpio_write(GD32_CONSOLE_RS485_DIR, + !GD32_CONSOLE_RS485_DIR_POLARITY); +#endif + + /* Enable and configure the selected console device */ + +#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) + + /* Reset USART */ + + gd32_usart_reset(GD32_CONSOLE_BASE); + + /* Enable USART clock */ + + gd32_usart_clock_enable(GD32_CONSOLE_BASE); + + /* Disabled the USART before to configure it. */ + + regval = getreg32(GD32_CONSOLE_BASE + GD32_USART_CTL0_OFFSET); + regval &= ~USART_CTL0_UEN; + putreg32(regval, GD32_CONSOLE_BASE + GD32_USART_CTL0_OFFSET); + + /* Configure CTL0 */ + + regval = getreg32(GD32_CONSOLE_BASE + GD32_USART_CTL0_OFFSET); + regval |= (USART_CTL0_WL_VALUE | USART_CTL0_PARITY_VALUE); + putreg32(regval, GD32_CONSOLE_BASE + GD32_USART_CTL0_OFFSET); + + /* Configure CTL1 */ + + regval = getreg32(GD32_CONSOLE_BASE + GD32_USART_CTL1_OFFSET); + regval |= USART_USART_CTL1_STB2BIT_VALUE; + putreg32(regval, GD32_CONSOLE_BASE + GD32_USART_CTL1_OFFSET); + + /* Configure USART baud rate value */ + + regval = getreg32(GD32_CONSOLE_BASE + GD32_USART_CTL0_OFFSET); + + if ((regval & USART_CTL0_OVSMOD) == USART_OVSMOD_8) + { + /* When oversampling by 8, configure the value of USART_BAUD */ + + udiv = ((GD32_CONSOLE_CLOCK * 2) + GD32_CONSOLE_BAUD / 2) / + GD32_CONSOLE_BAUD; + intdiv = udiv & 0xfff0; + fradiv = (udiv >> 1) & 0x7u; + } + else + { + /* When oversampling by 16, configure the value of USART_BAUD */ + + udiv = (GD32_CONSOLE_CLOCK + GD32_CONSOLE_BAUD / 2) / + GD32_CONSOLE_BAUD; + intdiv = udiv & 0xfff0; + fradiv = udiv & 0xf; + } + + regval = ((USART_BAUD_FRADIV_MASK | USART_BAUD_INTDIV_MASK) & + (intdiv | fradiv)); + putreg32(regval, GD32_CONSOLE_BASE + GD32_USART_BAUD_OFFSET); + + /* Enable Rx, Tx, and the USART */ + + regval = getreg32(GD32_CONSOLE_BASE + GD32_USART_CTL0_OFFSET); + regval |= (USART_CTL0_UEN | USART_CTL0_TEN | USART_CTL0_REN); + putreg32(regval, GD32_CONSOLE_BASE + GD32_USART_CTL0_OFFSET); + +#endif /* HAVE_CONSOLE && !CONFIG_SUPPRESS_UART_CONFIG */ +#endif /* HAVE_SERIALDRIVER */ +} + +/**************************************************************************** + * Name: gd32_usart_reset + * + * Description: + * Reset the USART. + * + ****************************************************************************/ + +void gd32_usart_reset(uint32_t usartbase) +{ + uint32_t rcu_rst; + uint32_t regaddr; + + /* Determine which USART to configure */ + + switch (usartbase) + { + default: + return; +#ifdef CONFIG_GD32F4_USART0_SERIALDRIVER + case GD32_USART0: + rcu_rst = RCU_APB2RST_USART0RST; + regaddr = GD32_RCU_APB2RST; + break; +#endif +#ifdef CONFIG_GD32F4_USART1_SERIALDRIVER + case GD32_USART1: + rcu_rst = RCU_APB1RST_USART1RST; + regaddr = GD32_RCU_APB1RST; + break; +#endif +#ifdef CONFIG_GD32F4_USART2_SERIALDRIVER + case GD32_USART2: + rcu_rst = RCU_APB1RST_USART2RST; + regaddr = GD32_RCU_APB1RST; + break; +#endif +#ifdef CONFIG_GD32F4_UART3_SERIALDRIVER + case GD32_UART3: + rcu_rst = RCU_APB1RST_UART3RST; + regaddr = GD32_RCU_APB1RST; + break; +#endif +#ifdef CONFIG_GD32F4_UART4_SERIALDRIVER + case GD32_UART4: + rcu_rst = RCU_APB1RST_UART4RST; + regaddr = GD32_RCU_APB1RST; + break; +#endif +#ifdef CONFIG_GD32F4_USART5_SERIALDRIVER + case GD32_USART5: + rcu_rst = RCU_APB2RST_USART5RST; + regaddr = GD32_RCU_APB2RST; + break; +#endif +#ifdef CONFIG_GD32F4_UART6_SERIALDRIVER + case GD32_UART6: + rcu_rst = RCU_APB1RST_UART6RST; + regaddr = GD32_RCU_APB1RST; + break; +#endif +#ifdef CONFIG_GD32F4_UART7_SERIALDRIVER + case GD32_UART7: + rcu_rst = RCU_APB1RST_UART7RST; + regaddr = GD32_RCU_APB1RST; + break; +#endif + } + + /* Enable APB 1/2 reset for USART */ + + modifyreg32(regaddr, 0, rcu_rst); + + /* Disable APB 1/2 reset for USART */ + + modifyreg32(regaddr, rcu_rst, 0); +} + +/**************************************************************************** + * Name: gd32_usart_clock_enable + * + * Description: + * Enable USART clock + ****************************************************************************/ + +void gd32_usart_clock_enable(uint32_t usartbase) +{ + uint32_t rcu_en; + uint32_t regaddr; + + /* Determine which USART to configure */ + + switch (usartbase) + { + default: + return; +#ifdef CONFIG_GD32F4_USART0_SERIALDRIVER + case GD32_USART0: + rcu_en = RCU_APB2EN_USART0EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif +#ifdef CONFIG_GD32F4_USART1_SERIALDRIVER + case GD32_USART1: + rcu_en = RCU_APB1EN_USART1EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_USART2_SERIALDRIVER + case GD32_USART2: + rcu_en = RCU_APB1EN_USART2EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_UART3_SERIALDRIVER + case GD32_UART3: + rcu_en = RCU_APB1EN_UART3EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_UART4_SERIALDRIVER + case GD32_UART4: + rcu_en = RCU_APB1EN_UART4EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_USART5_SERIALDRIVER + case GD32_USART5: + rcu_en = RCU_APB2EN_USART5EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif +#ifdef CONFIG_GD32F4_UART6_SERIALDRIVER + case GD32_UART6: + rcu_en = RCU_APB1EN_UART6EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_UART7_SERIALDRIVER + case GD32_UART7: + rcu_en = RCU_APB1EN_UART7EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif + } + + /* Enable APB 1/2 clock for USART */ + + modifyreg32(regaddr, 0, rcu_en); +} + +/**************************************************************************** + * Name: gd32_usart_clock_disable + * + * Description: + * Dinable USART clock + ****************************************************************************/ + +void gd32_usart_clock_disable(uint32_t usartbase) +{ + uint32_t rcu_en; + uint32_t regaddr; + + /* Determine which USART to configure */ + + switch (usartbase) + { + default: + return; +#ifdef CONFIG_GD32F4_USART0_SERIALDRIVER + case GD32_USART0: + rcu_en = RCU_APB2EN_USART0EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif +#ifdef CONFIG_GD32F4_USART1_SERIALDRIVER + case GD32_USART1: + rcu_en = RCU_APB1EN_USART1EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_USART2_SERIALDRIVER + case GD32_USART2: + rcu_en = RCU_APB1EN_USART2EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_UART3_SERIALDRIVER + case GD32_UART3: + rcu_en = RCU_APB1EN_UART3EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_UART4_SERIALDRIVER + case GD32_UART4: + rcu_en = RCU_APB1EN_UART4EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_USART5_SERIALDRIVER + case GD32_USART5: + rcu_en = RCU_APB2EN_USART5EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif +#ifdef CONFIG_GD32F4_UART6_SERIALDRIVER + case GD32_UART6: + rcu_en = RCU_APB1EN_UART6EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_UART7_SERIALDRIVER + case GD32_UART7: + rcu_en = RCU_APB1EN_UART7EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif + } + + /* Disable APB 1/2 clock for USART */ + + modifyreg32(regaddr, rcu_en, 0); +} diff --git a/arch/arm/src/gd32f4/gd32f4xx_lowputc.h b/arch/arm/src/gd32f4/gd32f4xx_lowputc.h new file mode 100644 index 0000000000..fbb312019b --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_lowputc.h @@ -0,0 +1,92 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_lowputc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_LOWPUTC_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_LOWPUTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: gd32_lowsetup + * + * Description: + * Called at the very beginning of _start. + * Performs low level initialization of serial console. + * + ****************************************************************************/ + +void gd32_lowsetup(void); + +/**************************************************************************** + * Name: gd32_usart_reset + * + * Description: + * Reset the USART. + * + ****************************************************************************/ + +void gd32_usart_reset(uint32_t usartbase); + +/**************************************************************************** + * Name: gd32_usart_clock_enable + * + * Description: + * Enable USART clock + ****************************************************************************/ + +void gd32_usart_clock_enable(uint32_t usartbase); + +/**************************************************************************** + * Name: gd32_usart_clock_disable + * + * Description: + * Dinable USART clock + ****************************************************************************/ + +void gd32_usart_clock_disable(uint32_t usartbase); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_LOWPUTC_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_pmu.c b/arch/arm/src/gd32f4/gd32f4xx_pmu.c new file mode 100644 index 0000000000..fc52c95feb --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_pmu.c @@ -0,0 +1,666 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_pmu.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "nvic.h" +#include "gd32f4xx_pmu.h" +#include "gd32f4xx.h" + +#if defined(CONFIG_GD32F4_PMU) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static uint32_t gd32_pmu_reg_snap[4]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_pmu_lvd_select + * + * Description: + * Select low voltage detector threshold. + * + * Input Parameters: + * lvdt_n - PMU_CTL_LVDT(n), LVD threshold level + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_lvd_select(uint32_t lvdt_n) +{ + uint32_t regval; + + /* Disable LVD */ + + modifyreg32(GD32_PMU_CTL, PMU_CTL_LVDEN, 0); + + regval = getreg32(GD32_PMU_CTL); + + /* Clear LVDT bits */ + + regval &= ~PMU_CTL_LVDT_MASK; + + /* Set LVDT bits according to pmu_lvdt_n */ + + regval |= lvdt_n; + putreg32(regval, GD32_PMU_CTL); + + /* Enable LVD */ + + modifyreg32(GD32_PMU_CTL, 0, PMU_CTL_LVDEN); +} + +/**************************************************************************** + * Name: gd32_pmu_lvd_enable + * + * Description: + * Enable LVD + * + ****************************************************************************/ + +void gd32_pmu_lvd_enable(void) +{ + /* Enable LVD */ + + modifyreg32(GD32_PMU_CTL, 0, PMU_CTL_LVDEN); +} + +/**************************************************************************** + * Name: gd32_pmu_lvd_disable + * + * Description: + * Disable LVD + * + ****************************************************************************/ + +void gd32_pmu_lvd_disable(void) +{ + /* Disable LVD */ + + modifyreg32(GD32_PMU_CTL, PMU_CTL_LVDEN, 0); +} + +/**************************************************************************** + * Name: gd32_pmu_ldo_output_select + * + * Description: + * Select the LDO output voltage. Set LDO output when the main PLL closed, + * and it takes effect when the main PLL enabled. + * + * Input Parameters: + * ldo_output - PMU_CTL_LDOVS(n), PMU LDO output voltage select + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_ldo_output_select(uint32_t ldo_output) +{ + uint32_t regval; + + regval = getreg32(GD32_PMU_CTL); + regval &= ~PMU_CTL_LDOVS_MASK; + regval |= ldo_output; + putreg32(regval, GD32_PMU_CTL); +} + +/**************************************************************************** + * Name: gd32_pmu_highdriver_mode_enable + * + * Description: + * Disable high-driver mode + * + ****************************************************************************/ + +void gd32_pmu_highdriver_mode_enable(void) +{ + modifyreg32(GD32_PMU_CTL, 0, PMU_CTL_HDEN); +} + +/**************************************************************************** + * Name: gd32_pmu_highdriver_mode_disable + * + * Description: + * Disable high-driver mode + * + ****************************************************************************/ + +void gd32_pmu_highdriver_mode_disable(void) +{ + modifyreg32(GD32_PMU_CTL, PMU_CTL_HDEN, 0); +} + +/**************************************************************************** + * Name: gd32_pmu_highdriver_switch_select + * + * Description: + * Switch high-driver mode. + * + * Input Parameters: + * highdr_switch - PMU high-driver mode + * - PMU_HIGHDR_SWITCH_NONE + * - PMU_HIGHDR_SWITCH_EN + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_highdriver_switch_select(uint32_t highdr_switch) +{ + uint32_t regval; + + while (getreg32(GD32_PMU_CS) & PMU_CS_HDRF); + + regval = getreg32(GD32_PMU_CTL); + regval &= ~PMU_CTL_HDS; + regval |= highdr_switch; + putreg32(regval, GD32_PMU_CTL); +} + +/**************************************************************************** + * Name: gd32_pmu_lowdriver_mode_enable + * + * Description: + * Enable low-driver mode in deep-sleep + * + ****************************************************************************/ + +void gd32_pmu_lowdriver_mode_enable(void) +{ + modifyreg32(GD32_PMU_CTL, 0, PMU_LOWDRIVER_ENABLE); +} + +/**************************************************************************** + * Name: gd32_pmu_lowdriver_mode_disable + * + * Description: + * Disable low-driver mode in deep-sleep + * + ****************************************************************************/ + +void gd32_pmu_lowdriver_mode_disable(void) +{ + modifyreg32(GD32_PMU_CTL, PMU_LOWDRIVER_ENABLE, PMU_LOWDRIVER_DISABLE); +} + +/**************************************************************************** + * Name: gd32_pmu_lowpower_driver_config + * + * Description: + * In deep-sleep mode, driver mode when use low power LDO. + * + * Input Parameters: + * mode - PMU low-driver mode + * - PMU_NORMALDR_LOWPWR: normal driver when use low power LDO + * - PMU_LOWDR_LOWPWR: low-driver mode enabled when LDEN is 11 and + * use low power LDO + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_lowpower_driver_config(uint32_t mode) +{ + uint32_t regval; + regval = getreg32(GD32_PMU_CTL); + regval &= ~PMU_CTL_LDLP; + regval |= mode; + putreg32(regval, GD32_PMU_CTL); +} + +/**************************************************************************** + * Name: gd32_pmu_normalpower_driver_config + * + * Description: + * In deep-sleep mode, driver mode when use normal power LDO. + * + * Input Parameters: + * mode - PMU low-driver mode + * - PMU_NORMALDR_NORMALPWR: normal driver when use normal power LDO + * - PMU_LOWDR_NORMALPWR: low-driver mode enabled when LDEN is 11 and + * use normal power LDO + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_normalpower_driver_config(uint32_t mode) +{ + uint32_t regval; + regval = getreg32(GD32_PMU_CTL); + regval &= ~PMU_CTL_LDNP; + regval |= mode; + putreg32(regval, GD32_PMU_CTL); +} + +/**************************************************************************** + * Name: gd32_pmu_to_sleepmode + * + * Description: + * PMU work in sleep mode. + * + * Input Parameters: + * sleepmodecmd - PMU command constants + * - WFI_CMD: use WFI command + * - WFE_CMD: use WFE command + * sleeponexit + * - true: SLEEPONEXIT bit is set when the WFI instruction is + * executed, the MCU enters Sleep mode as soon as it + * exits the lowest priority ISR. + * - false: SLEEPONEXIT bit is cleared, the MCU enters Sleep + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_to_sleepmode(uint8_t sleepmodecmd, bool sleeponexit) +{ + uint32_t regval; + + /* Clear SLEEPDEEP bit of Cortex-M4 System Control Register */ + + regval = getreg32(NVIC_SYSCON); + regval &= ~NVIC_SYSCON_SLEEPDEEP; + + if (sleeponexit) + { + regval |= NVIC_SYSCON_SLEEPONEXIT; + } + else + { + regval &= ~NVIC_SYSCON_SLEEPONEXIT; + } + + putreg32(regval, NVIC_SYSCON); + + /* Select WFI or WFE command to enter sleep mode */ + + if (sleepmodecmd == WFI_CMD) + { + asm("wfi"); + } + else + { + asm("wfe"); + } +} + +/**************************************************************************** + * Name: gd32_pmu_to_deepsleepmode + * + * Description: + * PMU work in deep-sleep mode + * + * Input Parameters: + * ldo + * - PMU_LDO_NORMAL: LDO normal work when pmu enter deep-sleep mode + * - PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter + * deep-sleep mode + * lowdrive + * - PMU_LOWDRIVER_DISABLE: Low-driver mode disable in deep-sleep mode + * - PMU_LOWDRIVER_ENABLE: Low-driver mode enable in deep-sleep mode + * + * deepsleepmodecmdd - PMU command constants + * - WFI_CMD: use WFI command + * - WFE_CMD: use WFE command + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_to_deepsleepmode(uint32_t ldo, uint32_t lowdrive, + uint8_t deepsleepmodecmd) +{ + uint32_t regval; + + regval = getreg32(GD32_PMU_CTL); + + /* Clear stbmod and ldolp bits */ + + regval &= ~(PMU_CTL_STBMOD | PMU_CTL_LDOLP | PMU_CTL_LDEN_MASK | + PMU_CTL_LDNP | PMU_CTL_LDLP); + + /* Set ldolp bit according to pmu_ldo */ + + regval |= ldo; + + /* Configure low drive mode in deep-sleep mode */ + + if (lowdrive == PMU_LOWDRIVER_ENABLE) + { + if (ldo == PMU_LDO_NORMAL) + { + regval |= (PMU_LOWDRIVER_ENABLE | PMU_CTL_LDNP); + } + else + { + regval |= (PMU_LOWDRIVER_ENABLE | PMU_CTL_LDLP); + } + } + + putreg32(regval, GD32_PMU_CTL); + + /* Set SLEEPDEEP bit of Cortex-M4 System Control Register */ + + regval = getreg32(NVIC_SYSCON); + regval |= NVIC_SYSCON_SLEEPDEEP; + putreg32(regval, NVIC_SYSCON); + + gd32_pmu_reg_snap[0] = getreg32(NVIC_SYSTICK_CTRL); + gd32_pmu_reg_snap[1] = getreg32(NVIC_IRQ0_31_ENABLE); + gd32_pmu_reg_snap[2] = getreg32(NVIC_IRQ32_63_ENABLE); + gd32_pmu_reg_snap[3] = getreg32(NVIC_IRQ64_95_ENABLE); + + putreg32((0x00010004u & gd32_pmu_reg_snap[0]), NVIC_SYSTICK_CTRL); + putreg32(0xff7ff831u, NVIC_IRQ0_31_CLEAR); + putreg32(0xff7ff831u, NVIC_IRQ32_63_CLEAR); + putreg32(0xff7ff831u, NVIC_IRQ64_95_CLEAR); + + /* Select WFI or WFE command to enter sleep mode */ + + if (deepsleepmodecmd == WFI_CMD) + { + asm("wfi"); + } + else + { + asm("sev"); + asm("wfe"); + asm("wfe"); + } + + putreg32(gd32_pmu_reg_snap[0], NVIC_SYSTICK_CTRL); + putreg32(gd32_pmu_reg_snap[1], NVIC_IRQ0_31_ENABLE); + putreg32(gd32_pmu_reg_snap[2], NVIC_IRQ32_63_ENABLE); + putreg32(gd32_pmu_reg_snap[3], NVIC_IRQ64_95_ENABLE); + + /* Reset SLEEPDEEP bit of Cortex-M4 System Control Register */ + + regval = getreg32(NVIC_SYSCON); + regval &= ~NVIC_SYSCON_SLEEPDEEP; + putreg32(regval, NVIC_SYSCON); +} + +/**************************************************************************** + * Name: gd32_pmu_to_standbymode + * + * Description: + * PMU work in standby mode + * + * Input Parameters: + * standbymodecmd - PMU command constants + * WFI_CMD: use WFI command + * WFE_CMD: use WFE command + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_to_standbymode(uint8_t standbymodecmd) +{ + uint32_t regval; + + /* Set SLEEPDEEP bit of Cortex-M4 System Control Register */ + + regval = getreg32(NVIC_SYSCON); + regval |= NVIC_SYSCON_SLEEPDEEP; + putreg32(regval, NVIC_SYSCON); + + regval = getreg32(GD32_PMU_CTL); + + /* Set stbmod bit */ + + regval |= PMU_CTL_STBMOD; + + /* Reset wakeup flag */ + + regval |= PMU_CTL_WURST; + putreg32(regval, GD32_PMU_CTL); + + /* Select WFI or WFE command to enter sleep mode */ + + if (standbymodecmd == WFI_CMD) + { + asm("wfi"); + } + else + { + asm("wfe"); + asm("wfe"); + } +} + +/**************************************************************************** + * Name: gd32_pmu_wakeup_pin_enable + * + * Description: + * Enables PMU wakeup pin. + * + ****************************************************************************/ + +void gd32_pmu_wakeup_pin_enable(void) +{ + modifyreg32(GD32_PMU_CS, 0, PMU_CS_WUPEN); +} + +/**************************************************************************** + * Name: gd32_pmu_wakeup_pin_disable + * + * Description: + * Disables PMU wakeup pin. + * + ****************************************************************************/ + +void gd32_pmu_wakeup_pin_disable(void) +{ + modifyreg32(GD32_PMU_CS, PMU_CS_WUPEN, 0); +} + +/**************************************************************************** + * Name: gd32_pmu_backup_ldo_config + * + * Description: + * Enables the backup ldo, to open Backup SRAM LDO for data protection of + * backup SRAM when VDD shut down. When VDD shut down and this bit is + * cleared, the data in Backup SRAM will be lost. + * Once set, the application should wait that the Backup SRAM LDO flag + * (BLDORF) is set to indicate that the data written into the RAM will be + * maintained when VDD shut down. + * + * Input Parameters: + * bkp_ldo - state to set it to + * - PMU_BLDOON_OFF: backup SRAM LDO closed + * - PMU_BLDOON_ON: backup SRAM LDO closed + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_backup_ldo_config(bool bkp_ldo) +{ + uint32_t regval; + + regval = getreg32(GD32_PMU_CS); + regval &= ~ PMU_CS_BLDOON; + regval |= bkp_ldo; + putreg32(regval, GD32_PMU_CS); +} + +/**************************************************************************** + * Name: gd32_pmu_backup_init + * + * Description: + * Insures the referenced count access to the backup domain + * (RTC registers, RTC backup data registers and backup SRAM is consistent + * with the hardware state without relying on a variable. + * + * NOTE: This function should only be called by SoC Start up code. + * + * Input Parameters: + * writable - set the initial state of the enable or disable + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_backup_init(bool writable) +{ + uint32_t regval; + + /* Make the hardware not writable */ + + regval = getreg32(GD32_PMU_CTL); + regval &= ~PMU_CS_WUPEN; + putreg32(regval, GD32_PMU_CTL); + + if (writable) + { + gd32_pmu_backup_write_enable(); + } + else + { + gd32_pmu_backup_write_disable(); + } +} + +/**************************************************************************** + * Name: gd32_pmu_backup_write_enable + * + * Description: + * Enableswrite access to the registers in backup domain + * + ****************************************************************************/ + +void gd32_pmu_backup_write_enable(void) +{ + modifyreg32(GD32_PMU_CTL, 0, PMU_CTL_BKPWEN); +} + +/**************************************************************************** + * Name: gd32_pmu_backup_write_disable + * + * Description: + * DIsables write access to the registers in backup domain + * + ****************************************************************************/ + +void gd32_pmu_backup_write_disable(void) +{ + modifyreg32(GD32_PMU_CTL, PMU_CTL_BKPWEN, 0); +} + +/**************************************************************************** + * Name: gd32_pmu_flag_get + * + * Description: + * Get flag state + * + * Input Parameters: + * flag - PMU_CS_WUF: wakeup flag + * - PMU_CS_STBF: standby flag + * - PMU_CS_LVDF: lvd flag + * - PMU_CS_BLDORF: backup SRAM LDO ready flag + * - PMU_CS_LDOVSRF: LDO voltage select ready flag + * - PMU_CS_HDRF: high-driver ready flag + * - PMU_CS_HDSRF: high-driver switch ready flag + * - PMU_CS_LDRF: low-driver mode ready flag + * + ****************************************************************************/ + +bool gd32_pmu_flag_get(uint32_t flag) +{ + if (getreg32(GD32_PMU_CS) & flag) + { + return 1; + } + else + { + return 0; + } +} + +/**************************************************************************** + * Name: gd32_pmu_backup_write_disable + * + * Description: + * Clear the flag + * + * Input Parameters: + * flag - PMU_FLAG_RESET_WAKEUP: reset wakeup flag + * - PMU_FLAG_RESET_STANDBY: reset standby flag + * + ****************************************************************************/ + +void gd32_pmu_flag_clear(uint32_t flag) +{ + uint32_t regval; + + regval = getreg32(GD32_PMU_CTL); + + switch (flag) + { + case PMU_FLAG_RESET_WAKEUP: + + /* Reset wakeup flag */ + + regval |= PMU_CTL_WURST; + putreg32(regval, GD32_PMU_CTL); + break; + case PMU_FLAG_RESET_STANDBY: + + /* Reset standby flag */ + + regval |= PMU_CTL_STBRST; + putreg32(regval, GD32_PMU_CTL); + break; + default: + break; + } +} + +#endif /* CONFIG_GD32F4_PMU */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_pmu.h b/arch/arm/src/gd32f4/gd32f4xx_pmu.h new file mode 100644 index 0000000000..00f3d1209e --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_pmu.h @@ -0,0 +1,395 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_pmu.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_PMU_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_PMU_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "chip.h" +#include "hardware/gd32f4xx_pmu.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_pmu_lvd_select + * + * Description: + * Select low voltage detector threshold. + * + * Input Parameters: + * lvdt_n - PMU_CTL_LVDT(n), LVD threshold level + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_lvd_select(uint32_t lvdt_n); + +/**************************************************************************** + * Name: gd32_pmu_lvd_enable + * + * Description: + * Enable LVD + * + ****************************************************************************/ + +void gd32_pmu_lvd_enable(void); + +/**************************************************************************** + * Name: gd32_pmu_lvd_disable + * + * Description: + * Disable LVD + * + ****************************************************************************/ + +void gd32_pmu_lvd_disable(void); + +/**************************************************************************** + * Name: gd32_pmu_ldo_output_select + * + * Description: + * Select the LDO output voltage. Set LDO output when the main PLL closed, + * and it takes effect when the main PLL enabled. + * + * Input Parameters: + * ldo_output - PMU_CTL_LDOVS(n), PMU LDO output voltage select + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_ldo_output_select(uint32_t ldo_output); + +/**************************************************************************** + * Name: gd32_pmu_highdriver_mode_enable + * + * Description: + * Enable high-driver mode + * + ****************************************************************************/ + +void gd32_pmu_highdriver_mode_enable(void); + +/**************************************************************************** + * Name: gd32_pmu_highdriver_mode_disable + * + * Description: + * Disable high-driver mode + * + ****************************************************************************/ + +void gd32_pmu_highdriver_mode_disable(void); + +/**************************************************************************** + * Name: gd32_pmu_highdriver_switch_select + * + * Description: + * Switch high-driver mode. + * + * Input Parameters: + * highdr_switch - PMU high-driver mode + * - PMU_HIGHDR_SWITCH_NONE + * - PMU_HIGHDR_SWITCH_EN + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_highdriver_switch_select(uint32_t highdr_switch); + +/**************************************************************************** + * Name: gd32_pmu_lowdriver_mode_enable + * + * Description: + * Enable low-driver mode in deep-sleep + * + ****************************************************************************/ + +void gd32_pmu_lowdriver_mode_enable(void); + +/**************************************************************************** + * Name: gd32_pmu_lowdriver_mode_disable + * + * Description: + * Disable low-driver mode in deep-sleep + * + ****************************************************************************/ + +void gd32_pmu_lowdriver_mode_disable(void); + +/**************************************************************************** + * Name: gd32_pmu_lowpower_driver_config + * + * Description: + * In deep-sleep mode, driver mode when use low power LDO. + * + * Input Parameters: + * mode - PMU low-driver mode + * - PMU_NORMALDR_LOWPWR: normal driver when use low power LDO + * - PMU_LOWDR_LOWPWR: low-driver mode enabled when LDEN is 11 and + * use low power LDO + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_lowpower_driver_config(uint32_t mode); + +/**************************************************************************** + * Name: gd32_pmu_normalpower_driver_config + * + * Description: + * In deep-sleep mode, driver mode when use normal power LDO. + * + * Input Parameters: + * mode - PMU low-driver mode + * - PMU_NORMALDR_NORMALPWR: normal driver when use normal power LDO + * - PMU_LOWDR_NORMALPWR: low-driver mode enabled when LDEN is 11 and + * use normal power LDO + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_normalpower_driver_config(uint32_t mode); + +/**************************************************************************** + * Name: gd32_pmu_to_sleepmode + * + * Description: + * PMU work in sleep mode. + * + * Input Parameters: + * sleepmodecmd - PMU command constants + * - WFI_CMD: use WFI command + * - WFE_CMD: use WFE command + * sleeponexit + * - true: SLEEPONEXIT bit is set when the WFI instruction is + * executed, the MCU enters Sleep mode as soon as it + * exits the lowest priority ISR. + * - false: SLEEPONEXIT bit is cleared, the MCU enters Sleep + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_to_sleepmode(uint8_t sleepmodecmd, bool sleeponexit); + +/**************************************************************************** + * Name: gd32_pmu_to_deepsleepmode + * + * Description: + * PMU work in deep-sleep mode + * + * Input Parameters: + * ldo + * - PMU_LDO_NORMAL: LDO normal work when pmu enter deep-sleep mode + * - PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter + * deep-sleep mode + * lowdrive + * - PMU_LOWDRIVER_DISABLE: Low-driver mode disable in deep-sleep mode + * - PMU_LOWDRIVER_ENABLE: Low-driver mode enable in deep-sleep mode + * + * deepsleepmodecmdd - PMU command constants + * - WFI_CMD: use WFI command + * - WFE_CMD: use WFE command + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_to_deepsleepmode(uint32_t ldo, uint32_t lowdrive, + uint8_t deepsleepmodecmd); + +/**************************************************************************** + * Name: gd32_pmu_to_standbymode + * + * Description: + * PMU work in standby mode + * + * Input Parameters: + * standbymodecmd - PMU command constants + * WFI_CMD: use WFI command + * WFE_CMD: use WFE command + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_to_standbymode(uint8_t standbymodecmd); + +/**************************************************************************** + * Name: gd32_pmu_wakeup_pin_enable + * + * Description: + * Enables PMU wakeup pin. + * + ****************************************************************************/ + +void gd32_pmu_wakeup_pin_enable(void); + +/**************************************************************************** + * Name: gd32_pmu_wakeup_pin_disable + * + * Description: + * Disables PMU wakeup pin. + * + ****************************************************************************/ + +void gd32_pmu_wakeup_pin_disable(void); + +/**************************************************************************** + * Name: gd32_pmu_backup_ldo_config + * + * Description: + * Enables the backup ldo, to open Backup SRAM LDO for data protection of + * backup SRAM when VDD shut down. When VDD shut down and this bit is + * cleared, the data in Backup SRAM will be lost. + * Once set, the application should wait that the Backup SRAM LDO flag + * (BLDORF) is set to indicate that the data written into the RAM will be + * maintained when VDD shut down. + * + * Input Parameters: + * bkp_ldo - state to set it to + * - PMU_BLDOON_OFF: backup SRAM LDO closed + * - PMU_BLDOON_ON: backup SRAM LDO closed + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_backup_ldo_config(bool bkp_ldo); + +/**************************************************************************** + * Name: gd32_pmu_backup_init + * + * Description: + * Insures the referenced count access to the backup domain + * (RTC registers, RTC backup data registers and backup SRAM is consistent + * with the hardware state without relying on a variable. + * + * NOTE: This function should only be called by SoC Start up code. + * + * Input Parameters: + * writable - set the initial state of the enable and the + * bkp_writable_counter + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_pmu_backup_init(bool writable); + +/**************************************************************************** + * Name: gd32_pmu_backup_write_enable + * + * Description: + * Enableswrite access to the registers in backup domain + * + ****************************************************************************/ + +void gd32_pmu_backup_write_enable(void); + +/**************************************************************************** + * Name: gd32_pmu_backup_write_disable + * + * Description: + * DIsables write access to the registers in backup domain + * + ****************************************************************************/ + +void gd32_pmu_backup_write_disable(void); + +/**************************************************************************** + * Name: gd32_pmu_flag_get + * + * Description: + * Get flag state + * + * Input Parameters: + * flag - PMU_CS_WUF: wakeup flag + * - PMU_CS_STBF: standby flag + * - PMU_CS_LVDF: lvd flag + * - PMU_CS_BLDORF: backup SRAM LDO ready flag + * - PMU_CS_LDOVSRF: LDO voltage select ready flag + * - PMU_CS_HDRF: high-driver ready flag + * - PMU_CS_HDSRF: high-driver switch ready flag + * - PMU_CS_LDRF: low-driver mode ready flag + * + ****************************************************************************/ + +bool gd32_pmu_flag_get(uint32_t flag); + +/**************************************************************************** + * Name: gd32_pmu_backup_write_disable + * + * Description: + * Clear the flag + * + * Input Parameters: + * flag - PMU_FLAG_RESET_WAKEUP: reset wakeup flag + * - PMU_FLAG_RESET_STANDBY: reset standby flag + * + ****************************************************************************/ + +void gd32_pmu_flag_clear(uint32_t flag); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_PMU_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_progmem.c b/arch/arm/src/gd32f4/gd32f4xx_progmem.c new file mode 100644 index 0000000000..25c0e52880 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_progmem.c @@ -0,0 +1,686 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_progmem.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "gd32f4xx_progmem.h" +#include "gd32f4xx_fmc.h" +#include "gd32f4xx.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_GD32F4_FLASH_CONFIG_DEFAULT) + +# define FMC_PROGMEM_SECTOR_SIZES {_K(128), _K(128)} +# define FMC_PROGMEM_SECTOR_NUM (2) +# define FMC_PROGMEM_SECTOR_SADDR (0x08040000) +# define FMC_PROGMEM_SECTOR_EADDR (0x0807FFFF) + +#elif !defined(CONFIG_GD32F4_FLASH_CONFIG_DEFAULT) + +# if defined(CONFIG_GD32F4_FLASH_CONFIG_E) + +# define FMC_PROGMEM_SECTOR_SIZES {_K(128), _K(128)} +# define FMC_PROGMEM_SECTOR_NUM (2) +# define FMC_PROGMEM_SECTOR_SADDR (0x08040000) +# define FMC_PROGMEM_SECTOR_EADDR (0x0807FFFF) + +# elif defined(CONFIG_GD32F4_FLASH_CONFIG_G) + +# define FMC_PROGMEM_SECTOR_SIZES {_K(128), _K(128)} +# define FMC_PROGMEM_SECTOR_NUM (2) +# define FMC_PROGMEM_SECTOR_SADDR (0x080C0000) +# define FMC_PROGMEM_SECTOR_EADDR (0x080FFFFF) + +# elif defined(CONFIG_GD32F4_FLASH_CONFIG_I) + +# define FMC_PROGMEM_SECTOR_SIZES {_K(16), _K(16), _K(16), _K(16)} +# define FMC_PROGMEM_SECTOR_NUM (4) +# define FMC_PROGMEM_SECTOR_SADDR (0x08100000) +# define FMC_PROGMEM_SECTOR_EADDR (0x0813FFFF) + +# elif defined(CONFIG_GD32F4_FLASH_CONFIG_K) + +# define FMC_PROGMEM_SECTOR_SIZES {_K(16), _K(16), _K(16), _K(16)} +# define FMC_PROGMEM_SECTOR_NUM (4) +# define FMC_PROGMEM_SECTOR_SADDR (0x08100000) +# define FMC_PROGMEM_SECTOR_EADDR (0x0813FFFF) + +# endif + +#endif /* !defined(CONFIG_GD32F4_FLASH_CONFIG_DEFAULT) */ + +/* Sector size */ + +#define SIZE_16KB (0x00004000) /* size of 16KB*/ +#define SIZE_64KB (0x00010000) /* size of 64KB*/ +#define SIZE_128KB (0x00020000) /* size of 128KB*/ +#define SIZE_256KB (0x00040000) /* size of 256KB*/ + +/* FMC BANK address */ + +#define FMC_START_ADDRESS (0x08000000) /* FMC start address */ +#define FMC_BANK0_START_ADDRESS FMC_START_ADDRESS /* FMC BANK0 start address */ +#define FMC_BANK1_START_ADDRESS (0x08100000) /* FMC BANK1 start address */ +#define FMC_SIZE (*(uint16_t *)0x1FFF7A22) /* FMC SIZE */ +#define FMC_END_ADDRESS (FMC_START_ADDRESS + (FMC_SIZE * 1024) - 1) + /* FMC end address */ +#define FMC_MAX_END_ADDRESS (0x08300000) /* FMC maximum end address */ + +/* FMC error message */ + +#define FMC_WRONG_SECTOR_NAME (0xFFFFFFFF) /* wrong sector name*/ +#define FMC_WRONG_SECTOR_NUM (0xFFFFFFFF) /* wrong sector number*/ +#define FMC_INVALID_SIZE (0xFFFFFFFF) /* invalid sector size*/ +#define FMC_INVALID_ADDR (0xFFFFFFFF) /* invalid sector address*/ + +#define FMC_ERASE_STATE_VAL (0xFF) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* FMC sector information */ + +typedef struct +{ + uint32_t sector_name; /* the name of the sector */ + uint32_t sector_num; /* the number of the sector */ + uint32_t sector_size; /* the size of the sector */ + uint32_t sector_start_addr; /* the start address of the sector */ + uint32_t sector_end_addr; /* the end address of the sector */ +} fmc_sector_info_struct; + +static const size_t sector_sizes[FMC_PROGMEM_SECTOR_NUM] = + FMC_PROGMEM_SECTOR_SIZES; + +static sem_t g_gd32_progmem_sem = SEM_INITIALIZER(1); + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_fmc_sector_info_get + * + * Description: + * Get the sector number, size and range of the given address + * + * Parameters: + * address - The flash address + * + * Return Value: + * fmc_sector_info_struct: The information of a sector + * + ****************************************************************************/ + +static fmc_sector_info_struct gd32_fmc_sector_info_get(uint32_t addr) +{ + fmc_sector_info_struct sector_info; + uint32_t temp = 0x00000000; + + if ((FMC_START_ADDRESS <= addr) && (FMC_END_ADDRESS >= addr)) + { + if ((FMC_BANK1_START_ADDRESS > addr)) + { + /* Bank0 area */ + + temp = (addr - FMC_BANK0_START_ADDRESS) / SIZE_16KB; + if (4u > temp) + { + sector_info.sector_name = (uint32_t)temp; + sector_info.sector_num = FMC_CTL_SN(temp); + sector_info.sector_size = SIZE_16KB; + sector_info.sector_start_addr = FMC_BANK0_START_ADDRESS + + (SIZE_16KB * temp); + sector_info.sector_end_addr = sector_info.sector_start_addr + + SIZE_16KB - 1; + } + else if (8u > temp) + { + sector_info.sector_name = 0x00000004u; + sector_info.sector_num = FMC_CTL_SN(4); + sector_info.sector_size = SIZE_64KB; + sector_info.sector_start_addr = 0x08010000u; + sector_info.sector_end_addr = 0x0801ffffu; + } + else + { + temp = (addr - FMC_BANK0_START_ADDRESS) / SIZE_128KB; + sector_info.sector_name = (uint32_t)(temp + 4); + sector_info.sector_num = FMC_CTL_SN(temp + 4); + sector_info.sector_size = SIZE_128KB; + sector_info.sector_start_addr = FMC_BANK0_START_ADDRESS + + (SIZE_128KB * temp); + sector_info.sector_end_addr = sector_info.sector_start_addr + + SIZE_128KB - 1; + } + } + else + { + /* bank1 area */ + + temp = (addr - FMC_BANK1_START_ADDRESS) / SIZE_16KB; + if (4u > temp) + { + sector_info.sector_name = (uint32_t)(temp + 12); + sector_info.sector_num = FMC_CTL_SN(temp + 16); + sector_info.sector_size = SIZE_16KB; + sector_info.sector_start_addr = FMC_BANK0_START_ADDRESS + + (SIZE_16KB * temp); + sector_info.sector_end_addr = sector_info.sector_start_addr + + SIZE_16KB - 1; + } + else if (8u > temp) + { + sector_info.sector_name = 0x00000010u; + sector_info.sector_num = FMC_CTL_SN(20); + sector_info.sector_size = SIZE_64KB; + sector_info.sector_start_addr = 0x08110000u; + sector_info.sector_end_addr = 0x0811ffffu; + } + else if (64u > temp) + { + temp = (addr - FMC_BANK1_START_ADDRESS) / SIZE_128KB; + sector_info.sector_name = (uint32_t)(temp + 16); + sector_info.sector_num = FMC_CTL_SN(temp + 20); + sector_info.sector_size = SIZE_128KB; + sector_info.sector_start_addr = FMC_BANK1_START_ADDRESS + + (SIZE_128KB * temp); + sector_info.sector_end_addr = sector_info.sector_start_addr + + SIZE_128KB - 1; + } + else + { + temp = (addr - FMC_BANK1_START_ADDRESS) / SIZE_256KB; + sector_info.sector_name = (uint32_t)(temp + 20); + sector_info.sector_num = FMC_CTL_SN(temp + 8); + sector_info.sector_size = SIZE_256KB; + sector_info.sector_start_addr = FMC_BANK1_START_ADDRESS + + (SIZE_256KB * temp); + sector_info.sector_end_addr = sector_info.sector_start_addr + + SIZE_256KB - 1; + } + } + } + else + { + /* invalid address */ + + sector_info.sector_name = FMC_WRONG_SECTOR_NAME; + sector_info.sector_num = FMC_WRONG_SECTOR_NUM; + sector_info.sector_size = FMC_INVALID_SIZE; + sector_info.sector_start_addr = FMC_INVALID_ADDR; + sector_info.sector_end_addr = FMC_INVALID_ADDR; + } + return sector_info; +} + +/**************************************************************************** + * Name: gd32_progmem_sem_lock + * + * Description: + * Lock semaphore + * + * Return Value: + * Zero(OK) - On success + * EINVAL - Invalid attempt to get the semaphore + * ECANCELED - May be returned if the thread is canceled while waiting + * + ****************************************************************************/ + +static int gd32_progmem_sem_lock(void) +{ + return nxsem_wait_uninterruptible(&g_gd32_progmem_sem); +} + +/**************************************************************************** + * Name: gd32_progmem_sem_unlock + * + * Description: + * Lock semaphore + * + ****************************************************************************/ + +static void gd32_progmem_sem_unlock(void) +{ + nxsem_post(&g_gd32_progmem_sem); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_progmem_neraseblocks + * + * Description: + * Return number of erase blocks + * + ****************************************************************************/ + +size_t up_progmem_neraseblocks(void) +{ + return FMC_PROGMEM_SECTOR_NUM; +} + +/**************************************************************************** + * Name: up_progmem_isuniform + * + * Description: + * Is program memory uniform or page size differs? + * + ****************************************************************************/ + +bool up_progmem_isuniform(void) +{ + return false; +} + +/**************************************************************************** + * Name: up_progmem_erasesize + * + * Description: + * Return erase block size + * + ****************************************************************************/ + +size_t up_progmem_erasesize(size_t block) +{ + if (block >= FMC_PROGMEM_SECTOR_NUM) + { + return 0; + } + else + { + return sector_sizes[block]; + } +} + +/**************************************************************************** + * Name: up_progmem_pagesize + * + * Description: + * Return read/write page size + * + ****************************************************************************/ + +size_t up_progmem_pagesize(size_t page) +{ + return up_progmem_erasesize(page); +} + +/**************************************************************************** + * Name: up_progmem_getpage + * + * Description: + * Address to read/write page conversion + * + * Input Parameters: + * addr - Address with or without flash offset + * (absolute or aligned to page0) + * + * Returned Value: + * Page or negative value on error. The following errors are reported + * (errno is not set!): + * + * -EFAULT: On invalid address + * + ****************************************************************************/ + +ssize_t up_progmem_getpage(size_t addr) +{ + size_t page = 0; + uint32_t i; + + if ((addr < FMC_PROGMEM_SECTOR_SADDR) || (addr > FMC_PROGMEM_SECTOR_EADDR)) + { + return -EFAULT; + } + + addr -= FMC_PROGMEM_SECTOR_SADDR; + + for (i = 0; i < FMC_PROGMEM_SECTOR_NUM; ++i) + { + page += up_progmem_pagesize(i); + if (page > addr) + { + return i; + } + } + + return -EFAULT; +} + +/**************************************************************************** + * Name: up_progmem_getaddress + * + * Description: + * Read/write page to address conversion + * + * Input Parameters: + * page - page index + * + * Returned Value: + * Base address of given page, SIZE_MAX if page index is not valid. + * + ****************************************************************************/ + +size_t up_progmem_getaddress(size_t page) +{ + size_t addr = FMC_PROGMEM_SECTOR_SADDR; + size_t i; + + if (page >= FMC_PROGMEM_SECTOR_NUM) + { + return SIZE_MAX; + } + + for (i = 0; i < page; ++i) + { + addr += up_progmem_pagesize(i); + } + + return addr; +} + +/**************************************************************************** + * Name: up_progmem_eraseblock + * + * Description: + * Erase selected block. + * + * Input Parameters: + * block - The erase block index to be erased. + * + * Returned Value: + * block size or negative value on error. The following errors are + * reported (errno is not set!): + * + * -EFAULT: On invalid page + * -EIO: On unsuccessful erase + * -EROFS: On access to write protected area + * -EACCES: Insufficient permissions (read/write protected) + * -EPERM: If operation is not permitted due to some other constraints + * (i.e. some internal block is not running etc.) + * + ****************************************************************************/ + +ssize_t up_progmem_eraseblock(size_t block) +{ + size_t addr; + fmc_sector_info_struct sector_info; + + if (block >= FMC_PROGMEM_SECTOR_NUM) + { + return -EFAULT; + } + + addr = up_progmem_getaddress(block); + sector_info = gd32_fmc_sector_info_get(addr); + if (sector_info.sector_name == FMC_WRONG_SECTOR_NAME) + { + return -EFAULT; + } + + /* Get flash ready and begin erasing single block */ + + gd32_fmc_unlock(); + gd32_fmc_flag_clear(FMC_STAT_PERR); + + if (gd32_fmc_sector_erase(sector_info.sector_num)) + { + return -EFAULT; + } + + /* Verify */ + + if (up_progmem_ispageerased(block) == 0) + { + /* success */ + + return up_progmem_pagesize(block); + } + else + { + /* failure */ + + return -EIO; + } +} + +/**************************************************************************** + * Name: up_progmem_ispageerased + * + * Description: + * Checks whether page is erased + * + * Input Parameters: + * page - The erase page index to be checked. + * + * Returned Value: + * Returns number of bytes NOT erased or negative value on error. If it + * returns zero then complete page is erased. + * + * The following errors are reported: + * -EFAULT: On invalid page + * + ****************************************************************************/ + +ssize_t up_progmem_ispageerased(size_t page) +{ + size_t page_size; + size_t addr; + int i; + + if (page >= FMC_PROGMEM_SECTOR_NUM) + { + return -EFAULT; + } + + page_size = up_progmem_pagesize(page); + addr = up_progmem_getaddress(page); + + for (i = 0; i < page_size; i++) + { + if (getreg8(addr) != 0xffu) + { + break; + } + } + + return (ssize_t)(page_size - i); +} + +/**************************************************************************** + * Name: up_progmem_write + * + * Description: + * Program data at given address + * + * Note: this function is not limited to single page and nor it requires + * the address be aligned inside the page boundaries. + * + * Input Parameters: + * addr - Address with or without flash offset + * (absolute or aligned to page0) + * buf - Pointer to buffer + * count - Number of bytes to write + * + * Returned Value: + * Bytes written or negative value on error. The following errors are + * reported (errno is not set!) + * + * EINVAL: If count is not aligned with the flash boundaries (i.e. + * some MCU's require per half-word or even word access) + * EFAULT: On invalid address + * EIO: On unsuccessful write + * EROFS: On access to write protected area + * EACCES: Insufficient permissions (read/write protected) + * EPERM: If operation is not permitted due to some other constraints + * (i.e. some internal block is not running etc.) + * + ****************************************************************************/ + +ssize_t up_progmem_write(size_t addr, const void *buf, size_t count) +{ + uint8_t *byte = (uint8_t *)buf; + uint32_t i; + int ret; + + /* Check for valid address range */ + + if (addr < FMC_PROGMEM_SECTOR_SADDR) + { + return -EFAULT; + } + + if ((addr + count) > (FMC_PROGMEM_SECTOR_EADDR + 1)) + { + return -EFAULT; + } + + ret = gd32_progmem_sem_lock(); + + if (ret < 0) + { + return -EFAULT; + } + + /* Get flash ready and begin flashing */ + + gd32_fmc_unlock(); + + for (i = 0; i < count; i++) + { + gd32_fmc_byte_program(addr, *byte); + + if (getreg8(addr) != *byte) + { + gd32_fmc_lock(); + gd32_progmem_sem_unlock(); + return -EIO; + } + + addr++; + byte++; + } + + gd32_fmc_lock(); + + gd32_progmem_sem_unlock(); + + return count; +} + +/**************************************************************************** + * Name: up_progmem_read + * + * Description: + * Read data at given address + * + * Note: this function is not limited to single page and nor it requires + * the address be aligned inside the page boundaries. + * + * Input Parameters: + * addr - Address with or without flash offset + * (absolute or aligned to page0) + * buf - Pointer to buffer + * count - Number of bytes to read + * + * Returned Value: + * Bytes read or negative value on error. The following errors are + * reported (errno is not set!) + * + * EINVAL: If count is not aligned with the flash boundaries (i.e. + * some MCU's require per half-word or even word access) + * EFAULT: On invalid address + * EIO: On unsuccessful read + * EACCES: Insufficient permissions (read/write protected) + * EPERM: If operation is not permitted due to some other constraints + * (i.e. some internal block is not running etc.) + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_HAVE_PROGMEM_READ +ssize_t up_progmem_read(size_t addr, void *buf, size_t count) +{ + uint8_t *byte = (uint8_t *)buf; + uint32_t i; + int ret; + + /* Check for valid address range */ + + if (addr < FMC_PROGMEM_SECTOR_SADDR) + { + return -EFAULT; + } + + if ((addr + count) > FMC_PROGMEM_SECTOR_EADDR) + { + return -EFAULT; + } + + ret = gd32_progmem_sem_lock(); + + if (ret < 0) + { + return -EFAULT; + } + + /* Read data */ + + for (i = 0; i < count; i++) + { + byte[i] = *(uint8_t *)addr; + addr++; + } + + gd32_progmem_sem_unlock(); +} +#endif + +/**************************************************************************** + * Name: up_progmem_erasestate + * + * Description: + * Return value of erase state. + * + ****************************************************************************/ + +uint8_t up_progmem_erasestate(void) +{ + return FMC_ERASE_STATE_VAL; +} diff --git a/arch/arm/src/gd32f4/gd32f4xx_progmem.h b/arch/arm/src/gd32f4/gd32f4xx_progmem.h new file mode 100644 index 0000000000..4a41347efa --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_progmem.h @@ -0,0 +1,44 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_progmem.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_PROGMEM_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_PROGMEM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Refer to GD32F4xx_User_Manual Chapter 2: Flash memory controller to know + * about how program with the flash memory on GD32F450Z. + * + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define FMC_STAT_PERR (FMC_STAT_END | FMC_STAT_OPERR | FMC_STAT_WPERR | FMC_STAT_PGMERR | FMC_STAT_PGSERR) + +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_PROGMEM_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_rcu.c b/arch/arm/src/gd32f4/gd32f4xx_rcu.c new file mode 100644 index 0000000000..cece3fd6b7 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_rcu.c @@ -0,0 +1,762 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_rcu.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "arm_internal.h" + +#include "chip.h" +#include "gd32f4xx_gpio.h" +#include "gd32f4xx_rcu.h" +#include "gd32f4xx.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Allow 2 milliseconds for the IRC16M to become ready. */ + +#define IRC16M_STARTUP_TIMEOUT (2 * CONFIG_BOARD_LOOPSPERMSEC) + +/* Allow 10 milliseconds for the HXTAL to become ready. */ + +#define HXTAL_STARTUP_TIMEOUT (10 * CONFIG_BOARD_LOOPSPERMSEC) + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include chip-specific clocking initialization logic */ + +#if defined(CONFIG_GD32F4_GD32F4XX) +#else +# error "Unknown GD32 chip" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define RCU_MODIFY do { \ + volatile uint32_t i; \ + uint32_t cfg_regval; \ + cfg_regval = getreg32(GD32_RCU_CFG0); \ + cfg_regval |= RCU_CFG0_AHBPSC_CKSYS_DIV2; \ + putreg32(cfg_regval, GD32_RCU_CFG0); \ + for(i = 0; i < 50000; i++); \ + cfg_regval = getreg32(GD32_RCU_CFG0); \ + cfg_regval |= RCU_CFG0_AHBPSC_CKSYS_DIV4; \ + putreg32(cfg_regval, GD32_RCU_CFG0); \ + for(i = 0; i < 50000; i++); \ + } \ + while(0); + +/**************************************************************************** + * Pravite Functions + ****************************************************************************/ + +#ifdef GD32_BOARD_SYSCLK_IRC16MEN +/**************************************************************************** + * Name: gd32_system_clock_irc16m + * + * Description: + * Select the IRC16M as system clock. + * + ****************************************************************************/ + +static void gd32_system_clock_irc16m(void) +{ + uint32_t regval; + uint32_t timeout = 0; + uint32_t stab_flag = 0; + + /* Wait until IRC16M is stable or the startup time is longer than + * IRC16M_STARTUP_TIMEOUT + */ + + do + { + timeout++; + stab_flag = (getreg32(GD32_RCU_CTL) & RCU_CTL_IRC16MSTB); + } + while ((0 == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout)); + + /* If fail */ + + if (0U == (getreg32(GD32_RCU_CTL) & RCU_CTL_IRC16MSTB)) + { + while (1) + { + } + } + + /* Set the AHB = SYSCLK */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_AHBPSC_MASK; + regval |= RCU_CFG0_AHBPSC_CKSYS_DIV1; + putreg32(regval, GD32_RCU_CFG0); + + /* Set the APB2 = AHB */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_APB2PSC_MASK; + regval |= RCU_CFG0_APB2PSC_CKAHB_DIV1; + putreg32(regval, GD32_RCU_CFG0); + + /* Set the APB1 = AHB */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_APB1PSC_MASK; + regval |= RCU_CFG0_APB1PSC_CKAHB_DIV1; + putreg32(regval, GD32_RCU_CFG0); + + /* Select IRC16M as system clock */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_SCS_MASK; + regval |= RCU_CFG0_SCS_IRC16M; + putreg32(regval, GD32_RCU_CFG0); + + /* Wait until IRC16M is selected as system clock */ + + while (0 != (getreg32(GD32_RCU_CFG0) & RCU_CFG0_SCSS_IRC16M)) + { + } +} + +#elif defined (GD32_BOARD_SYSCLK_HXTAL) +/**************************************************************************** + * Name: gd32_system_clock_hxtal + * + * Description: + * Select the HXTAL as system clock. + * + ****************************************************************************/ + +static void gd32_system_clock_hxtal(void) +{ + uint32_t regval; + uint32_t timeout = 0; + uint32_t stab_flag = 0; + + /* Enable HXTAL */ + +#ifdef GD32_RCU_CTL_HXTALBPSEN + + /* Bypass HXTAL oscillator when using the external clock which drives the + * OSCIN pin. + * If use a crystal with HXTAL, do not define GD32_RCU_CTL_HXTALBPSEN. + */ + + regval = getreg32(GD32_RCU_CTL); + regval |= RCU_CTL_HXTALBPS; + putreg32(regval, GD32_RCU_CTL); + +#endif + + regval = getreg32(GD32_RCU_CTL); + regval |= RCU_CTL_HXTALEN; + putreg32(regval, GD32_RCU_CTL); + + /* Wait until HXTAL is stable or the startup time is longer than + * HXTAL_STARTUP_TIMEOUT + */ + + do + { + timeout++; + stab_flag = (getreg32(GD32_RCU_CTL) & RCU_CTL_HXTALSTB); + } + while ((0 == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* If fail */ + + if (0U == (getreg32(GD32_RCU_CTL) & RCU_CTL_HXTALSTB)) + { + while (1) + { + } + } + + /* Set the AHB = SYSCLK */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_AHBPSC_MASK; + regval |= RCU_CFG0_AHBPSC_CKSYS_DIV1; + putreg32(regval, GD32_RCU_CFG0); + + /* Set the APB2 = AHB */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_APB2PSC_MASK; + regval |= RCU_CFG0_APB2PSC_CKAHB_DIV1; + putreg32(regval, GD32_RCU_CFG0); + + /* Set the APB1 = AHB */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_APB1PSC_MASK; + regval |= RCU_CFG0_APB1PSC_CKAHB_DIV1; + putreg32(regval, GD32_RCU_CFG0); + + /* select HXTAL as system clock */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_SCS_MASK; + regval |= RCU_CFG0_SCS_HXTAL; + putreg32(regval, GD32_RCU_CFG0); + + /* wait until HXTAL is selected as system clock */ + + while (0 != (getreg32(GD32_RCU_CFG0) & RCU_CFG0_SCSS_HXTAL)) + { + } +} + +#elif defined (GD32_BOARD_SYSCLK_PLL_IRC16M) +/**************************************************************************** + * Name: gd32_system_clock_pll_irc16m + * + * Description: + * Configure the system clock by PLL which selects IRC16M as its clock + * source. + * + ****************************************************************************/ + +static void gd32_system_clock_pll_irc16m(void) +{ + uint32_t regval; + uint32_t timeout = 0; + uint32_t stab_flag = 0; + + /* Wait until IRC16M is stable or the startup time is longer than + * IRC16M_STARTUP_TIMEOUT + */ + + do + { + timeout++; + stab_flag = (getreg32(GD32_RCU_CTL) & RCU_CTL_IRC16MSTB); + } + while ((0 == stab_flag) && (IRC16M_STARTUP_TIMEOUT != timeout)); + + /* If fail */ + + if (0U == (getreg32(GD32_RCU_CTL) & RCU_CTL_IRC16MSTB)) + { + while (1) + { + } + } + + /* LDO output voltage high mode */ + + regval = getreg32(GD32_RCU_APB1EN); + regval |= RCU_APB1EN_PMUEN; + putreg32(regval, GD32_RCU_APB1EN); + + regval = getreg32(GD32_PMU_CTL); + regval &= ~PMU_CTL_LDOVS_MASK; + regval |= PMU_LDOVS_HIGH; + putreg32(regval, GD32_PMU_CTL); + + /* Set the AHB = SYSCLK */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_AHBPSC_MASK; + regval |= GD32_RCU_CFG0_AHB_PSC; + putreg32(regval, GD32_RCU_CFG0); + + /* Set the APB2 = AHB/2 */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_APB2PSC_MASK; + regval |= GD32_RCU_CFG0_APB2_PSC; + putreg32(regval, GD32_RCU_CFG0); + + /* Set the APB1 = AHB/4 */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_APB1PSC_MASK; + regval |= GD32_RCU_CFG0_APB1_PSC; + putreg32(regval, GD32_RCU_CFG0); + + /* Configure the main PLL, and set PSC, PLL_N, PLL_P, PLL_Q */ + + regval = getreg32(GD32_RCU_PLL); + regval = (GD32_PLL_PLLPSC | GD32_PLL_PLLN | GD32_PLL_PLLP + | GD32_PLL_PLLQ | RCU_PLL_PLLSEL_IRC16M); + putreg32(regval, GD32_RCU_PLL); + + /* Enable the main PLL */ + + regval = getreg32(GD32_RCU_CTL); + regval |= RCU_CTL_PLLEN; + putreg32(regval, GD32_RCU_CTL); + + /* Wait until the PLL is ready */ + + while ((getreg32(GD32_RCU_CTL) & RCU_CTL_PLLSTB) == 0) + { + } + + /* Enable the high-drive to extend the clock frequency to up to 200 Mhz */ + + regval = getreg32(GD32_PMU_CTL); + regval |= PMU_CTL_HDEN; + putreg32(regval, GD32_PMU_CTL); + while ((getreg32(GD32_PMU_CS) & PMU_CS_HDRF) == 0) + { + } + + /* Select the high-drive mode */ + + regval = getreg32(GD32_PMU_CTL); + regval |= PMU_CTL_HDS; + putreg32(regval, GD32_PMU_CTL); + while ((getreg32(GD32_PMU_CS) & PMU_CS_HDSRF) == 0) + { + } + + /* Select PLL as system clock */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_SCS_MASK; + regval |= RCU_CFG0_SCS_PLLP; + putreg32(regval, GD32_RCU_CFG0); + + /* Wait until PLL is selected as system clock */ + + while ((getreg32(GD32_RCU_CFG0) & RCU_CFG0_SCSS_MASK) + != RCU_CFG0_SCSS_PLLP) + { + } +} + +#elif defined (GD32_BOARD_SYSCLK_PLL_HXTAL) +/**************************************************************************** + * Name: gd32_system_clock_pll_hxtal + * + * Description: + * Configure the system clock by PLL which selects HXTAL as its clock + * source. + * + ****************************************************************************/ + +static void gd32_system_clock_pll_hxtal(void) +{ + uint32_t regval; + uint32_t timeout = 0; + uint32_t stab_flag = 0; + + /* enable HXTAL */ + +#ifdef GD32_RCU_CTL_HXTALBPSEN + + /* Bypass HXTAL oscillator when using the external clock which drives the + * OSCIN pin. + * If use a crystal with HXTAL, do not define GD32_RCU_CTL_HXTALBPSEN. + */ + + regval = getreg32(GD32_RCU_CTL); + regval |= RCU_CTL_HXTALBPS; + putreg32(regval, GD32_RCU_CTL); + +#endif + + regval = getreg32(GD32_RCU_CTL); + regval |= RCU_CTL_HXTALEN; + putreg32(regval, GD32_RCU_CTL); + + /* wait until HXTAL is stable or the startup time is longer than + * HXTAL_STARTUP_TIMEOUT + */ + + do + { + timeout++; + stab_flag = (getreg32(GD32_RCU_CTL) & RCU_CTL_HXTALSTB); + } + while ((0 == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + + if (0U == (getreg32(GD32_RCU_CTL) & RCU_CTL_HXTALSTB)) + { + while (1) + { + } + } + + /* LDO output voltage high mode */ + + regval = getreg32(GD32_RCU_APB1EN); + regval |= RCU_APB1EN_PMUEN; + putreg32(regval, GD32_RCU_APB1EN); + + regval = getreg32(GD32_PMU_CTL); + regval &= ~PMU_CTL_LDOVS_MASK; + regval |= PMU_LDOVS_HIGH; + putreg32(regval, GD32_PMU_CTL); + + /* Set the AHB = SYSCLK */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_AHBPSC_MASK; + regval |= GD32_RCU_CFG0_AHB_PSC; + putreg32(regval, GD32_RCU_CFG0); + + /* Set the APB2 = AHB/2 */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_APB2PSC_MASK; + regval |= GD32_RCU_CFG0_APB2_PSC; + putreg32(regval, GD32_RCU_CFG0); + + /* Set the APB1 = AHB/4 */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_APB1PSC_MASK; + regval |= GD32_RCU_CFG0_APB1_PSC; + putreg32(regval, GD32_RCU_CFG0); + + /* Configure the main PLL, and set PSC, PLL_N, PLL_P, PLL_Q */ + + regval = getreg32(GD32_RCU_PLL); + regval = (GD32_PLL_PLLPSC | GD32_PLL_PLLN | GD32_PLL_PLLP + | GD32_PLL_PLLQ | RCU_PLL_PLLSEL_HXTAL); + putreg32(regval, GD32_RCU_PLL); + + /* Enable the main PLL */ + + regval = getreg32(GD32_RCU_CTL); + regval |= RCU_CTL_PLLEN; + putreg32(regval, GD32_RCU_CTL); + + /* Wait until the PLL is ready */ + + while ((getreg32(GD32_RCU_CTL) & RCU_CTL_PLLSTB) == 0) + { + } + + /* Enable the high-drive to extend the clock frequency to up to 200 Mhz */ + + regval = getreg32(GD32_PMU_CTL); + regval |= PMU_CTL_HDEN; + putreg32(regval, GD32_PMU_CTL); + while ((getreg32(GD32_PMU_CS) & PMU_CS_HDRF) == 0) + { + } + + /* Select the high-drive mode */ + + regval = getreg32(GD32_PMU_CTL); + regval |= PMU_CTL_HDS; + putreg32(regval, GD32_PMU_CTL); + while ((getreg32(GD32_PMU_CS) & PMU_CS_HDSRF) == 0) + { + } + + /* Select PLL as system clock */ + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_SCS_MASK; + regval |= RCU_CFG0_SCS_PLLP; + putreg32(regval, GD32_RCU_CFG0); + + /* Wait until PLL is selected as system clock */ + + while ((getreg32(GD32_RCU_CFG0) & RCU_CFG0_SCSS_MASK) + != RCU_CFG0_SCSS_PLLP) + { + } +} +#endif + +/**************************************************************************** + * Name: gd32_system_clock_config + * + * Description: + * Configure the system clock using the settings in board.h. + * + ****************************************************************************/ + +static void gd32_system_clock_config(void) +{ +#ifdef GD32_BOARD_SYSCLK_IRC16MEN + + /* Select IRC16M as SYSCLK based on board.h setting. */ + + gd32_system_clock_irc16m(); + +#elif defined (GD32_BOARD_SYSCLK_HXTAL) + + /* Select HXTAL as SYSCLK based on board.h setting. */ + + gd32_system_clock_hxtal(); + +#elif defined (GD32_BOARD_SYSCLK_PLL_IRC16M) + + /* Select PLL which source is IRC16M as SYSCLK based on board.h setting. */ + + gd32_system_clock_pll_irc16m(); + +#elif defined (GD32_BOARD_SYSCLK_PLL_HXTAL) + + /* Select PLL which source is HXTAL as SYSCLK based on board.h setting. */ + + gd32_system_clock_pll_hxtal(); + +#else + #error "Invalid system clock configuration." +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_clockconfig + * + * Description: + * Called to initialize the GD32F4. This does whatever setup is needed to + * put the MCU in a usable state. This includes the initialization of + * clocking using the settings in board.h. + * + ****************************************************************************/ + +void gd32_clockconfig(void) +{ + uint32_t regval; + + /* Reset the RCU clock configuration to the default reset state */ + + /* Set IRC16MEN bit */ + + regval = getreg32(GD32_RCU_CTL); + regval |= RCU_CTL_IRC16MEN; + putreg32(regval, GD32_RCU_CTL); + + RCU_MODIFY + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~RCU_CFG0_SCS_MASK; + putreg32(regval, GD32_RCU_CFG0); + + /* Reset HXTALEN, CKMEN and PLLEN bits */ + + regval = getreg32(GD32_RCU_CTL); + regval &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); + putreg32(regval, GD32_RCU_CTL); + + /* Reset HXTALBPS bit */ + + regval = getreg32(GD32_RCU_CTL); + regval &= ~RCU_CTL_HXTALBPS; + putreg32(regval, GD32_RCU_CTL); + + /* Reset CFG0 register */ + + putreg32(0x00000000, GD32_RCU_CFG0); + + /* wait until IRC16M is selected as system clock */ + + regval = getreg32(GD32_RCU_CFG0); + while (0 != (regval & RCU_CFG0_SCSS_IRC16M)) + { + regval = getreg32(GD32_RCU_CFG0); + } + + /* Reset PLL register */ + + putreg32(0x24003010, GD32_RCU_PLL); + + /* Disable all interrupts */ + + putreg32(0x00000000, GD32_RCU_INT); + +#if defined(CONFIG_ARCH_BOARD_GD32F4_CUSTOM_CLOCKCONFIG) + + /* Invoke Board Custom Clock Configuration */ + + gd32_board_clockconfig(); + +#else + + /* Invoke standard, fixed clock configuration based on definitions + * in board.h + */ + + /* Configure the System clock source, PLL Multiplier and Divider factors, + * AHB/APBx prescalers and Flash settings + */ + + gd32_system_clock_config(); +#endif +} + +/**************************************************************************** + * Name: gd32_rcu_ckout0_config + * + * Description: + * Configure the CK_OUT0 clock source and divider. CK_OUT0 is connected + * to PA8. PA8 should be configured in alternate function mode. + * + ****************************************************************************/ + +void gd32_rcu_ckout0_config(uint32_t src, uint32_t div) +{ + uint32_t regval; + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~(RCU_CFG0_CKOUT0SEL_MASK | RCU_CFG0_CKOUT0DIV_MASK); + regval |= (src | div); + putreg32(regval, GD32_RCU_CFG0); +} + +/**************************************************************************** + * Name: gd32_rcu_ckout1_config + * + * Description: + * Configure the CK_OUT0 clock source and divider. CK_OUT0 is connected + * to PC9. PC9 should be configured in alternate function mode. + ****************************************************************************/ + +void gd32_rcu_ckout1_config(uint32_t src, uint32_t div) +{ + uint32_t regval; + + regval = getreg32(GD32_RCU_CFG0); + regval &= ~(RCU_CFG0_CKOUT1SEL_MASK | RCU_CFG0_CKOUT1DIV_MASK); + regval |= (src | div); + putreg32(regval, GD32_RCU_CFG0); +} + +/**************************************************************************** + * Name: gd32_rcu_periph_clock_enable + * + * Description: + * Enable the peripherals clock. + * + ****************************************************************************/ + +void gd32_rcu_periph_clock_enable(uint32_t periph) +{ + uint32_t reg_off; + uint32_t bit_pos; + uint32_t regaddr; + uint32_t regval; + + bit_pos = periph & 0x1f; + reg_off = (periph >> RCU_PERI_REG_SHIFT); + regaddr = GD32_RCU_BASE + reg_off; + + regval = getreg32(regaddr); + regval |= (1 << bit_pos); + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Name: gd32_rcu_periph_clock_disable + * + * Description: + * Enable the peripherals clock. + * + ****************************************************************************/ + +void gd32_rcu_periph_clock_disable(uint32_t periph) +{ + uint32_t reg_off; + uint32_t bit_pos; + uint32_t regaddr; + uint32_t regval; + + bit_pos = periph & 0x1f; + reg_off = (periph >> RCU_PERI_REG_SHIFT); + regaddr = GD32_RCU_BASE + reg_off; + + regval = getreg32(regaddr); + regval &= ~(1 << bit_pos); + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Name: gd32_clock_enable + * + * Description: + * Re-enable the clock and restore the clock settings based on settings + * in board.h. This function is only available to support low-power + * modes of operation: When re-awakening from deep-sleep modes, it is + * necessary to re-enable/re-start the PLL + * + * This functional performs a subset of the operations performed by + * gd32_clockconfig(): It does not reset any devices, and it does not + * reset the currently enabled peripheral clocks. + * + * If CONFIG_ARCH_BOARD_GD32F4_CUSTOM_CLOCKCONFIG is defined, then clocking + * will be enabled by an externally provided, board-specific function + * called gd32_board_clockconfig(). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_PM + +void gd32_clock_enable(void) +{ +#if defined(CONFIG_ARCH_BOARD_GD32F4_CUSTOM_CLOCKCONFIG) + + /* Invoke Board Custom Clock Configuration */ + + gd32_board_clockconfig(); + +#else + + /* Invoke standard, fixed clock configuration based on definitions + * in board.h + */ + + /* Configure the System clock source, PLL Multiplier and Divider factors, + * AHB/APBx prescalers and Flash settings + */ + + gd32_system_clock_config(); + +#endif +} +#endif diff --git a/arch/arm/src/gd32f4/gd32f4xx_rcu.h b/arch/arm/src/gd32f4/gd32f4xx_rcu.h new file mode 100644 index 0000000000..dab961f76f --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_rcu.h @@ -0,0 +1,180 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_rcu.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_RCU_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_RCU_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +#if defined(CONFIG_GD32F4_GD32F4XX) +# include "hardware/gd32f4xx_rcu.h" +#else +# error "Unknown GD32 chip" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#define RCU_PERI_REG_SHIFT (6) +#define RCU_GPIOA_EN ((GD32_RCU_AHB1EN_OFFSET << RCU_PERI_REG_SHIFT) | 0) + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_clockconfig + * + * Description: + * Called to initialize the GD32F4. This does whatever setup is needed to + * put the MCU in a usable state. This includes the initialization of + * clocking using the settings in board.h. + * + ****************************************************************************/ + +void gd32_clockconfig(void); + +/**************************************************************************** + * Name: gd32_rcu_ckout0_config + * + * Description: + * Configure the CK_OUT0 clock source and divider. CK_OUT0 is connected + * to PA8. PA8 should be configured in alternate function mode. + ****************************************************************************/ + +void gd32_rcu_ckout0_config(uint32_t src, uint32_t div); + +/**************************************************************************** + * Name: gd32_rcu_ckout1_config +* + * Description: + * Configure the CK_OUT0 clock source and divider. CK_OUT0 is connected + * to PC9. PC9 should be configured in alternate function mode. + ****************************************************************************/ + +void gd32_rcu_ckout1_config(uint32_t src, uint32_t div); + +/**************************************************************************** + * Name: gd32_board_clockconfig + * + * Description: + * Any GD32 board may replace the "standard" board clock configuration + * logic with its own, custom clock configuration logic. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_BOARD_GD32F4_CUSTOM_CLOCKCONFIG +void gd32_board_clock_config(void); +#endif + +/**************************************************************************** + * Name: gd32_clockenable + * + * Description: + * Re-enable the clock and restore the clock settings based on settings in + * board.h. + * This function is only available to support low-power modes of operation: + * When re-awakening from deep-sleep modes, it is necessary to re-enable/ + * re-start the PLL + * + * This functional performs a subset of the operations performed by + * gd32_clockconfig(): It does not reset any devices, and it does not + * reset the currently enabled peripheral clocks. + * + * If CONFIG_ARCH_BOARD_GD32F4_CUSTOM_CLOCKCONFIG is defined, then clocking + * will be enabled by an externally provided, board-specific function + * called gd32_board_clockconfig(). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_PM +void gd32_clock_enable(void); +#endif + +/**************************************************************************** + * Name: gd32_rcu_lxtal_enable + * + * Description: + * Enable the External Low Speed crystal oscillator (LXTAL). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gd32_rcu_lxtal_enable(void); + +/**************************************************************************** + * Name: gd32_rcu_irc16_enable + * + * Description: + * Enable the Internal 16M RC oscillator (IRC16M). + * + ****************************************************************************/ + +void gd32_rcu_irc16m_enable(void); + +/**************************************************************************** + * Name: gd32_rcu_irc16m_disable + * + * Description: + * Disable the Internal 16M RC oscillator (IRC16M). + * + ****************************************************************************/ + +void gd32_rcu_irc16m_disable(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_RCU_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_serial.c b/arch/arm/src/gd32f4/gd32f4xx_serial.c new file mode 100644 index 0000000000..fdebe29ed9 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_serial.c @@ -0,0 +1,2984 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_serial.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include + +#include "chip.h" +#include "gd32f4xx.h" +#include "gd32f4xx_usart.h" +#include "gd32f4xx_rcu.h" +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Is there at least one USART enabled and configured as a RS-232 device? */ + +/* Power management definitions */ + +#if defined(CONFIG_PM) && !defined(CONFIG_GD32F4_PM_SERIAL_ACTIVITY) +# define CONFIG_GD32F4_PM_SERIAL_ACTIVITY 10 +#endif + +#if defined(CONFIG_PM) +# define PM_IDLE_DOMAIN 0 /* Revisit */ +#endif + +/* If we are not using the serial driver for the console, then we still must + * provide some minimal implementation of up_putc. + */ + +#ifdef USE_SERIALDRIVER + +#ifdef HAVE_SERIALDRIVER + +#if defined(SERIAL_HAVE_RXDMA) || defined(SERIAL_HAVE_TXDMA) + +/* USART DMA priority */ +#if defined(CONFIG_GD32F4_USART_PRIQ) +# define USART_DMA_PRIO CONFIG_GD32F4_USART_PRIQ +#else +# define USART_DMA_PRIO DMA_PRIO_MEDIUM_SELECT +#endif +#endif + +#ifdef SERIAL_HAVE_RXDMA +/* The DMA buffer size when using RX DMA to emulate a FIFO. + * + * When streaming data, the generic serial layer will be called every time + * the FIFO receives half this number of bytes. + */ +# if !defined(CONFIG_GD32F4_SERIAL_RXDMA_BUFFER_SIZE) +# define CONFIG_GD32F4_SERIAL_RXDMA_BUFFER_SIZE 32 +# endif +# define RXDMA_BUFFER_MASK (4 - 1) +# define RXDMA_BUFFER_SIZE ((CONFIG_GD32F4_SERIAL_RXDMA_BUFFER_SIZE \ + + RXDMA_BUFFER_MASK) \ + & ~RXDMA_BUFFER_MASK) + +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct up_dev_s +{ + bool initialized; /* Indicate that if has been initialized and HW is setup. */ + +#ifdef CONFIG_SERIAL_TERMIOS + +# ifdef CONFIG_SERIAL_IFLOWCONTROL + bool iflow; /* input flow control (RTS) enabled */ +# endif +# ifdef CONFIG_SERIAL_OFLOWCONTROL + bool oflow; /* output flow control (CTS) enabled */ +# endif + + uint16_t oversamp /* USART oversample mode */ + uintptr_t usartbase; /* Base address of UART registers */ + uint32_t baud; /* Configured baud */ + uint32_t clock; /* Frequency of the UART */ + uint8_t irq; /* IRQ associated with this USART */ + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (8 or 9) */ + uint8_t stop_2bits; /* True: Configure with 2 stop bits instead of 1 */ + uint32_t tx_gpio; /* USART TX GPIO pin configuration */ + uint32_t rx_gpio; /* USART RX GPIO pin configuration */ + +# ifdef CONFIG_SERIAL_IFLOWCONTROL + uint32_t rts_gpio; /* UART RTS GPIO pin configuration */ +# endif +# ifdef CONFIG_SERIAL_OFLOWCONTROL + uint32_t cts_gpio; /* UART CTS GPIO pin configuration */ +# endif + +#else /* CONFIG_SERIAL_TERMIOS */ + +# ifdef CONFIG_SERIAL_IFLOWCONTROL + const bool iflow; /* input flow control (RTS) enabled */ +# endif +# ifdef CONFIG_SERIAL_OFLOWCONTROL + const bool oflow; /* output flow control (CTS) enabled */ +# endif + + const uint16_t oversamp; /* USART oversample mode */ + const uintptr_t usartbase; /* Base address of UART registers */ + const uint32_t baud; /* Configured baud */ + const uint32_t clock; /* Frequency of the UART */ + const uint8_t irq; /* IRQ associated with this USART */ + const uint8_t parity; /* 0=none, 1=odd, 2=even */ + const uint8_t bits; /* Number of bits (8 or 9) */ + const uint8_t stop_2bits; /* True: Configure with 2 stop bits instead of 1 */ + const uint32_t tx_gpio; /* USART TX GPIO pin configuration */ + const uint32_t rx_gpio; /* USART RX GPIO pin configuration */ + +# ifdef CONFIG_SERIAL_IFLOWCONTROL + const uint32_t rts_gpio; /* UART RTS GPIO pin configuration */ +# endif +# ifdef CONFIG_SERIAL_OFLOWCONTROL + const uint32_t cts_gpio; /* UART CTS GPIO pin configuration */ +# endif + +#endif /* CONFIG_SERIAL_TERMIOS */ + + uint32_t ie; /* USART enabled interrupts */ + uint16_t sr; /* Save USART status */ + + /* TX DMA state */ + +#ifdef SERIAL_HAVE_TXDMA + const uint32_t txdma_channel; /* DMA channel assigned */ + DMA_HANDLE txdma; /* currently-open trasnmit DMA stream */ +#endif + + /* RX DMA state */ + +#ifdef SERIAL_HAVE_RXDMA + const uint32_t rxdma_channel; /* DMA channel assigned */ + DMA_HANDLE rxdma; /* currently-open receive DMA stream */ + bool rxenable; /* DMA-based reception en/disable */ + uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */ + char *const rxfifo; /* Receive DMA buffer */ +#endif + +#ifdef HAVE_RS485 + const uint32_t rs485_dir_gpio; /* USART RS-485 DIR GPIO pin cfg */ + const bool rs485_dir_polarity; /* USART RS-485 DIR TXEN polarity */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline uint32_t up_serialin(struct up_dev_s *priv, int offset); +static inline void up_serialout(struct up_dev_s *priv, int offset, + uint32_t value); +static void up_setusartint(struct up_dev_s *priv, uint32_t ie); +static void up_disableusartint(struct up_dev_s *priv, uint32_t *ie); +static void up_restoreusartint(struct up_dev_s *priv, uint32_t ie); + +static void gd32_usart_configure(struct uart_dev_s *dev); + +static int up_setup(struct uart_dev_s *dev); +static void up_shutdown(struct uart_dev_s *dev); +static int up_attach(struct uart_dev_s *dev); +static void up_detach(struct uart_dev_s *dev); +static int up_interrupt(int irq, void *context, void *arg); +static int up_ioctl(struct file *filep, int cmd, unsigned long arg); + +#if defined(SERIAL_NOT_HAVE_DMA) || defined(SERIAL_HAVE_TX_DMA) +static int up_receive(struct uart_dev_s *dev, unsigned int *status); +static void up_rxint(struct uart_dev_s *dev, bool enable); +static bool up_rxavailable(struct uart_dev_s *dev); +#endif + +#ifdef CONFIG_SERIAL_IFLOWCONTROL +static bool up_rxflowcontrol(struct uart_dev_s *dev, unsigned int nbuffered, + bool upper); +#endif +static void up_send(struct uart_dev_s *dev, int ch); + +#if defined(SERIAL_HAVE_RXDMA) +static int up_dma_nextrx(struct up_dev_s *priv); +static int up_dma_receive(struct uart_dev_s *dev, unsigned int *status); +static void up_dma_rxint(struct uart_dev_s *dev, bool enable); +static bool up_dma_rxavailable(struct uart_dev_s *dev); +static void up_dma_rx_callback(DMA_HANDLE handle, uint16_t status, + void *arg); +#endif + +#if defined(SERIAL_HAVE_TXDMA) +static void up_dma_tx_callback(DMA_HANDLE handle, uint16_t status, + void *arg); +static void up_dma_txavailable(struct uart_dev_s *dev); +static void up_dma_send(struct uart_dev_s *dev); +static void up_dma_txint(struct uart_dev_s *dev, bool enable); +#endif + +#if defined(SERIAL_HAVE_RXDMA) || defined(SERIAL_HAVE_TXDMA) +static int up_dma_setup(struct uart_dev_s *dev); +static void up_dma_shutdown(struct uart_dev_s *dev); +#endif + +#if defined(SERIAL_HAVE_RX_DMA) || defined(SERIAL_NOT_HAVE_DMA) || \ + defined(CONFIG_GD32F4_SERIALBRK_BSDCOMPAT) +static void up_txint(struct uart_dev_s *dev, bool enable); +#endif + +static bool up_txready(struct uart_dev_s *dev); +static bool up_txempty(struct uart_dev_s *dev); + +#ifdef CONFIG_PM +static void up_pm_notify(struct pm_callback_s *cb, int dowmin, + enum pm_state_e pmstate); +static int up_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ +#if defined(SERIAL_HAVE_RXTX_DMA) +static const struct uart_ops_s g_uart_ops_rxtx_dma = +{ + .setup = up_dma_setup, + .shutdown = up_dma_shutdown, + .attach = up_attach, + .detach = up_detach, + .ioctl = up_ioctl, + .receive = up_dma_receive, + .rxint = up_dma_rxint, + .rxavailable = up_dma_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = up_rxflowcontrol, +#endif + .send = up_send, + .txint = up_dma_txint, + .dmatxavail = up_dma_txavailable, + .dmasend = up_dma_send, + .txready = up_txready, + .txempty = up_txempty, +}; +#endif + +#if defined(SERIAL_HAVE_RX_DMA) +static const struct uart_ops_s g_uart_ops_rx_dma = +{ + .setup = up_dma_setup, + .shutdown = up_dma_shutdown, + .attach = up_attach, + .detach = up_detach, + .ioctl = up_ioctl, + .receive = up_dma_receive, + .rxint = up_dma_rxint, + .rxavailable = up_dma_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = up_rxflowcontrol, +#endif + .send = up_send, + .txint = up_txint, + .txready = up_txready, + .txempty = up_txempty, +}; +#endif + +#if defined(SERIAL_HAVE_TX_DMA) +static const struct uart_ops_s g_uart_ops_tx_dma = +{ + .setup = up_dma_setup, + .shutdown = up_dma_shutdown, + .attach = up_attach, + .detach = up_detach, + .ioctl = up_ioctl, + .receive = up_receive, + .rxint = up_rxint, + .rxavailable = up_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = up_rxflowcontrol, +#endif + .send = up_send, + .txint = up_dma_txint, + .dmatxavail = up_dma_txavailable, + .dmasend = up_dma_send, + .txready = up_txready, + .txempty = up_txempty, +}; +#endif + +#if defined(SERIAL_NOT_HAVE_DMA) +static const struct uart_ops_s g_uart_ops_no_dma = +{ + .setup = up_setup, + .shutdown = up_shutdown, + .attach = up_attach, + .detach = up_detach, + .ioctl = up_ioctl, + .receive = up_receive, + .rxint = up_rxint, + .rxavailable = up_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = up_rxflowcontrol, +#endif + .send = up_send, + .txint = up_txint, + .txready = up_txready, + .txempty = up_txempty, +}; +#endif + +/* Receive / Transmit buffers */ + +#ifdef CONFIG_GD32F4_USART0_SERIALDRIVER +static char g_usart0rxbuffer[CONFIG_USART0_RXBUFSIZE]; +static char g_usart0txbuffer[CONFIG_USART0_TXBUFSIZE]; +# ifdef CONFIG_GD32F4_USART0_RXDMA +static char g_usart0rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_GD32F4_USART1_SERIALDRIVER +static char g_usart1rxbuffer[CONFIG_USART1_RXBUFSIZE]; +static char g_usart1txbuffer[CONFIG_USART1_TXBUFSIZE]; +# ifdef CONFIG_GD32F4_USART1_RXDMA +static char g_usart1rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_GD32F4_USART2_SERIALDRIVER +static char g_usart2rxbuffer[CONFIG_USART2_RXBUFSIZE]; +static char g_usart2txbuffer[CONFIG_USART2_TXBUFSIZE]; +# ifdef CONFIG_GD32F4_USART2_RXDMA +static char g_usart2rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_GD32F4_UART3_SERIALDRIVER +static char g_uart3rxbuffer[CONFIG_UART3_RXBUFSIZE]; +static char g_uart3txbuffer[CONFIG_UART3_TXBUFSIZE]; +# ifdef CONFIG_GD32F4_UART3_RXDMA +static char g_uart3rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_GD32F4_UART4_SERIALDRIVER +static char g_uart4rxbuffer[CONFIG_UART4_RXBUFSIZE]; +static char g_uart4txbuffer[CONFIG_UART4_TXBUFSIZE]; +# ifdef CONFIG_GD32F4_UART4_RXDMA +static char g_uart4rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_GD32F4_USART5_SERIALDRIVER +static char g_usart5rxbuffer[CONFIG_USART5_RXBUFSIZE]; +static char g_usart5txbuffer[CONFIG_USART5_TXBUFSIZE]; +# ifdef CONFIG_GD32F4_USART5_RXDMA +static char g_usart5rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_GD32F4_UART6_SERIALDRIVER +static char g_uart6rxbuffer[CONFIG_UART6_RXBUFSIZE]; +static char g_uart6txbuffer[CONFIG_UART6_TXBUFSIZE]; +# ifdef CONFIG_GD32F4_UART6_RXDMA +static char g_uart6rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_GD32F4_UART7_SERIALDRIVER +static char g_uart7rxbuffer[CONFIG_UART7_RXBUFSIZE]; +static char g_uart7txbuffer[CONFIG_UART7_TXBUFSIZE]; +# ifdef CONFIG_GD32F4_UART7_RXDMA +static char g_uart7rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +/* This describes the state of the GD32 USART0 ports. */ + +#ifdef CONFIG_GD32F4_USART0_SERIALDRIVER + +static struct up_dev_s g_usart0priv = +{ + .oversamp = USART_OVSMOD_16, + .usartbase = GD32_USART0, + .baud = CONFIG_USART0_BAUD, + .clock = GD32_PCLK2_FREQUENCY, + .irq = GD32_IRQ_USART0, + .parity = CONFIG_USART0_PARITY, + .bits = CONFIG_USART0_BITS, + .stop_2bits = CONFIG_USART0_2STOP, + + .tx_gpio = GPIO_USART0_TX, + .rx_gpio = GPIO_USART0_RX, +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_USART0_IFLOWCONTROL) + .iflow = true, + .rts_gpio = GPIO_USART0_RTS, +#endif +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_USART0_OFLOWCONTROL) + .oflow = true, + .cts_gpio = GPIO_USART0_CTS, +#endif +#ifdef CONFIG_GD32F4_USART0_TXDMA + .txdma_channel = DMA_CHANNEL_USART0_TX, +#endif +#ifdef CONFIG_GD32F4_USART0_RXDMA + .rxdma_channel = DMA_CHANNEL_USART0_RX, + .rxfifo = g_usart0rxfifo, +#endif + +#ifdef CONFIG_USART0_RS485 + .rs485_dir_gpio = GPIO_USART0_RS485_DIR, +# if (CONFIG_USART0_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif +}; + +static struct uart_dev_s g_usart0port = +{ +#if CONSOLE_UART == 0 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART0_RXBUFSIZE, + .buffer = g_usart0rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART0_TXBUFSIZE, + .buffer = g_usart0txbuffer, + }, +#if defined(CONFIG_GD32F4_USART0_RXDMA) && defined(CONFIG_GD32F4_USART0_TXDMA) + .ops = &g_uart_ops_rxtx_dma, +#elif defined(CONFIG_GD32F4_USART0_RXDMA) && !defined(CONFIG_GD32F4_USART0_TXDMA) + .ops = &g_uart_ops_rx_dma, +#elif !defined(CONFIG_GD32F4_USART0_RXDMA) && defined(CONFIG_GD32F4_USART0_TXDMA) + .ops = &g_uart_ops_tx_dma, +#else + .ops = &g_uart_ops_no_dma, +#endif + .priv = &g_usart0priv, +}; + +#endif + +/* This describes the state of the GD32 USART1 port. */ + +#ifdef CONFIG_GD32F4_USART1_SERIALDRIVER + +static struct up_dev_s g_usart1priv = +{ + .oversamp = USART_OVSMOD_16, + .usartbase = GD32_USART1, + .baud = CONFIG_USART1_BAUD, + .clock = GD32_PCLK1_FREQUENCY, + .irq = GD32_IRQ_USART1, + .parity = CONFIG_USART1_PARITY, + .bits = CONFIG_USART1_BITS, + .stop_2bits = CONFIG_USART1_2STOP, + + .tx_gpio = GPIO_USART1_TX, + .rx_gpio = GPIO_USART1_RX, +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_USART1_IFLOWCONTROL) + .iflow = true, + .rts_gpio = GPIO_USART1_RTS, +#endif +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_USART1_OFLOWCONTROL) + .oflow = true, + .cts_gpio = GPIO_USART1_CTS, +#endif +#ifdef CONFIG_GD32F4_USART1_TXDMA + .txdma_channel = DMA_CHANNEL_USART1_TX, +#endif +#ifdef CONFIG_GD32F4_USART1_RXDMA + .rxdma_channel = DMA_CHANNEL_USART1_RX, + .rxfifo = g_usart1rxfifo, +#endif + +#ifdef CONFIG_USART1_RS485 + .rs485_dir_gpio = GPIO_USART1_RS485_DIR, +# if (CONFIG_USART1_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif +}; + +static struct uart_dev_s g_usart1port = +{ +#if CONSOLE_UART == 1 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART1_RXBUFSIZE, + .buffer = g_usart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART1_TXBUFSIZE, + .buffer = g_usart1txbuffer, + }, +#if defined(CONFIG_GD32F4_USART1_RXDMA) && defined(CONFIG_GD32F4_USART1_TXDMA) + .ops = &g_uart_ops_rxtx_dma, +#elif defined(CONFIG_GD32F4_USART1_RXDMA) && !defined(CONFIG_GD32F4_USART1_TXDMA) + .ops = &g_uart_ops_rx_dma, +#elif !defined(CONFIG_GD32F4_USART1_RXDMA) && defined(CONFIG_GD32F4_USART1_TXDMA) + .ops = &g_uart_ops_tx_dma, +#else + .ops = &g_uart_ops_no_dma, +#endif + .priv = &g_usart1priv, +}; + +#endif + +/* This describes the state of the GD32 USART2 port. */ + +#ifdef CONFIG_GD32F4_USART2_SERIALDRIVER + +static struct up_dev_s g_usart2priv = +{ + .oversamp = USART_OVSMOD_16, + .usartbase = GD32_USART2, + .baud = CONFIG_USART2_BAUD, + .clock = GD32_PCLK1_FREQUENCY, + .irq = GD32_IRQ_USART2, + .parity = CONFIG_USART2_PARITY, + .bits = CONFIG_USART2_BITS, + .stop_2bits = CONFIG_USART2_2STOP, + + .tx_gpio = GPIO_USART2_TX, + .rx_gpio = GPIO_USART2_RX, +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_USART2_IFLOWCONTROL) + .iflow = true, + .rts_gpio = GPIO_USART2_RTS, +#endif +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_USART2_OFLOWCONTROL) + .oflow = true, + .cts_gpio = GPIO_USART2_CTS, +#endif +#ifdef CONFIG_GD32F4_USART2_TXDMA + .txdma_channel = DMA_CHANNEL_USART2_TX, +#endif +#ifdef CONFIG_GD32F4_USART2_RXDMA + .rxdma_channel = DMA_CHANNEL_USART2_RX, + .rxfifo = g_usart2rxfifo, +#endif + +#ifdef CONFIG_USART2_RS485 + .rs485_dir_gpio = GPIO_USART2_RS485_DIR, +# if (CONFIG_USART2_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif +}; + +static struct uart_dev_s g_usart2port = +{ +#if CONSOLE_UART == 2 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART2_RXBUFSIZE, + .buffer = g_usart2rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART2_TXBUFSIZE, + .buffer = g_usart2txbuffer, + }, +#if defined(CONFIG_GD32F4_USART2_RXDMA) && defined(CONFIG_GD32F4_USART2_TXDMA) + .ops = &g_uart_ops_rxtx_dma, +#elif defined(CONFIG_GD32F4_USART2_RXDMA) && !defined(CONFIG_GD32F4_USART2_TXDMA) + .ops = &g_uart_ops_rx_dma, +#elif !defined(CONFIG_GD32F4_USART2_RXDMA) && defined(CONFIG_GD32F4_USART2_TXDMA) + .ops = &g_uart_ops_tx_dma, +#else + .ops = &g_uart_ops_no_dma, +#endif + .priv = &g_usart2priv, +}; + +#endif + +/* This describes the state of the GD32 USART5 port. */ + +#ifdef CONFIG_GD32F4_USART5_SERIALDRIVER + +static struct up_dev_s g_usart5priv = +{ + .oversamp = USART_OVSMOD_16, + .usartbase = GD32_USART5, + .baud = CONFIG_USART5_BAUD, + .clock = GD32_PCLK2_FREQUENCY, + .irq = GD32_IRQ_USART5, + .parity = CONFIG_USART5_PARITY, + .bits = CONFIG_USART5_BITS, + .stop_2bits = CONFIG_USART5_2STOP, + + .tx_gpio = GPIO_USART5_TX, + .rx_gpio = GPIO_USART5_RX, +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_USART5_IFLOWCONTROL) + .iflow = true, + .rts_gpio = GPIO_USART5_RTS, +#endif +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_USART5_OFLOWCONTROL) + .oflow = true, + .cts_gpio = GPIO_USART5_CTS, +#endif +#ifdef CONFIG_GD32F4_USART5_TXDMA + .txdma_channel = DMA_CHANNEL_USART5_TX, +#endif +#ifdef CONFIG_GD32F4_USART5_RXDMA + .rxdma_channel = DMA_CHANNEL_USART5_RX, + .rxfifo = g_usart5rxfifo, +#endif + +#ifdef CONFIG_USART5_RS485 + .rs485_dir_gpio = GPIO_USART5_RS485_DIR, +# if (CONFIG_USART5_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif +}; + +static struct uart_dev_s g_usart5port = +{ +#if CONSOLE_UART == 5 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART5_RXBUFSIZE, + .buffer = g_usart5rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART5_TXBUFSIZE, + .buffer = g_usart5txbuffer, + }, +#if defined(CONFIG_GD32F4_USART5_RXDMA) && defined(CONFIG_GD32F4_USART5_TXDMA) + .ops = &g_uart_ops_rxtx_dma, +#elif defined(CONFIG_GD32F4_USART5_RXDMA) && !defined(CONFIG_GD32F4_USART5_TXDMA) + .ops = &g_uart_ops_rx_dma, +#elif !defined(CONFIG_GD32F4_USART5_RXDMA) && defined(CONFIG_GD32F4_USART5_TXDMA) + .ops = &g_uart_ops_tx_dma, +#else + .ops = &g_uart_ops_no_dma, +#endif + .priv = &g_usart5priv, +}; + +#endif + +/* This describes the state of the GD32 UART3 port. */ + +#ifdef CONFIG_GD32F4_UART3_SERIALDRIVER + +static struct up_dev_s g_uart3priv = +{ + .oversamp = USART_OVSMOD_16, + .usartbase = GD32_UART3, + .baud = CONFIG_UART3_BAUD, + .clock = GD32_PCLK1_FREQUENCY, + .irq = GD32_IRQ_UART3, + .parity = CONFIG_UART3_PARITY, + .bits = CONFIG_UART3_BITS, + .stop_2bits = CONFIG_UART3_2STOP, + + .tx_gpio = GPIO_UART3_TX, + .rx_gpio = GPIO_UART3_RX, +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_UART3_IFLOWCONTROL) + .iflow = true, + .rts_gpio = GPIO_UART3_RTS, +#endif +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_UART3_OFLOWCONTROL) + .oflow = true, + .cts_gpio = GPIO_UART3_CTS, +#endif +#ifdef CONFIG_GD32F4_UART3_TXDMA + .txdma_channel = DMA_CHANNEL_UART3_TX, +#endif +#ifdef CONFIG_GD32F4_UART3_RXDMA + .rxdma_channel = DMA_CHANNEL_UART3_RX, + .rxfifo = g_uart3rxfifo, +#endif + +#ifdef CONFIG_UART3_RS485 + .rs485_dir_gpio = GPIO_UART3_RS485_DIR, +# if (CONFIG_UART3_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif +}; + +static struct uart_dev_s g_uart3port = +{ +#if CONSOLE_UART == 3 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_UART3_RXBUFSIZE, + .buffer = g_uart3rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART3_TXBUFSIZE, + .buffer = g_uart3txbuffer, + }, +#if defined(CONFIG_GD32F4_UART3_RXDMA) && defined(CONFIG_GD32F4_UART3_TXDMA) + .ops = &g_uart_ops_rxtx_dma, +#elif defined(CONFIG_GD32F4_UART3_RXDMA) && !defined(CONFIG_GD32F4_UART3_TXDMA) + .ops = &g_uart_ops_rx_dma, +#elif !defined(CONFIG_GD32F4_UART3_RXDMA) && defined(CONFIG_GD32F4_UART3_TXDMA) + .ops = &g_uart_ops_tx_dma, +#else + .ops = &g_uart_ops_no_dma, +#endif + .priv = &g_uart3priv, +}; + +#endif + +/* This describes the state of the GD32 UART4 port. */ + +#ifdef CONFIG_GD32F4_UART4_SERIALDRIVER + +static struct up_dev_s g_uart4priv = +{ + .oversamp = USART_OVSMOD_16, + .usartbase = GD32_UART4, + .baud = CONFIG_UART4_BAUD, + .clock = GD32_PCLK1_FREQUENCY, + .irq = GD32_IRQ_UART4, + .parity = CONFIG_UART4_PARITY, + .bits = CONFIG_UART4_BITS, + .stop_2bits = CONFIG_UART4_2STOP, + + .tx_gpio = GPIO_UART4_TX, + .rx_gpio = GPIO_UART4_RX, +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_UART4_IFLOWCONTROL) + .iflow = true, + .rts_gpio = GPIO_UART4_RTS, +#endif +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_UART4_OFLOWCONTROL) + .oflow = true, + .cts_gpio = GPIO_UART4_CTS, +#endif +#ifdef CONFIG_GD32F4_UART4_TXDMA + .txdma_channel = DMA_CHANNEL_UART4_TX, +#endif +#ifdef CONFIG_GD32F4_UART4_RXDMA + .rxdma_channel = DMA_CHANNEL_UART4_RX, + .rxfifo = g_uart4rxfifo, +#endif + +#ifdef CONFIG_UART4_RS485 + .rs485_dir_gpio = GPIO_UART4_RS485_DIR, +# if (CONFIG_UART4_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif +}; + +static struct uart_dev_s g_uart4port = +{ +#if CONSOLE_UART == 3 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_UART4_RXBUFSIZE, + .buffer = g_uart4rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART4_TXBUFSIZE, + .buffer = g_uart4txbuffer, + }, +#if defined(CONFIG_GD32F4_UART4_RXDMA) && defined(CONFIG_GD32F4_UART4_TXDMA) + .ops = &g_uart_ops_rxtx_dma, +#elif defined(CONFIG_GD32F4_UART4_RXDMA) && !defined(CONFIG_GD32F4_UART4_TXDMA) + .ops = &g_uart_ops_rx_dma, +#elif !defined(CONFIG_GD32F4_UART4_RXDMA) && defined(CONFIG_GD32F4_UART4_TXDMA) + .ops = &g_uart_ops_tx_dma, +#else + .ops = &g_uart_ops_no_dma, +#endif + .priv = &g_uart4priv, +}; + +#endif + +/* This describes the state of the GD32 UART6 port. */ + +#ifdef CONFIG_GD32F4_UART6_SERIALDRIVER + +static struct up_dev_s g_uart6priv = +{ + .oversamp = USART_OVSMOD_16, + .usartbase = GD32_UART6, + .baud = CONFIG_UART6_BAUD, + .clock = GD32_PCLK1_FREQUENCY, + .irq = GD32_IRQ_UART6, + .parity = CONFIG_UART6_PARITY, + .bits = CONFIG_UART6_BITS, + .stop_2bits = CONFIG_UART6_2STOP, + + .tx_gpio = GPIO_UART6_TX, + .rx_gpio = GPIO_UART6_RX, +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_UART6_IFLOWCONTROL) + .iflow = true, + .rts_gpio = GPIO_UART6_RTS, +#endif +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_UART6_OFLOWCONTROL) + .oflow = true, + .cts_gpio = GPIO_UART6_CTS, +#endif +#ifdef CONFIG_GD32F4_UART6_TXDMA + .txdma_channel = DMA_CHANNEL_UART6_TX, +#endif +#ifdef CONFIG_GD32F4_UART6_RXDMA + .rxdma_channel = DMA_CHANNEL_UART6_TX, + .rxfifo = g_uart6rxfifo, +#endif + +#ifdef CONFIG_UART6_RS485 + .rs485_dir_gpio = GPIO_UART6_RS485_DIR, +# if (CONFIG_UART6_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif +}; + +static struct uart_dev_s g_uart6port = +{ +#if CONSOLE_UART == 3 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_UART6_RXBUFSIZE, + .buffer = g_uart6rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART6_TXBUFSIZE, + .buffer = g_uart6txbuffer, + }, +#if defined(CONFIG_GD32F4_UART6_RXDMA) && defined(CONFIG_GD32F4_UART6_TXDMA) + .ops = &g_uart_ops_rxtx_dma, +#elif defined(CONFIG_GD32F4_UART6_RXDMA) && !defined(CONFIG_GD32F4_UART6_TXDMA) + .ops = &g_uart_ops_rx_dma, +#elif !defined(CONFIG_GD32F4_UART6_RXDMA) && defined(CONFIG_GD32F4_UART6_TXDMA) + .ops = &g_uart_ops_tx_dma, +#else + .ops = &g_uart_ops_no_dma, +#endif + .priv = &g_uart6priv, +}; + +#endif + +/* This describes the state of the GD32 UART7 port. */ + +#ifdef CONFIG_GD32F4_UART7_SERIALDRIVER + +static struct up_dev_s g_uart7priv = +{ + .oversamp = USART_OVSMOD_16, + .usartbase = GD32_UART7, + .baud = CONFIG_UART7_BAUD, + .clock = GD32_PCLK1_FREQUENCY, + .irq = GD32_IRQ_UART7, + .parity = CONFIG_UART7_PARITY, + .bits = CONFIG_UART7_BITS, + .stop_2bits = CONFIG_UART7_2STOP, + + .tx_gpio = GPIO_UART7_TX, + .rx_gpio = GPIO_UART7_RX, +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_UART7_IFLOWCONTROL) + .iflow = true, + .rts_gpio = GPIO_UART7_RTS, +#endif +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_UART7_OFLOWCONTROL) + .oflow = true, + .cts_gpio = GPIO_UART7_CTS, +#endif +#ifdef CONFIG_GD32F4_UART7_TXDMA + .txdma_channel = DMA_CHANNEL_UART7_TX, +#endif +#ifdef CONFIG_GD32F4_UART7_RXDMA + .rxdma_channel = DMA_CHANNEL_UART7_TX, + .rxfifo = g_uart7rxfifo, +#endif + +#ifdef CONFIG_UART7_RS485 + .rs485_dir_gpio = GPIO_UART7_RS485_DIR, +# if (CONFIG_UART7_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif +}; + +static struct uart_dev_s g_uart7port = +{ +#if CONSOLE_UART == 3 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_UART7_RXBUFSIZE, + .buffer = g_uart7rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART7_TXBUFSIZE, + .buffer = g_uart7txbuffer, + }, +#if defined(CONFIG_GD32F4_UART7_RXDMA) && defined(CONFIG_GD32F4_UART7_TXDMA) + .ops = &g_uart_ops_rxtx_dma, +#elif defined(CONFIG_GD32F4_UART7_RXDMA) && !defined(CONFIG_GD32F4_UART7_TXDMA) + .ops = &g_uart_ops_rx_dma, +#elif !defined(CONFIG_GD32F4_UART7_RXDMA) && defined(CONFIG_GD32F4_UART7_TXDMA) + .ops = &g_uart_ops_tx_dma, +#else + .ops = &g_uart_ops_no_dma, +#endif + .priv = &g_uart7priv, +}; + +#endif + +/* This table lets us iterate over the configured USARTs */ + +static struct uart_dev_s * const g_uart_devs[GD32_NUSART] = +{ +#ifdef CONFIG_GD32F4_USART0_SERIALDRIVER + [0] = &g_usart0port, +#endif +#ifdef CONFIG_GD32F4_USART1_SERIALDRIVER + [1] = &g_usart1port, +#endif +#ifdef CONFIG_GD32F4_USART2_SERIALDRIVER + [2] = &g_usart2port, +#endif +#ifdef CONFIG_GD32F4_UART3_SERIALDRIVER + [3] = &g_uart3port, +#endif +#ifdef CONFIG_GD32F4_UART4_SERIALDRIVER + [4] = &g_uart4port, +#endif +#ifdef CONFIG_GD32F4_USART5_SERIALDRIVER + [5] = &g_usart5port, +#endif +#ifdef CONFIG_GD32F4_UART6_SERIALDRIVER + [6] = &g_uart6port, +#endif +#ifdef CONFIG_GD32F4_UART7_SERIALDRIVER + [7] = &g_uart7port, +#endif +}; + +#ifdef CONFIG_PM +static struct pm_callback_s g_serial_pmcb = +{ + .notify = up_pm_notify, + .prepare = up_pm_prepare, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_serialin + ****************************************************************************/ + +static inline uint32_t up_serialin(struct up_dev_s *priv, int offset) +{ + return getreg32(priv->usartbase + offset); +} + +/**************************************************************************** + * Name: up_serialout + ****************************************************************************/ + +static inline void up_serialout(struct up_dev_s *priv, int offset, + uint32_t value) +{ + putreg32(value, priv->usartbase + offset); +} + +/**************************************************************************** + * Name: up_setusartint + ****************************************************************************/ + +static void up_setusartint(struct up_dev_s *priv, uint32_t ie) +{ + uint8_t ctl; + uint32_t ctl_ie; + uint32_t regval; + + /* Save the USART interrupts */ + + priv->ie = ie; + + ctl = (USART_CFG_CTL_MASK & (ie >> USART_CFG_SHIFT)); + + /* Set interrupt in CTL0 register */ + + if (USART_CFG_CTL0_INT == (ctl & USART_CFG_CTL0_INT)) + { + ctl_ie = (ie << USART_CFG_CTL0_INT_SHIFT); + regval = up_serialin(priv, GD32_USART_CTL0_OFFSET); + regval &= ~(USART_CTL0_USED_INTS); + regval |= (ctl_ie & (USART_CTL0_USED_INTS)); + up_serialout(priv, GD32_USART_CTL0_OFFSET, regval); + } + + /* Set interrupt in CTL1 register */ + + if (USART_CFG_CTL1_INT == (ctl & USART_CFG_CTL1_INT)) + { + ctl_ie = (ie << USART_CFG_CTL1_INT_SHIFT); + regval = up_serialin(priv, GD32_USART_CTL1_OFFSET); + regval &= ~(USART_CTL1_USED_INTS); + regval |= (ctl_ie & (USART_CTL1_USED_INTS)); + up_serialout(priv, GD32_USART_CTL1_OFFSET, regval); + } + + /* Set interrupt in CTL2 register */ + + if (USART_CFG_CTL2_INT == (ctl & USART_CFG_CTL2_INT)) + { + ctl_ie = (ie >> USART_CFG_CTL2_INT_SHIFT); + regval = up_serialin(priv, GD32_USART_CTL2_OFFSET); + regval &= ~(USART_CTL2_USED_INTS); + regval |= (ctl_ie & (USART_CTL2_USED_INTS)); + up_serialout(priv, GD32_USART_CTL2_OFFSET, regval); + } + + /* Set interrupt in CTL3 register */ + + if (USART_CFG_CTL3_INT == (ctl & USART_CFG_CTL3_INT)) + { + ctl_ie = (ie >> USART_CFG_CTL3_INT_SHIFT); + regval = up_serialin(priv, GD32_USART_CTL3_OFFSET); + regval &= ~(USART_CTL3_USED_INTS); + regval |= (ctl_ie & (USART_CTL3_USED_INTS)); + up_serialout(priv, GD32_USART_CTL3_OFFSET, regval); + } +} + +/**************************************************************************** + * Name: up_disableusartint + ****************************************************************************/ + +static void up_disableusartint(struct up_dev_s *priv, uint32_t *ie) +{ + irqstate_t flags; + uint32_t ctl_ie; + + flags = enter_critical_section(); + + if (ie) + { + uint32_t ctl; + + /* Save interrupt in CTL0 register */ + + ctl = up_serialin(priv, GD32_USART_CTL0_OFFSET); + ctl_ie = ((ctl & USART_CTL0_USED_INTS) >> USART_CFG_CTL0_INT_SHIFT); + + /* Save interrupt in CTL1 register */ + + ctl = up_serialin(priv, GD32_USART_CTL1_OFFSET); + ctl_ie |= ((ctl & USART_CTL1_USED_INTS) >> USART_CFG_CTL1_INT_SHIFT); + + /* Save interrupt in CTL2 register */ + + ctl = up_serialin(priv, GD32_USART_CTL2_OFFSET); + ctl_ie |= ((ctl & USART_CTL2_USED_INTS) << USART_CFG_CTL2_INT_SHIFT); + + /* Save interrupt in CTL3 register */ + + ctl = up_serialin(priv, GD32_USART_CTL3_OFFSET); + ctl_ie |= ((ctl & USART_CTL3_USED_INTS) << USART_CFG_CTL3_INT_SHIFT); + + *ie = ctl_ie; + } + + /* Disable all interrupts */ + + ctl_ie = (USART_CFG_CTL_MASK << USART_CFG_SHIFT); + up_setusartint(priv, ctl_ie); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: up_restoreusartint + ****************************************************************************/ + +static void up_restoreusartint(struct up_dev_s *priv, uint32_t ie) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + up_setusartint(priv, ie); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: up_dma_nextrx + * + * Description: + * Returns the index into the RX FIFO where the DMA will place the next + * byte that it receives. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_RXDMA +static int up_dma_nextrx(struct up_dev_s *priv) +{ + size_t dmacount; + + dmacount = gd32_dma_tansnum_get(priv->rxdma); + + return (RXDMA_BUFFER_SIZE - (int)dmacount); +} +#endif + +/**************************************************************************** + * Name: gd32_usart_configure + * + * Description: + * Configure the USART. + * + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_UART_CONFIG +static void gd32_usart_configure(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + uint32_t udiv; + uint32_t intdiv; + uint32_t fradiv; + uint32_t regval; + + /* Reset USART */ + + gd32_usart_reset(priv->usartbase); + + /* Enable USART clock */ + + gd32_usart_clock_enable(priv->usartbase); + + /* Configure the USART oversample mode. */ + + regval = up_serialin(priv, GD32_USART_CTL0_OFFSET); + regval &= ~(USART_CTL0_OVSMOD); + regval |= priv->oversamp; + up_serialout(priv, GD32_USART_CTL0_OFFSET, regval); + + /* Configure USART baud rate value */ + + if ((priv->oversamp & USART_CTL0_OVSMOD) == USART_OVSMOD_8) + { + /* When oversampling by 8, configure the value of USART_BAUD */ + + udiv = ((priv->clock * 2) + priv->baud / 2) / priv->baud; + intdiv = udiv & 0xfff0; + fradiv = (udiv >> 1) & 0x7u; + } + else + { + /* When oversampling by 16, configure the value of USART_BAUD */ + + udiv = (priv->clock + priv->baud / 2) / priv->baud; + intdiv = udiv & 0xfff0; + fradiv = udiv & 0xf; + } + + regval = ((USART_BAUD_FRADIV_MASK | USART_BAUD_INTDIV_MASK) & + (intdiv | fradiv)); + up_serialout(priv, GD32_USART_BAUD_OFFSET, regval); + + /* Configure parity mode */ + + regval = up_serialin(priv, GD32_USART_CTL0_OFFSET); + regval &= ~(USART_CTL0_PM_MASK | USART_CTL0_WL); + + if (priv->parity == 1) + { + /* Configure as odd parity */ + + regval |= USART_CTL0_PM_ODD; + } + else if (priv->parity == 2) + { + /* Configure as even parity */ + + regval |= USART_CTL0_PM_EVEN; + } + + /* Configure USART word length */ + + if (priv->bits == 9 || (priv->bits == 8 && priv->parity != 0)) + { + regval |= USART_WL_9BIT; + } + else + { + regval |= USART_WL_8BIT; + } + + up_serialout(priv, GD32_USART_CTL0_OFFSET, regval); + + /* Configure STOP bits */ + + regval = up_serialin(priv, GD32_USART_CTL1_OFFSET); + regval &= ~(USART_CTL1_STB_MASK); + + if (priv->stop_2bits) + { + regval |= USART_CTL1_STB2BIT; + } + + up_serialout(priv, GD32_USART_CTL1_OFFSET, regval); + + /* Configure hardware flow control */ + + regval = up_serialin(priv, GD32_USART_CTL2_OFFSET); + regval &= ~(USART_CTL2_RTSEN | USART_CTL2_CTSEN); + +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && \ + !defined(CONFIG_GD32F4_FLOWCONTROL_BROKEN) + if (priv->iflow && (priv->rts_gpio != 0)) + { + regval |= USART_CTL2_RTSEN; + } +#endif + +#ifdef CONFIG_SERIAL_OFLOWCONTROL + if (priv->oflow && (priv->cts_gpio != 0)) + { + regval |= USART_CTL2_CTSEN; + } +#endif + + up_serialout(priv, GD32_USART_CTL2_OFFSET, regval); +} +#endif /* CONFIG_SUPPRESS_UART_CONFIG */ + +/**************************************************************************** + * Name: up_setup + * + * Description: + * Configure the USART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +static int up_setup(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + +#ifndef CONFIG_SUPPRESS_UART_CONFIG + uint32_t regval; + + /* Configure pins for USART use */ + + gd32_gpio_config(priv->tx_gpio); + gd32_gpio_config(priv->rx_gpio); + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->rts_gpio != 0) + { + uint32_t config = priv->rts_gpio; + +#ifdef CONFIG_GD32F4_FLOWCONTROL_BROKEN + /* Instead of letting hardware manage this pin, we will bitbang */ + + config = (config & ~GPIO_CFG_MODE_MASK) | GPIO_CFG_OUTPUT; +#endif + gd32_gpio_config(config); + } +#endif + +#ifdef CONFIG_SERIAL_OFLOWCONTROL + if (priv->cts_gpio != 0) + { + gd32_gpio_config(priv->cts_gpio); + } +#endif + +#ifdef HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + { + gd32_gpio_config(priv->rs485_dir_gpio); + gd32_gpio_write(priv->rs485_dir_gpio, !priv->rs485_dir_polarity); + } +#endif + + /* Configure the USART. */ + + gd32_usart_configure(dev); + + /* Enable USART receiver and transmmiter */ + + regval = up_serialin(priv, GD32_USART_CTL0_OFFSET); + regval |= (USART_CTL0_UEN | USART_CTL0_REN | USART_CTL0_TEN); + up_serialout(priv, GD32_USART_CTL0_OFFSET, regval); + +#endif /* CONFIG_SUPPRESS_UART_CONFIG */ + + /* Set up the cached interrupt enables value */ + + priv->ie = 0; + + /* Set initialize state. */ + + priv->initialized = true; + + return OK; +} + +/**************************************************************************** + * Name: up_dma_setup + * + * Description: + * Configure the USART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +#if defined(SERIAL_HAVE_RXDMA) || defined(SERIAL_HAVE_TXDMA) +static int up_dma_setup(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + int result; + + /* Do the basic UART setup first, unless we are the console */ + + if (!dev->isconsole) + { + result = up_setup(dev); + if (result != OK) + { + return result; + } + } + +#if defined(SERIAL_HAVE_TXDMA) + /* Acquire the Tx DMA channel. This should always succeed. */ + + if (priv->txdma_channel != 0) + { + priv->txdma = gd32_dma_channel_alloc(priv->txdma_channel); + + /* Enable DMA request for transmission */ + + modifyreg32(priv->usartbase + GD32_USART_CTL2_OFFSET, + 0, USART_CTL2_DENT); + } +#endif + +#if defined(SERIAL_HAVE_RXDMA) + /* Acquire the DMA channel. This should always succeed. */ + + if (priv->rxdma_channel != 0) + { + dma_single_data_parameter_struct dma_init_struct; + + priv->rxdma = gd32_dma_channel_alloc(priv->rxdma_channel); + + dma_init_struct.direction = DMA_PERIPH_TO_MEMORY; + dma_init_struct.memory0_addr = (uint32_t)priv->rxfifo; + dma_init_struct.number = RXDMA_BUFFER_SIZE; + dma_init_struct.periph_addr = priv->usartbase + GD32_USART_DATA_OFFSET; + dma_init_struct.periph_memory_width = DMA_WIDTH_8BITS_SELECT; + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.priority = USART_DMA_PRIO; + dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_ENABLE; + + /* Configure for circular DMA reception into the RX fifo */ + + gd32_dma_setup(priv->rxdma, &dma_init_struct, 1); + + /* Reset our DMA shadow pointer to match the address just + * programmed above. + */ + + priv->rxdmanext = 0; + + /* Enable receive Rx DMA for the UART */ + + modifyreg32(priv->usartbase + GD32_USART_CTL2_OFFSET, + 0, USART_CTL2_DENR); + + /* Start the DMA channel, and arrange for callbacks at the half and + * full points in the FIFO. This ensures that we have half a FIFO + * worth of time to claim bytes before they are overwritten. + */ + + gd32_dma_start(priv->rxdma, up_dma_rx_callback, (void *)dev, + USART_DMA_INTEN); + } +#endif + + return OK; +} +#endif + +/**************************************************************************** + * Name: up_shutdown + * + * Description: + * Disable the USART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void up_shutdown(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Reset initialize state. */ + + priv->initialized = false; + + /* Reset hardware and disable Rx and Tx */ + + gd32_usart_reset(priv->usartbase); + + /* Disable USART clock */ + + gd32_usart_clock_disable(priv->usartbase); + + /* Unconfigure RX, TX GPIO */ + + gd32_gpio_unconfig(priv->tx_gpio); + gd32_gpio_unconfig(priv->rx_gpio); + +#ifdef CONFIG_SERIAL_OFLOWCONTROL + if (priv->cts_gpio != 0) + { + gd32_gpio_unconfig(priv->cts_gpio); + } +#endif + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->rts_gpio != 0) + { + gd32_gpio_unconfig(priv->rts_gpio); + } +#endif + +#ifdef HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + { + gd32_gpio_unconfig(priv->rs485_dir_gpio); + } +#endif +} + +/**************************************************************************** + * Name: up_dma_shutdown + * + * Description: + * Disable the USART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +#if defined(SERIAL_HAVE_RXDMA) || defined(SERIAL_HAVE_TXDMA) +static void up_dma_shutdown(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Perform the normal UART shutdown */ + + up_shutdown(dev); + +#if defined(SERIAL_HAVE_RXDMA) + /* Stop the RX DMA channel */ + + if (priv->rxdma_channel != 0) + { + gd32_dma_stop(priv->rxdma); + + /* Release the RX DMA channel */ + + gd32_dma_channel_free(priv->rxdma); + priv->rxdma = NULL; + } +#endif + +#if defined(SERIAL_HAVE_TXDMA) + /* Stop the TX DMA channel */ + + if (priv->txdma_channel != 0) + { + gd32_dma_stop(priv->txdma); + + /* Release the TX DMA channel */ + + gd32_dma_channel_free(priv->txdma); + priv->txdma = NULL; + } +#endif +} +#endif + +/**************************************************************************** + * Name: up_attach + * + * Description: + * Configure the USART to operation in interrupt driven mode. This method + * is called when the serial port is opened. Normally, this is just after + * the setup() method is called, however, the serial console may operate + * in a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled when by the attach method (unless + * the hardware supports multiple levels of interrupt enabling). The RX + * and TX interrupts are not enabled until the txint() and rxint() methods + * are called. + * + ****************************************************************************/ + +static int up_attach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + int ret; + + /* Attach and enable the IRQ */ + + ret = irq_attach(priv->irq, up_interrupt, dev); + if (ret == OK) + { + /* Enable the interrupt (RX and TX interrupts are still disabled + * in the USART + */ + + up_enable_irq(priv->irq); + } + + return ret; +} + +/**************************************************************************** + * Name: up_detach + * + * Description: + * Detach USART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. The + * exception is the serial console which is never shutdown. + * + ****************************************************************************/ + +static void up_detach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + up_disable_irq(priv->irq); + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: up_interrupt + * + * Description: + * This is the UART status interrupt handler. It will be invoked when an + * interrupt received on the 'irq'. It should call uart_transmitchars or + * uart_receivechar to perform the appropriate data transfers. The + * interrupt handling logic must be able to map the 'irq' number into the + * appropriate uart_dev_s structure in order to call these functions. + * + ****************************************************************************/ + +static int up_interrupt(int irq, void *context, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + int passes; + bool handled; + + DEBUGASSERT(dev != NULL && priv != NULL); + +#if defined(CONFIG_PM) && CONFIG_GD32F4_PM_SERIAL_ACTIVITY > 0 + /* Report serial activity to the power management logic */ + + pm_activity(PM_IDLE_DOMAIN, CONFIG_GD32F4_PM_SERIAL_ACTIVITY); +#endif + + /* Loop until there are no characters to be transferred or, + * until we have been looping for a long time. + */ + + handled = true; + for (passes = 0; passes < 256 && handled; passes++) + { + handled = false; + + /* Get the current USART status. */ + + priv->sr = up_serialin(priv, GD32_USART_STAT0_OFFSET); + +#ifdef HAVE_RS485 + /* Transmission is complete. */ + + if (((priv->sr & USART_STAT0_TC) != 0) && + ((priv->ie & USART_CFG_CTL0_INT_TCIE) == + USART_CFG_CTL0_INT_TCIE) && + ((priv->ie & USART_CFG_CTL0_INT_TBEIE) != + USART_CFG_CTL0_INT_TBEIE)) + { + gd32_gpio_write(priv->rs485_dir_gpio, !priv->rs485_dir_polarity); + priv->ie &= ~USART_CFG_CTL0_INT_TCIE + priv->ie |= (0x0f000000 & USART_CFG_CTL0_INT_TCIE); + up_restoreusartint(priv, priv->ie); + } +#endif + + /* Handle incoming, receive bytes. */ + + if (((priv->sr & USART_STAT0_RBNE) != 0) && + ((priv->ie & USART_CFG_CTL0_INT_RBNEIE) == + USART_CFG_CTL0_INT_RBNEIE)) + { + uart_recvchars(dev); + handled = true; + } + +#ifdef SERIAL_HAVE_RXDMA + if (((priv->sr & USART_STAT0_IDLEF) != 0) && + ((priv->ie & USART_CFG_CTL0_INT_IDLIE) == + USART_CFG_CTL0_INT_IDLIE)) + { + uart_recvchars(dev); + up_serialin(priv, GD32_USART_DATA_OFFSET); + handled = true; + } +#endif + + /* Clear USART err flags. */ + + else if ((priv->sr & (USART_STAT0_ORERR | USART_STAT0_NERR | \ + USART_STAT0_FERR | USART_STAT0_PERR)) != 0) + { + up_serialin(priv, GD32_USART_DATA_OFFSET); + } + + /* Handle outgoing, transmit bytes */ + + if (((priv->sr & USART_STAT0_TBE) != 0) && + ((priv->ie & USART_CFG_CTL0_INT_TBEIE) == + USART_CFG_CTL0_INT_TBEIE)) + { + uart_xmitchars(dev); + handled = true; + } + } + + return OK; +} + +/**************************************************************************** + * Name: up_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int up_ioctl(struct file *filep, int cmd, unsigned long arg) +{ +#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT) \ + || defined(CONFIG_GD32F4_SERIALBRK_BSDCOMPAT) + struct inode *inode = filep->f_inode; + struct uart_dev_s *dev = inode->i_private; +#endif +#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_GD32F4_SERIALBRK_BSDCOMPAT) + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; +#endif + uint32_t regval; + int ret = OK; + + switch (cmd) + { +#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT + case TIOCSERGSTRUCT: + { + struct up_dev_s *user = (struct up_dev_s *)arg; + if (!user) + { + ret = -EINVAL; + } + else + { + memcpy(user, dev, sizeof(struct up_dev_s)); + } + } + break; +#endif + +#ifdef CONFIG_GD32F4_USART_SINGLEWIRE + case TIOCSSINGLEWIRE: + { + /* Change to single-wire operation. the RX pin is disconnected from + * the USART and the UUSARTART implements a half-duplex serial + * connection. The USART uses the TX pin for both receiving and + * transmitting. + */ + + regval = up_serialin(priv, GD32_USART_CTL2_OFFSET); + + if ((arg & SER_SINGLEWIRE_ENABLED) != 0) + { + uint32_t gpio_val = (arg & SER_SINGLEWIRE_PUSHPULL) == + SER_SINGLEWIRE_PUSHPULL ? + GPIO_CFG_PP : GPIO_CFG_OD; + gpio_val |= ((arg & SER_SINGLEWIRE_PULL_MASK) == + SER_SINGLEWIRE_PULLUP) ? GPIO_CFG_PUPD_PULLUP + : GPIO_CFG_PUPD_NONE; + gpio_val |= ((arg & SER_SINGLEWIRE_PULL_MASK) == + SER_SINGLEWIRE_PULLDOWN) ? GPIO_CFG_PUPD_PULLDOWN + : GPIO_CFG_PUPD_NONE; + gd32_gpio_config((priv->tx_gpio & ~(GPIO_CFG_ODPP_MASK | + GPIO_CFG_PUPD_MASK)) | + gpio_val); + regval |= USART_CTL2_HDEN; + } + else + { + gd32_gpio_config((priv->tx_gpio & ~(GPIO_CFG_ODPP_MASK | + GPIO_CFG_PUPD_MASK)) | + GPIO_CFG_PP); + regval &= ~USART_CTL2_HDEN; + } + + up_serialout(priv, GD32_USART_CTL2_OFFSET, regval); + } + break; +#endif + +#ifdef CONFIG_SERIAL_TERMIOS + case TCGETS: + { + struct termios *termiosp = (struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* The driver only support 8/9 bit modes and therefore is + * no way to report 9-bit mode, we always claim 8. + */ + + termiosp->c_cflag = + ((priv->parity != 0) ? PARENB : 0) | + ((priv->parity == 1) ? PARODD : 0) | + ((priv->stop_2bits) ? CSTOPB : 0) | +#ifdef CONFIG_SERIAL_IFLOWCONTROL + ((priv->iflow) ? CRTS_IFLOW : 0) | +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + ((priv->oflow) ? CCTS_OFLOW : 0) | +#endif + CS8; + + cfsetispeed(termiosp, priv->baud); + + /* TODO: CCTS_IFLOW, CCTS_OFLOW */ + } + break; + + case TCSETS: + { + struct termios *termiosp = (struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* Perform some sanity checks before accepting any changes */ + + if (((termiosp->c_cflag & CSIZE) != CS8) +#ifdef CONFIG_SERIAL_IFLOWCONTROL + || ((termiosp->c_cflag & CRTS_IFLOW) && (priv->rts_gpio == 0)) +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + || ((termiosp->c_cflag & CCTS_OFLOW) && (priv->cts_gpio == 0)) +#endif + ) + { + ret = -EINVAL; + break; + } + + if (termiosp->c_cflag & PARENB) + { + priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2; + } + else + { + priv->parity = 0; + } + + priv->stop_2bits = (termiosp->c_cflag & CSTOPB) != 0; +#ifdef CONFIG_SERIAL_IFLOWCONTROL + priv->iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0; +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0; +#endif + + /* Note that since there is no way to request 9-bit mode + * and no way to support 5/6/7-bit modes, we ignore them + * all here. + */ + + /* Note that only cfgetispeed is used because we have knowledge + * that only one speed is supported. + */ + + priv->baud = cfgetispeed(termiosp); + + /* Effect the changes immediately - note that we do not implement + * TCSADRAIN / TCSAFLUSH + */ + + gd32_usart_configure(dev); + } + break; +#endif /* CONFIG_SERIAL_TERMIOS */ + +#ifdef CONFIG_GD32F4_USART_BREAKS +# ifdef CONFIG_GD32F4_SERIALBRK_BSDCOMPAT + case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ + { + irqstate_t flags; + uint32_t tx_break; + + flags = enter_critical_section(); + + /* Disconnect TX to USART */ + + up_txint(dev, false); + + /* Configure TX as a GPIO output pin and Send a break signal */ + + tx_break = (~(GPIO_CFG_MODE_MASK | GPIO_CFG_OUTPUT_SET) & + priv->tx_gpio) | GPIO_CFG_MODE_OUTPUT; + gd32_gpio_config(tx_break); + + leave_critical_section(flags); + } + break; + + case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ + { + irqstate_t flags; + + flags = enter_critical_section(); + + /* Connect TX to USART */ + + gd32_gpio_config(priv->tx_gpio); + + /* Enable further tx activity */ + + up_txint(dev, true); + + leave_critical_section(flags); + } + break; +# else + case TIOCSBRK: /* No BSD compatibility: Turn break on for M bit times */ + { + irqstate_t flags; + + flags = enter_critical_section(); + regval = up_serialin(priv, GD32_USART_CTL0_OFFSET); + regval |= USART_CTL0_SBKCMD; + up_serialout(priv, GD32_USART_CTL0_OFFSET, regval); + leave_critical_section(flags); + } + break; + + case TIOCCBRK: /* No BSD compatibility: May turn off break too soon */ + { + uint32_t cr1; + irqstate_t flags; + + flags = enter_critical_section(); + regval = up_serialin(priv, GD32_USART_CTL0_OFFSET); + regval &= ~ USART_CTL0_SBKCMD; + up_serialout(priv, GD32_USART_CTL0_OFFSET, regval); + leave_critical_section(flags); + } + break; +# endif +#endif + + /* Only availible in USART0,1,2,5 */ + +#ifdef CONFIG_GD32F4_USART_INVERT + case TIOCSINVERT: + { + uint32_t regaddr; + irqstate_t flags; + + flags = enter_critical_section(); + + regval = up_serialin(priv, GD32_USART_CTL3_OFFSET); + + if (arg & SER_INVERT_ENABLED_RX) + { + regval |= USART_CTL3_RINV; + } + else + { + regval &= ~USART_CTL3_RINV; + } + + if (arg & SER_INVERT_ENABLED_TX) + { + regval |= USART_CTL3_TINV; + } + else + { + regval &= ~USART_CTL3_TINV; + } + + /* R/TINV bit fields can written when UEN in CTL0 is 0 */ + + regaddr = GD32_USART_CTL0(priv->usartbase); + + /* Clear UEN bit */ + + modifyreg32(regaddr, USART_CTL0_UEN, 0); + + up_serialout(priv, GD32_USART_CTL3_OFFSET, regval); + + /* Set UEN bit */ + + modifyreg32(regaddr, 0, USART_CTL0_UEN); + + leave_critical_section(flags); + } + break; +#endif + + default: + ret = -ENOTTY; + break; + } + + UNUSED(regval); + + return ret; +} + +/**************************************************************************** + * Name: up_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the USART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +#if defined(SERIAL_HAVE_TX_DMA) || defined(SERIAL_NOT_HAVE_DMA) +static int up_receive(struct uart_dev_s *dev, unsigned int *status) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + uint32_t data; + + /* Get the receive data */ + + data = up_serialin(priv, GD32_USART_DATA_OFFSET); + + /* Get the receive data and error flag. Return those in status */ + + /* Return status information */ + + if (status) + { + *status = priv->sr; + priv->sr = 0; + } + + /* Then return the receive data */ + + return data & 0xff; +} +#endif + +/**************************************************************************** + * Name: up_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +#if defined(SERIAL_HAVE_TX_DMA) || defined(SERIAL_NOT_HAVE_DMA) +static void up_rxint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + irqstate_t flags; + uint32_t ie; + + flags = enter_critical_section(); + ie = priv->ie; + if (enable) + { + /* Receive an interrupt when their is anything in the Rx data register + * (or an Rx timeout occurs). + */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS +#ifdef CONFIG_USART_ERRINTS + ie |= (USART_CFG_CTL0_INT_RBNEIE | USART_CFG_CTL0_INT_PERRIE | + USART_CFG_CTL2_INT_ERRIE); +#else + ie |= USART_CFG_CTL0_INT_RBNEIE; +#endif +#endif + } + else + { + ie &= ~(USART_CFG_CTL0_INT_RBNEIE | USART_CFG_CTL0_INT_PERRIE | + USART_CFG_CTL2_INT_ERRIE); + } + + /* Then set the new interrupt state */ + + up_restoreusartint(priv, ie); + leave_critical_section(flags); +} +#endif + +/**************************************************************************** + * Name: up_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +#if defined(SERIAL_HAVE_TX_DMA) || defined(SERIAL_NOT_HAVE_DMA) +static bool up_rxavailable(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* return true if read data buffer not empty */ + + return ((up_serialin(priv, GD32_USART_STAT0_OFFSET) & + USART_STAT0_RBNE) != 0); +} +#endif + +/**************************************************************************** + * Name: up_rxflowcontrol + * + * Description: + * Called when Rx buffer is full (or exceeds configured watermark levels + * if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is defined). + * Return true if UART activated RX flow control to block more incoming + * data + * + * Input Parameters: + * dev - UART device instance + * nbuffered - the number of characters currently buffered + * (if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is + * not defined the value will be 0 for an empty buffer or the + * defined buffer size for a full buffer) + * upper - true indicates the upper watermark was crossed where + * false indicates the lower watermark has been crossed + * + * Returned Value: + * true if RX flow control activated. + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_IFLOWCONTROL +static bool up_rxflowcontrol(struct uart_dev_s *dev, + unsigned int nbuffered, bool upper) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + +#if defined(CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS) && \ + defined(CONFIG_GD32F4_FLOWCONTROL_BROKEN) + if (priv->iflow && (priv->rts_gpio != 0)) + { + /* Set it high resume/stop sending */ + + gd32_gpio_write(priv->rts_gpio, upper); + + if (upper) + { + /* Return 'false' so input data is still being processed + * until sending end reacts on nRTS signal and stops sending more. + */ + + return false; + } + + return upper; + } + +#else + if (priv->iflow) + { + /* Is the RX buffer full? */ + + if (upper) + { + /* Disable Rx interrupt to prevent more data being from + * peripheral. When hardware RTS is enabled, this will + * prevent more data from coming in. + * + * This function is only called when UART recv buffer is full, + * that is: "dev->recv.head + 1 == dev->recv.tail". + * + * Logic in "uart_read" will automatically toggle Rx interrupts + * when buffer is read empty and thus we do not have to re- + * enable Rx interrupts. + */ + + uart_disablerxint(dev); + return true; + } + + /* No.. The RX buffer is empty */ + + else + { + /* We might leave Rx interrupt disabled if full recv buffer was + * read empty. Enable Rx interrupt to make sure that more input is + * received. + */ + + uart_enablerxint(dev); + } + } +#endif + + return false; +} +#endif + +/**************************************************************************** + * Name: up_dma_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the USART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_RXDMA +static int up_dma_receive(struct uart_dev_s *dev, unsigned int *status) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + int c = 0; + + if (up_dma_nextrx(priv) != priv->rxdmanext) + { + /* Invalidate the DMA buffer */ + + up_invalidate_dcache((uintptr_t)priv->rxfifo, + (uintptr_t)priv->rxfifo + RXDMA_BUFFER_SIZE); + + /* Read from the DMA buffer */ + + c = priv->rxfifo[priv->rxdmanext]; + + priv->rxdmanext++; + if (priv->rxdmanext == RXDMA_BUFFER_SIZE) + { + priv->rxdmanext = 0; + } + } + + return c; +} +#endif + +/**************************************************************************** + * Name: up_dma_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_RXDMA +static void up_dma_rxint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + irqstate_t flags; + uint32_t ie; + + /* Enable or disable DMA reception. + * + * Note that it is not safe to check for available bytes and immediately + * pass them to uart_recvchars as that could potentially recurse back + * to us again. Instead, bytes must wait until the next up_dma_poll or + * DMA event. + */ + + priv->rxenable = enable; + + flags = enter_critical_section(); + + ie = priv->ie; + if (enable) + { + /* Receive an interrupt when the DMA receive data. */ + + ie |= USART_CFG_CTL0_INT_IDLIE; + } + else + { + ie &= ~(USART_CFG_CTL0_INT_RBNEIE | USART_CFG_CTL0_INT_PERRIE | + USART_CFG_CTL2_INT_ERRIE); + } + + /* Then set the new interrupt state */ + + up_restoreusartint(priv, ie); + leave_critical_section(flags); +} +#endif + +/**************************************************************************** + * Name: up_dma_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_RXDMA +static bool up_dma_rxavailable(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Compare our receive pointer to the current DMA pointer, if they + * do not match, then there are bytes to be received. + */ + + return (up_dma_nextrx(priv) != priv->rxdmanext); +} +#endif + +/**************************************************************************** + * Name: up_dma_tx_callback + * + * Description: + * This function clears dma buffer at complete of DMA transfer and wakes up + * threads waiting for space in buffer. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_TXDMA +static void up_dma_tx_callback(DMA_HANDLE handle, uint16_t status, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Update 'nbytes' indicating number of bytes actually transferred by DMA. + * This is important to free TX buffer space by 'uart_xmitchars_done'. + */ + + if (status & DMA_INTF_FTFIF) + { + dev->dmatx.nbytes += dev->dmatx.length; + if (dev->dmatx.nlength) + { + /* Set up DMA on next buffer */ + + dma_single_data_parameter_struct dma_init_struct; + + dma_init_struct.direction = DMA_MEMORY_TO_PERIPH; + dma_init_struct.memory0_addr = (uint32_t)dev->dmatx.nbuffer; + dma_init_struct.number = dev->dmatx.nlength; + dma_init_struct.periph_addr = priv->usartbase + + GD32_USART_DATA_OFFSET; + dma_init_struct.periph_memory_width = DMA_WIDTH_8BITS_SELECT; + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.priority = USART_DMA_PRIO; + dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_DISABLE; + + /* Configure DMA for USART transmmit */ + + gd32_dma_setup(priv->txdma, &dma_init_struct, 1); + + /* Set length for the next completion */ + + dev->dmatx.length = dev->dmatx.nlength; + dev->dmatx.nlength = 0; + + /* Start transmission with the callback on DMA completion */ + + gd32_dma_start(priv->txdma, up_dma_tx_callback, + (void *)dev, USART_DMA_INTEN); + + return; + } + } + else if (status & DMA_INTF_HTFIF) + { + dev->dmatx.nbytes += dev->dmatx.length / 2; + } + + /* Adjust the pointers */ + + uart_xmitchars_done(dev); +} +#endif + +/**************************************************************************** + * Name: up_dma_txavailable + * + * Description: + * Informs DMA that Tx data is available and is ready for transfer. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_TXDMA +static void up_dma_txavailable(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Only send when the DMA is idle */ + + if (gd32_dma_tansnum_get(priv->txdma) == 0) + { + uart_xmitchars_dma(dev); + } +} +#endif + +/**************************************************************************** + * Name: up_dma_send + * + * Description: + * Called (usually) from the interrupt level to start DMA transfer. + * (Re-)Configures DMA Stream updating buffer and buffer length. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_TXDMA +static void up_dma_send(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* We need to stop DMA before reconfiguration */ + + gd32_dma_stop(priv->txdma); + + /* Reset the number sent */ + + dev->dmatx.nbytes = 0; + + /* Make use of setup function to update buffer and its length for + * next transfer + */ + + /* Set up DMA on next buffer */ + + dma_single_data_parameter_struct dma_init_struct; + + dma_init_struct.direction = DMA_MEMORY_TO_PERIPH; + + dma_init_struct.memory0_addr = (uint32_t)dev->dmatx.buffer; + dma_init_struct.number = dev->dmatx.length; + dma_init_struct.periph_addr = priv->usartbase + GD32_USART_DATA_OFFSET; + dma_init_struct.periph_memory_width = DMA_WIDTH_8BITS_SELECT; + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.priority = USART_DMA_PRIO; + dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_DISABLE; + + /* Configure DMA for USART transmmit */ + + gd32_dma_setup(priv->txdma, &dma_init_struct, 1); + + /* Start transmission with the callback on DMA completion */ + + gd32_dma_start(priv->txdma, up_dma_tx_callback, + (void *)dev, USART_DMA_INTEN); + + while (up_txempty(dev) == 0); +} +#endif + +/**************************************************************************** + * Name: up_send + * + * Description: + * This method will send one byte on the USART + * + ****************************************************************************/ + +static void up_send(struct uart_dev_s *dev, int ch) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; +#ifdef HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + { + gd32_gpio_write(priv->rs485_dir_gpio, priv->rs485_dir_polarity); + } +#endif + + up_serialout(priv, GD32_USART_DATA_OFFSET, + (uint32_t)(ch & USART_DATA_MASK)); +} + +/**************************************************************************** + * Name: up_dma_txint + * + * Description: + * Call to enable or disable TX interrupts from the UART. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_TXDMA +static void up_dma_txint(struct uart_dev_s *dev, bool enable) +{ + /* Nothing to do. */ +} +#endif + +/**************************************************************************** + * Name: up_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +#if defined(SERIAL_HAVE_RX_DMA) || defined(SERIAL_NOT_HAVE_DMA) || \ + defined(CONFIG_GD32F4_SERIALBRK_BSDCOMPAT) +static void up_txint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + if (enable) + { + /* Enable the TX interrupt */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + uint32_t ie = priv->ie | USART_CFG_CTL0_INT_TBEIE; + + /* If RS-485 is supported on this USART, also enable the TCIE */ + +# ifdef HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + { + ie |= USART_CFG_CTL0_INT_TCIE; + } +# endif + + up_setusartint(priv, ie); + +#else + /* Fake a TX interrupt here by just calling uart_xmitchars() with + * interrupts disabled (note this may recurse). + */ + + uart_xmitchars(dev); +#endif + } + else + { + /* Disable the TX interrupt */ + + priv->ie &= ~USART_CFG_CTL0_INT_TBEIE; + priv->ie |= (0x0f000000 & USART_CFG_CTL0_INT_TBEIE); + up_setusartint(priv, priv->ie); + } + + leave_critical_section(flags); +} +#endif + +/**************************************************************************** + * Name: up_txready + * + * Description: + * Return true if the transmit data register is empty + * + ****************************************************************************/ + +static bool up_txready(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + return ((up_serialin(priv, GD32_USART_STAT0_OFFSET) & + USART_STAT0_TBE) != 0); +} + +/**************************************************************************** + * Name: up_txempty + * + * Description: + * Return true if the transmit data register is empty + * + ****************************************************************************/ + +static bool up_txempty(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Return true if transmit data buffer empty */ + + return ((up_serialin(priv, GD32_USART_STAT0_OFFSET) & + USART_STAT0_TC) != 0); +} + +/**************************************************************************** + * Name: up_dma_rx_callback + * + * Description: + * This function checks the current DMA state and calls the generic + * serial stack when bytes appear to be available. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_RXDMA +static void up_dma_rx_callback(DMA_HANDLE handle, uint16_t status, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + if (priv->rxenable && up_dma_rxavailable(dev)) + { + uart_recvchars(dev); + } +} +#endif + +/**************************************************************************** + * Name: up_pm_notify + * + * Description: + * Notify the driver of new power state. This callback is called after + * all drivers have had the opportunity to prepare for the new power state. + * + * Input Parameters: + * + * cb - Returned to the driver. The driver version of the callback + * structure may include additional, driver-specific state data at + * the end of the structure. + * + * pmstate - Identifies the new PM state + * + * Returned Value: + * None - The driver already agreed to transition to the low power + * consumption state when when it returned OK to the prepare() call. + * + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void up_pm_notify(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + switch (pmstate) + { + case(PM_NORMAL): + { + /* Logic for PM_NORMAL goes here */ + } + break; + + case(PM_IDLE): + { + /* Logic for PM_IDLE goes here */ + } + break; + + case(PM_STANDBY): + { + /* Logic for PM_STANDBY goes here */ + } + break; + + case(PM_SLEEP): + { + /* Logic for PM_SLEEP goes here */ + } + break; + + default: + { + /* Should not get here */ + } + break; + } +} +#endif + +/**************************************************************************** + * Name: up_pm_prepare + * + * Description: + * Request the driver to prepare for a new power state. This is a warning + * that the system is about to enter into a new power state. The driver + * should begin whatever operations that may be required to enter power + * state. The driver may abort the state change mode by returning a + * non-zero value from the callback function. + * + * Input Parameters: + * + * cb - Returned to the driver. The driver version of the callback + * structure may include additional, driver-specific state data at + * the end of the structure. + * + * pmstate - Identifies the new PM state + * + * Returned Value: + * Zero - (OK) means the event was successfully processed and that the + * driver is prepared for the PM state change. + * + * Non-zero - means that the driver is not prepared to perform the tasks + * needed achieve this power setting and will cause the state + * change to be aborted. NOTE: The prepare() method will also + * be called when reverting from lower back to higher power + * consumption modes (say because another driver refused a + * lower power state change). Drivers are not permitted to + * return non-zero values when reverting back to higher power + * consumption modes! + * + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static int up_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + /* Logic to prepare for a reduced power state goes here. */ + + return OK; +} +#endif +#endif /* HAVE_SERIALDRIVER */ +#endif /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef USE_SERIALDRIVER + +/**************************************************************************** + * Name: arm_earlyserialinit + * + * Description: + * Performs the low level USART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before arm_serialinit. + * + ****************************************************************************/ + +#ifdef USE_EARLYSERIALINIT +void arm_earlyserialinit(void) +{ +#ifdef HAVE_SERIALDRIVER + unsigned i; + + /* Disable all USART interrupts */ + + for (i = 0; i < GD32_NUSART; i++) + { + if (g_uart_devs[i]->priv) + { + up_disableusartint(g_uart_devs[i]->priv, 0); + } + } + + /* Configure whichever one is the console */ + + up_setup(g_uart_devs[CONSOLE_UART]); +#endif /* HAVE UART */ +} +#endif + +/**************************************************************************** + * Name: arm_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that arm_earlyserialinit was called previously. + * + ****************************************************************************/ + +void arm_serialinit(void) +{ +#ifdef HAVE_SERIALDRIVER + char devname[16]; + unsigned i; + unsigned start = 0; +#ifdef CONFIG_PM + int ret; +#endif + + /* Register to receive power management callbacks */ + +#ifdef CONFIG_PM + ret = pm_register(&g_serial_pmcb); + DEBUGASSERT(ret == OK); + UNUSED(ret); +#endif + + /* Register the console */ + +#ifdef CONSOLE_UART + uart_register("/dev/console", g_uart_devs[CONSOLE_UART]); + +#ifndef CONFIG_GD32F4_SERIAL_DISABLE_REORDERING + /* If not disabled, register the console UART to ttyS0 and exclude + * it from initializing it further down + */ + + uart_register("/dev/ttyS0", g_uart_devs[CONSOLE_UART]); + start = 1; +#endif + +#if defined(SERIAL_HAVE_CONSOLE_RXDMA) || defined(SERIAL_HAVE_CONSOLE_TXDMA) + /* If we need to re-initialise the console to enable DMA do that here. */ + + up_dma_setup(g_uart_devs[CONSOLE_UART]); +#endif +#endif /* CONSOLE_UART */ + + /* Register all remaining USARTs */ + + strcpy(devname, "/dev/ttySx"); + + for (i = 0; i < GD32_NUSART; i++) + { + /* Don't create a device for non-configured ports. */ + + if (g_uart_devs[i] == 0) + { + continue; + } + +#ifndef CONFIG_GD32F4_SERIAL_DISABLE_REORDERING + /* Don't create a device for the console - we did that above */ + + if (g_uart_devs[i]->isconsole) + { + continue; + } +#endif + + /* Register USARTs as devices in increasing order */ + + devname[9] = '0' + start++; + uart_register(devname, g_uart_devs[i]); + } +#endif /* HAVE UART */ +} + +/**************************************************************************** + * Name: gd32_serial_dma_poll + * + * Description: + * Checks receive DMA buffers for received bytes that have not accumulated + * to the point where the DMA half/full interrupt has triggered. + * + * This function should be called from a timer or other periodic context. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_RXDMA +void gd32_serial_dma_poll(void) +{ + irqstate_t flags; + + flags = enter_critical_section(); + +#ifdef CONFIG_GD32F4_USART0_RXDMA + if (g_usart0priv.rxdma != NULL) + { + up_dma_rx_callback(g_usart0priv.rxdma, 0, &g_usart0port); + } +#endif + +#ifdef CONFIG_GD32F4_USART1_RXDMA + if (g_usart1priv.rxdma != NULL) + { + up_dma_rx_callback(g_usart1priv.rxdma, 0, &g_usart1port); + } +#endif + +#ifdef CONFIG_GD32F4_USART2_RXDMA + if (g_usart2priv.rxdma != NULL) + { + up_dma_rx_callback(g_usart2priv.rxdma, 0, &g_usart2port); + } +#endif + +#ifdef CONFIG_GD32F4_UART3_RXDMA + if (g_uart3priv.rxdma != NULL) + { + up_dma_rx_callback(g_uart3priv.rxdma, 0, &g_uart3port); + } +#endif + +#ifdef CONFIG_GD32F4_UART4_RXDMA + if (g_uart4priv.rxdma != NULL) + { + up_dma_rx_callback(g_uart4priv.rxdma, 0, &g_uart4port); + } +#endif + +#ifdef CONFIG_GD32F4_USART5_RXDMA + if (g_usart5priv.rxdma != NULL) + { + up_dma_rx_callback(g_usart5priv.rxdma, 0, &g_usart5port); + } +#endif + +#ifdef CONFIG_GD32F4_UART6_RXDMA + if (g_uart6priv.rxdma != NULL) + { + up_dma_rx_callback(g_uart6priv.rxdma, 0, &g_uart6port); + } +#endif + +#ifdef CONFIG_GD32F4_UART7_RXDMA + if (g_uart7priv.rxdma != NULL) + { + up_dma_rx_callback(g_uart7priv.rxdma, 0, &g_uart7port); + } +#endif + + leave_critical_section(flags); +} +#endif + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef CONSOLE_UART + + struct up_dev_s *priv = (struct up_dev_s *)g_uart_devs[CONSOLE_UART]->priv; + uint32_t ie; + + up_disableusartint(priv, &ie); + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + arm_lowputc('\r'); + } + + arm_lowputc(ch); + up_restoreusartint(priv, ie); +#endif + return ch; +} + +#else /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef CONSOLE_UART + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + arm_lowputc('\r'); + } + + arm_lowputc(ch); +#endif + return ch; +} + +#endif /* USE_SERIALDRIVER */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_spi.c b/arch/arm/src/gd32f4/gd32f4xx_spi.c new file mode 100644 index 0000000000..86cfec3ca4 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_spi.c @@ -0,0 +1,2433 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_spi.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * The external functions, gd32_spi0/1/2/3/4/5select and gd32_spi0/1/2/3/4/5 + * status must be provided by board-specific logic. They are implementations + * of the select and status methods of the SPI interface defined by + * struct spi_ops_s (see include/nuttx/spi/spi.h). + * All other methods (including gd32_spibus_initialize()) are provided by + * common GD32F4 logic. To use this common SPI logic on your board: + * + * 1. Provide logic in gd32_boardinitialize() to configure SPI chip select + * pins. + * 2. Provide gd32_spi[n]select() and gd32_spi[n]status() functions + * in your board-specific logic. These functions will perform chip + * selection and status operations using GPIOs in the way your board is + * configured. + * 3. Add a calls to gd32_spibus_initialize() in your low level + * application initialization logic + * 4. The handle returned by gd32_spibus_initialize() may then be used to + * bind the SPI driver to higher level logic (e.g., calling + * mmcsd_spislotinitialize(), for example, will bind the SPI driver to + * the SPI MMC/SD driver). + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "arm_internal.h" + +#include "chip.h" +#include "gd32f4xx.h" +#include "gd32f4xx_spi.h" + +#if defined(CONFIG_GD32F4_SPI0) || defined(CONFIG_GD32F4_SPI1) || \ + defined(CONFIG_GD32F4_SPI2) || defined(CONFIG_GD32F4_SPI3) || \ + defined(CONFIG_GD32F4_SPI4) || defined(CONFIG_GD32F4_SPI5) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define GD32_SPI_CLK_MAX (30000000ul) +#define GD32_SPI_CLK_INIT (400000) + +/* SPI parameter initialization mask */ + +#define SPI_INIT_MASK ((uint32_t)0x00003040u) /* SPI parameter initialization mask */ + +/* SPI interrupts */ + +#ifdef CONFIG_GD32F4_SPI_INTERRUPT +# error "Now SPI interrupt has not yet supported" +#endif + +#ifdef CONFIG_GD32F4_SPI_DMA + +# error "Now SPI DMA has not ready" + +/* SPI DMA priority */ + +#if defined(CONFIG_GD32F4_SPI_PRIQ) +# define SPI_DMA_PRIO CONFIG_GD32F4_SPI_PRIQ +#else +# define SPI_DMA_PRIO DMA_PRIO_MEDIUM_SELECT +#endif + +# define SPI_DMA_BUFFER_MASK (4 - 1) +# define SPI_DMA_BUFEER_ALIGN aligned_data(4) + +# if defined(CONFIG_GD32F4_SPI0_DMA_BUFFER) && CONFIG_GD32F4_SPI0_DMA_BUFFER > 0 +# define SPI0_DMA_BUFSIZE_ADJ ((CONFIG_GD32F4_SPI0_DMA_BUFFER + SPI_DMA_BUFFER_MASK) & \ + ~SPI_DMA_BUFFER_MASK) +# endif + +# if defined(CONFIG_GD32F4_SPI1_DMA_BUFFER) && CONFIG_GD32F4_SPI1_DMA_BUFFER > 0 +# define SPI1_DMA_BUFSIZE_ADJ ((CONFIG_GD32F4_SPI1_DMA_BUFFER + SPI_DMA_BUFFER_MASK) & \ + ~SPI_DMA_BUFFER_MASK) +# endif + +# if defined(CONFIG_GD32F4_SPI2_DMA_BUFFER) && CONFIG_GD32F4_SPI2_DMA_BUFFER > 0 +# define SPI2_DMA_BUFSIZE_ADJ ((CONFIG_GD32F4_SPI2_DMA_BUFFER + SPI_DMA_BUFFER_MASK) & \ + ~SPI_DMA_BUFFER_MASK) +# endif + +# if defined(CONFIG_GD32F4_SPI3_DMA_BUFFER) && CONFIG_GD32F4_SPI3_DMA_BUFFER > 0 +# define SPI3_DMA_BUFSIZE_ADJ ((CONFIG_GD32F4_SPI3_DMA_BUFFER + SPI_DMA_BUFFER_MASK) & \ + ~SPI_DMA_BUFFER_MASK) +# endif + +# if defined(CONFIG_GD32F4_SPI4_DMA_BUFFER) && CONFIG_GD32F4_SPI4_DMA_BUFFER > 0 +# define SPI4_DMA_BUFSIZE_ADJ ((CONFIG_GD32F4_SPI4_DMA_BUFFER + SPI_DMA_BUFFER_MASK) & \ + ~SPI_DMA_BUFFER_MASK) +# endif + +# if defined(CONFIG_GD32F4_SPI5_DMA_BUFFER) && CONFIG_GD32F4_SPI5_DMA_BUFFER > 0 +# define SPI5_DMA_BUFSIZE_ADJ ((CONFIG_GD32F4_SPI5_DMA_BUFFER + SPI_DMA_BUFFER_MASK) & \ + ~SPI_DMA_BUFFER_MASK) +# endif + +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct gd32_spidev_s +{ + struct spi_dev_s spidev; /* Externally visible part of the SPI interface */ + uint32_t spibase; /* SPIn spibase address */ + uint32_t spiclock; /* Clocking for the SPI module */ + uint32_t frequency; /* Requested clock frequency */ + uint32_t actual; /* Actual clock frequency */ + sem_t exclsem; /* Held while chip is selected for mutual exclusion */ + uint8_t nbits; /* Width of word in bits (8 to 16) */ + uint8_t mode; /* Mode 0,1,2,3 */ +#ifdef CONFIG_GD32F4_SPI_INTERRUPT + uint8_t spiirq; /* SPI IRQ number */ +#endif +#ifdef CONFIG_GD32F4_SPI_DMA + volatile uint16_t rxresult; /* Result of the RX DMA */ + volatile uint16_t txresult; /* Result of the RX DMA */ +#ifdef CONFIG_SPI_TRIGGER + bool defertrig; /* Flag indicating that trigger should be deferred */ + bool trigarmed; /* Flag indicating that the trigger is armed */ +#endif + uint8_t rxch; /* The RX DMA channel number */ + uint8_t txch; /* The TX DMA channel number */ + uint8_t *rxbuf; /* The RX DMA buffer */ + uint8_t *txbuf; /* The TX DMA buffer */ + size_t buflen; /* The DMA buffer length */ + DMA_HANDLE rxdma; /* DMA channel handle for RX transfers */ + DMA_HANDLE txdma; /* DMA channel handle for TX transfers */ + sem_t rxsem; /* Wait for RX DMA to complete */ + sem_t txsem; /* Wait for TX DMA to complete */ +#endif + bool initialized; /* Has SPI interface been initialized */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Clock */ + +static void gd32_spi_reset(uint32_t spibase); +static void gd32_spi_clock_enable(uint32_t spibase); +static void gd32_spi_clock_disable(uint32_t spibase); + +/* Helpers */ + +static inline uint32_t spi_getreg(struct gd32_spidev_s *priv, + uint8_t offset); +static inline void spi_putreg(struct gd32_spidev_s *priv, + uint8_t offset, uint32_t value); +static inline uint16_t spi_getreg16(struct gd32_spidev_s *priv, + uint8_t offset); +static inline void spi_putreg16(struct gd32_spidev_s *priv, + uint8_t offset, uint16_t value); +static inline uint8_t spi_getreg8(struct gd32_spidev_s *priv, + uint8_t offset); +static inline void spi_putreg8(struct gd32_spidev_s *priv, + uint8_t offset, uint8_t value); + +static inline uint16_t spi_readword(struct gd32_spidev_s *priv); +static inline void spi_writeword(struct gd32_spidev_s *priv, + uint16_t byte); + +/* SPI methods */ + +static int spi_lock(struct spi_dev_s *dev, bool lock); +static uint32_t spi_setfrequency(struct spi_dev_s *dev, + uint32_t frequency); +static void spi_setmode(struct spi_dev_s *dev, + enum spi_mode_e mode); +static void spi_setbits(struct spi_dev_s *dev, int nbits); +#ifdef CONFIG_SPI_HWFEATURES +static int spi_hwfeatures(struct spi_dev_s *dev, + spi_hwfeatures_t features); +#endif +static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd); +static void spi_exchange(struct spi_dev_s *dev, + const void *txbuffer, + void *rxbuffer, size_t nwords); +#ifdef CONFIG_SPI_TRIGGER +static int spi_trigger(struct spi_dev_s *dev); +#endif +#ifndef CONFIG_SPI_EXCHANGE +static void spi_sndblock(struct spi_dev_s *dev, + const void *txbuffer, size_t nwords); +static void spi_recvblock(struct spi_dev_s *dev, + void *rxbuffer, size_t nwords); +#endif + +/* DMA support */ + +#ifdef CONFIG_GD32F4_SPI_DMA +static int spi_dmarxwait(struct gd32_spidev_s *priv); +static int spi_dmatxwait(struct gd32_spidev_s *priv); +static void spi_dmarxcallback(DMA_HANDLE handle, uint16_t isr, + void *arg); +static void spi_dmatxcallback(DMA_HANDLE handle, uint16_t isr, + void *arg); +static void spi_dmarxsetup(struct gd32_spidev_s *priv, + void *rxbuffer, void *rxdummy, + size_t nwords); +static void spi_dmatxsetup(struct gd32_spidev_s *priv, + const void *txbuffer, + const void *txdummy, + size_t nwords); +static inline void spi_dmarxstart(struct gd32_spidev_s *priv); +static inline void spi_dmatxstart(struct gd32_spidev_s *priv); +#endif + +/* Initialization */ + +static void spi_bus_initialize(struct gd32_spidev_s *priv); +static void gd32_spi_gpio_config(uint32_t spibase); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_GD32F4_SPI0 +static const struct spi_ops_s g_spi0ops = +{ + .lock = spi_lock, + .select = gd32_spi0select, + .setfrequency = spi_setfrequency, + .setmode = spi_setmode, + .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif + .status = gd32_spi0status, +#ifdef CONFIG_SPI_CMDDATA + .cmddata = gd32_spi0cmddata, +#endif + .send = spi_send, +#ifdef CONFIG_SPI_EXCHANGE + .exchange = spi_exchange, +#else + .sndblock = spi_sndblock, + .recvblock = spi_recvblock, +#endif +#ifdef CONFIG_SPI_TRIGGER + .trigger = spi_trigger, +#endif +#ifdef CONFIG_SPI_CALLBACK + .registercallback = gd32_spi0register, /* Provided externally */ +#else + .registercallback = 0, /* Not implemented */ +#endif +}; + +#if defined(SPI0_DMA_BUFSIZE_ADJ) +static uint8_t g_spi0_txbuf[SPI0_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +static uint8_t g_spi0_rxbuf[SPI0_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +#endif + +static struct gd32_spidev_s g_spi0dev = +{ + .spidev = + { + &g_spi0ops + }, + .spibase = GD32_SPI0, + .spiclock = GD32_PCLK2_FREQUENCY, +#ifdef CONFIG_GD32F4_SPI_INTERRUPT + .spiirq = GD32_IRQ_SPI0, +#endif +#ifdef CONFIG_GD32F4_SPI_DMA +# ifdef CONFIG_GD32F4_SPI0_DMA + .rxch = DMA_CHANNEL_SPI0_RX, + .txch = DMA_CHANNEL_SPI0_TX, +# if defined(SPI0_DMA_BUFSIZE_ADJ) + .rxbuf = g_spi0_rxbuf, + .txbuf = g_spi0_txbuf, + .buflen = SPI0_DMA_BUFSIZE_ADJ, +# endif +# else + .rxch = 0, + .txch = 0, +# endif +#endif +}; +#endif + +#ifdef CONFIG_GD32F4_SPI1 +static const struct spi_ops_s g_spi1ops = +{ + .lock = spi_lock, + .select = gd32_spi1select, + .setfrequency = spi_setfrequency, + .setmode = spi_setmode, + .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif + .status = gd32_spi1status, +#ifdef CONFIG_SPI_CMDDATA + .cmddata = gd32_spi1cmddata, +#endif + .send = spi_send, +#ifdef CONFIG_SPI_EXCHANGE + .exchange = spi_exchange, +#else + .sndblock = spi_sndblock, + .recvblock = spi_recvblock, +#endif +#ifdef CONFIG_SPI_TRIGGER + .trigger = spi_trigger, +#endif +#ifdef CONFIG_SPI_CALLBACK + .registercallback = gd32_spi1register, /* Provided externally */ +#else + .registercallback = 0, /* Not implemented */ +#endif +}; + +#if defined(SPI1_DMA_BUFSIZE_ADJ) +static uint8_t g_spi1_txbuf[SPI1_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +static uint8_t g_spi1_rxbuf[SPI1_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +#endif + +static struct gd32_spidev_s g_spi1dev = +{ + .spidev = + { + &g_spi1ops + }, + .spibase = GD32_SPI1, + .spiclock = GD32_PCLK1_FREQUENCY, +#ifdef CONFIG_GD32F4_SPI_INTERRUPT + .spiirq = GD32_IRQ_SPI1, +#endif +#ifdef CONFIG_GD32F4_SPI_DMA +# ifdef CONFIG_GD32F4_SPI1_DMA + .rxch = DMA_CHANNEL_SPI1_RX, + .txch = DMA_CHANNEL_SPI1_TX, +# if defined(SPI1_DMA_BUFSIZE_ADJ) + .rxbuf = g_spi1_rxbuf, + .txbuf = g_spi1_txbuf, + .buflen = SPI1_DMA_BUFSIZE_ADJ, +# endif +# else + .rxch = 0, + .txch = 0, +# endif +#endif +}; +#endif + +#ifdef CONFIG_GD32F4_SPI2 +static const struct spi_ops_s g_spi2ops = +{ + .lock = spi_lock, + .select = gd32_spi2select, + .setfrequency = spi_setfrequency, + .setmode = spi_setmode, + .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif + .status = gd32_spi2status, +#ifdef CONFIG_SPI_CMDDATA + .cmddata = gd32_spi2cmddata, +#endif + .send = spi_send, +#ifdef CONFIG_SPI_EXCHANGE + .exchange = spi_exchange, +#else + .sndblock = spi_sndblock, + .recvblock = spi_recvblock, +#endif +#ifdef CONFIG_SPI_TRIGGER + .trigger = spi_trigger, +#endif +#ifdef CONFIG_SPI_CALLBACK + .registercallback = gd32_spi2register, /* Provided externally */ +#else + .registercallback = 0, /* Not implemented */ +#endif +}; + +#if defined(SPI2_DMA_BUFSIZE_ADJ) +static uint8_t g_spi2_txbuf[SPI2_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +static uint8_t g_spi2_rxbuf[SPI2_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +#endif + +static struct gd32_spidev_s g_spi2dev = +{ + .spidev = + { + &g_spi2ops + }, + .spibase = GD32_SPI2, + .spiclock = GD32_PCLK1_FREQUENCY, +#ifdef CONFIG_GD32F4_SPI_INTERRUPT + .spiirq = GD32_IRQ_SPI2, +#endif +#ifdef CONFIG_GD32F4_SPI_DMA +# ifdef CONFIG_GD32F4_SPI2_DMA + .rxch = DMA_CHANNEL_SPI2_RX, + .txch = DMA_CHANNEL_SPI2_TX, +# if defined(SPI2_DMA_BUFSIZE_ADJ) + .rxbuf = g_spi2_rxbuf, + .txbuf = g_spi2_txbuf, + .buflen = SPI2_DMA_BUFSIZE_ADJ, +# endif +# else + .rxch = 0, + .txch = 0, +# endif +#endif +}; +#endif + +#ifdef CONFIG_GD32F4_SPI3 +static const struct spi_ops_s g_spi3ops = +{ + .lock = spi_lock, + .select = gd32_spi3select, + .setfrequency = spi_setfrequency, + .setmode = spi_setmode, + .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif + .status = gd32_spi3status, +#ifdef CONFIG_SPI_CMDDATA + .cmddata = gd32_spi3cmddata, +#endif + .send = spi_send, +#ifdef CONFIG_SPI_EXCHANGE + .exchange = spi_exchange, +#else + .sndblock = spi_sndblock, + .recvblock = spi_recvblock, +#endif +#ifdef CONFIG_SPI_TRIGGER + .trigger = spi_trigger, +#endif +#ifdef CONFIG_SPI_CALLBACK + .registercallback = gd32_spi3register, /* Provided externally */ +#else + .registercallback = 0, /* Not implemented */ +#endif +}; + +#if defined(SPI3_DMA_BUFSIZE_ADJ) +static uint8_t g_spi3_txbuf[SPI3_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +static uint8_t g_spi3_rxbuf[SPI3_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +#endif + +static struct gd32_spidev_s g_spi3dev = +{ + .spidev = + { + &g_spi3ops + }, + .spibase = GD32_SPI3, + .spiclock = GD32_PCLK2_FREQUENCY, +#ifdef CONFIG_GD32F4_SPI_INTERRUPT + .spiirq = GD32_IRQ_SPI3, +#endif +#ifdef CONFIG_GD32F4_SPI_DMA +# ifdef CONFIG_GD32F4_SPI3_DMA + .rxch = DMA_CHANNEL_SPI3_RX, + .txch = DMA_CHANNEL_SPI3_TX, +# if defined(SPI3_DMA_BUFSIZE_ADJ) + .rxbuf = g_spi3_rxbuf, + .txbuf = g_spi3_txbuf, + .buflen = SPI3_DMA_BUFSIZE_ADJ, +# endif +# else + .rxch = 0, + .txch = 0, +# endif +#endif +}; +#endif + +#ifdef CONFIG_GD32F4_SPI4 +static const struct spi_ops_s g_spi4ops = +{ + .lock = spi_lock, + .select = gd32_spi4select, + .setfrequency = spi_setfrequency, + .setmode = spi_setmode, + .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif + .status = gd32_spi4status, +#ifdef CONFIG_SPI_CMDDATA + .cmddata = gd32_spi4cmddata, +#endif + .send = spi_send, +#ifdef CONFIG_SPI_EXCHANGE + .exchange = spi_exchange, +#else + .sndblock = spi_sndblock, + .recvblock = spi_recvblock, +#endif +#ifdef CONFIG_SPI_TRIGGER + .trigger = spi_trigger, +#endif +#ifdef CONFIG_SPI_CALLBACK + .registercallback = gd32_spi4register, /* Provided externally */ +#else + .registercallback = 0, /* Not implemented */ +#endif +}; + +#if defined(SPI4_DMA_BUFSIZE_ADJ) +static uint8_t g_spi4_txbuf[SPI4_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +static uint8_t g_spi4_rxbuf[SPI4_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +#endif + +static struct gd32_spidev_s g_spi4dev = +{ + .spidev = + { + &g_spi4ops + }, + .spibase = GD32_SPI4, + .spiclock = GD32_PCLK2_FREQUENCY, +#ifdef CONFIG_GD32F4_SPI_INTERRUPT + .spiirq = GD32_IRQ_SPI4, +#endif +#ifdef CONFIG_GD32F4_SPI_DMA +# ifdef CONFIG_GD32F4_SPI4_DMA + .rxch = DMA_CHANNEL_SPI4_RX, + .txch = DMA_CHANNEL_SPI4_TX, +# if defined(SPI4_DMA_BUFSIZE_ADJ) + .rxbuf = g_spi4_rxbuf, + .txbuf = g_spi4_txbuf, + .buflen = SPI4_DMA_BUFSIZE_ADJ, +# endif +# else + .rxch = 0, + .txch = 0, +# endif +#endif +}; +#endif + +#ifdef CONFIG_GD32F4_SPI5 +static const struct spi_ops_s g_spi5ops = +{ + .lock = spi_lock, + .select = gd32_spi5select, + .setfrequency = spi_setfrequency, + .setmode = spi_setmode, + .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif + .status = gd32_spi5status, +#ifdef CONFIG_SPI_CMDDATA + .cmddata = gd32_spi5cmddata, +#endif + .send = spi_send, +#ifdef CONFIG_SPI_EXCHANGE + .exchange = spi_exchange, +#else + .sndblock = spi_sndblock, + .recvblock = spi_recvblock, +#endif +#ifdef CONFIG_SPI_TRIGGER + .trigger = spi_trigger, +#endif +#ifdef CONFIG_SPI_CALLBACK + .registercallback = gd32_spi5register, /* Provided externally */ +#else + .registercallback = 0, /* Not implemented */ +#endif +}; + +#if defined(SPI5_DMA_BUFSIZE_ADJ) +static uint8_t g_spi5_txbuf[SPI5_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +static uint8_t g_spi5_rxbuf[SPI5_DMA_BUFSIZE_ADJ] SPI_DMA_BUFEER_ALIGN; +#endif + +static struct gd32_spidev_s g_spi5dev = +{ + .spidev = + { + &g_spi5ops + }, + .spibase = GD32_SPI5, + .spiclock = GD32_PCLK2_FREQUENCY, +#ifdef CONFIG_GD32F5_SPI_INTERRUPT + .spiirq = GD32_IRQ_SPI5, +#endif +#ifdef CONFIG_GD32F4_SPI_DMA +# ifdef CONFIG_GD32F4_SPI5_DMA + .rxch = DMA_CHANNEL_SPI5_RX, + .txch = DMA_CHANNEL_SPI5_TX, +# if defined(SPI5_DMA_BUFSIZE_ADJ) + .rxbuf = g_spi5_rxbuf, + .txbuf = g_spi5_txbuf, + .buflen = SPI5_DMA_BUFSIZE_ADJ, +# endif +# else + .rxch = 0, + .txch = 0, +# endif +#endif +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_spi_reset + * + * Description: + * Reset the SPI. + * + ****************************************************************************/ + +static void gd32_spi_reset(uint32_t spibase) +{ + uint32_t rcu_rst; + uint32_t regaddr; + + /* Determine which SPI to configure */ + + switch (spibase) + { + default: + return; +#ifdef CONFIG_GD32F4_SPI0 + case GD32_SPI0: + rcu_rst = RCU_APB2RST_SPI0RST; + regaddr = GD32_RCU_APB2RST; + break; +#endif +#ifdef CONFIG_GD32F4_SPI1 + case GD32_SPI1: + rcu_rst = RCU_APB1RST_SPI1RST; + regaddr = GD32_RCU_APB1RST; + break; +#endif +#ifdef CONFIG_GD32F4_SPI2 + case GD32_SPI2: + rcu_rst = RCU_APB1RST_SPI2RST; + regaddr = GD32_RCU_APB1RST; + break; +#endif +#ifdef CONFIG_GD32F4_SPI3 + case GD32_SPI3: + rcu_rst = RCU_APB2RST_SPI3RST; + regaddr = GD32_RCU_APB2RST; + break; +#endif +#ifdef CONFIG_GD32F4_SPI4 + case GD32_SPI4: + rcu_rst = RCU_APB2RST_SPI4RST; + regaddr = GD32_RCU_APB2RST; + break; +#endif +#ifdef CONFIG_GD32F4_SPI5 + case GD32_SPI5: + rcu_rst = RCU_APB2RST_SPI5RST; + regaddr = GD32_RCU_APB2RST; + break; +#endif + } + + /* Enable APB 1/2 reset for SPI */ + + modifyreg32(regaddr, 0, rcu_rst); + + /* Disable APB 1/2 reset for SPI */ + + modifyreg32(regaddr, rcu_rst, 0); +} + +/**************************************************************************** + * Name: gd32_spi_clock_enable + * + * Description: + * Enable SPI clock + ****************************************************************************/ + +static void gd32_spi_clock_enable(uint32_t spibase) +{ + uint32_t rcu_en; + uint32_t regaddr; + + /* Determine which SPI to configure */ + + switch (spibase) + { + default: + return; +#ifdef CONFIG_GD32F4_SPI0 + case GD32_SPI0: + rcu_en = RCU_APB2EN_SPI0EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif +#ifdef CONFIG_GD32F4_SPI1 + case GD32_SPI1: + rcu_en = RCU_APB1EN_SPI1EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_SPI2 + case GD32_SPI2: + rcu_en = RCU_APB1EN_SPI2EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_SPI3 + case GD32_SPI3: + rcu_en = RCU_APB2EN_SPI3EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif +#ifdef CONFIG_GD32F4_SPI4 + case GD32_SPI4: + rcu_en = RCU_APB2EN_SPI4EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif +#ifdef CONFIG_GD32F4_SPI5 + case GD32_SPI5: + rcu_en = RCU_APB2EN_SPI5EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif + } + + /* Enable APB 1/2 clock for SPI */ + + modifyreg32(regaddr, 0, rcu_en); +} + +/**************************************************************************** + * Name: gd32_spi_clock_disable + * + * Description: + * Dinable SPI clock + ****************************************************************************/ + +static void gd32_spi_clock_disable(uint32_t spibase) +{ + uint32_t rcu_en; + uint32_t regaddr; + + /* Determine which SPI to configure */ + + switch (spibase) + { + default: + return; +#ifdef CONFIG_GD32F4_SPI0 + case GD32_SPI0: + rcu_en = RCU_APB2EN_SPI0EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif +#ifdef CONFIG_GD32F4_SPI1 + case GD32_SPI1: + rcu_en = RCU_APB1EN_SPI1EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_SPI2 + case GD32_SPI2: + rcu_en = RCU_APB1EN_SPI2EN; + regaddr = GD32_RCU_APB1EN; + break; +#endif +#ifdef CONFIG_GD32F4_SPI3 + case GD32_SPI3: + rcu_en = RCU_APB2EN_SPI3EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif +#ifdef CONFIG_GD32F4_SPI4 + case GD32_SPI4: + rcu_en = RCU_APB2EN_SPI4EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif +#ifdef CONFIG_GD32F4_SPI5 + case GD32_SPI5: + rcu_en = RCU_APB2EN_SPI5EN; + regaddr = GD32_RCU_APB2EN; + break; +#endif + } + + /* Disable APB 1/2 clock for SPI */ + + modifyreg32(regaddr, rcu_en, 0); +} + +/**************************************************************************** + * Name: spi_getreg + * + * Description: + * Get the contents of the SPI register at offset + * + * Input Parameters: + * priv - private SPI device structure + * offset - offset to the register of interest + * + * Returned Value: + * The contents of the 32-bit register + * + ****************************************************************************/ + +static inline uint32_t spi_getreg(struct gd32_spidev_s *priv, + uint8_t offset) +{ + return getreg32(priv->spibase + offset); +} + +/**************************************************************************** + * Name: spi_putreg + * + * Description: + * Write a 32-bit value to the SPI register at offset + * + * Input Parameters: + * priv - private SPI device structure + * offset - offset to the register of interest + * value - the 32-bit value to be written + * + * Returned Value: + * The contents of the 32-bit register + * + ****************************************************************************/ + +static inline void spi_putreg(struct gd32_spidev_s *priv, + uint8_t offset, uint32_t value) +{ + putreg32(value, priv->spibase + offset); +} + +/**************************************************************************** + * Name: spi_getreg16 + * + * Description: + * Get the 16 bit contents of the SPI register at offset + * + * Input Parameters: + * priv - private SPI device structure + * offset - offset to the register of interest + * + * Returned Value: + * The contents of the 16-bit register + * + ****************************************************************************/ + +static inline uint16_t spi_getreg16(struct gd32_spidev_s *priv, + uint8_t offset) +{ + return getreg16(priv->spibase + offset); +} + +/**************************************************************************** + * Name: spi_putreg16 + * + * Description: + * Write a 16-bit value to the SPI register at offset + * + * Input Parameters: + * priv - private SPI device structure + * offset - offset to the register of interest + * value - the 16-bit value to be written + * + * Returned Value: + * Nothing + * + ****************************************************************************/ + +static inline void spi_putreg16(struct gd32_spidev_s *priv, + uint8_t offset, uint16_t value) +{ + putreg16(value, priv->spibase + offset); +} + +/**************************************************************************** + * Name: spi_getreg8 + * + * Description: + * Get the 8 bit contents of the SPI register at offset + * + * Input Parameters: + * priv - private SPI device structure + * offset - offset to the register of interest + * + * Returned Value: + * The contents of the 8-bit register + * + ****************************************************************************/ + +static inline uint8_t spi_getreg8(struct gd32_spidev_s *priv, + uint8_t offset) +{ + return getreg8(priv->spibase + offset); +} + +/**************************************************************************** + * Name: spi_putreg8 + * + * Description: + * Write a 8-bit value to the SPI register at offset + * + * Input Parameters: + * priv - private SPI device structure + * offset - offset to the register of interest + * value - the 8-bit value to be written + * + * Returned Value: + * Nothing + * + ****************************************************************************/ + +static inline void spi_putreg8(struct gd32_spidev_s *priv, + uint8_t offset, uint8_t value) +{ + putreg8(value, priv->spibase + offset); +} + +/**************************************************************************** + * Name: spi_modifyreg + * + * Description: + * Clear and set bits in the register + * + * Input Parameters: + * priv - Device-specific state data + * clrbits - The bits to clear + * setbits - The bits to set + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void spi_modifyreg(struct gd32_spidev_s *priv, uint32_t offset, + uint16_t setbits, uint16_t clrbits) +{ + uint32_t regval; + regval = spi_getreg(priv, offset); + regval &= ~clrbits; + regval |= setbits; + spi_putreg(priv, offset, regval); +} + +/**************************************************************************** + * Name: spi_wait_status + * + * Description: + * Wait for bit to be set in status + * + * Input Parameters: + * priv - Device-specific state data + * status- bit to wait on. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void spi_wait_status(struct gd32_spidev_s *priv, + uint32_t offset, uint32_t status) +{ + while (status != (spi_getreg(priv, offset) & status)); +} + +/**************************************************************************** + * Name: spi_readword + * + * Description: + * Read one 16 bit word from SPI DATA + * + * Input Parameters: + * priv - Device-specific state data + * + * Returned Value: + * 16 bit word as read + * + ****************************************************************************/ + +static inline uint16_t spi_readword(struct gd32_spidev_s *priv) +{ + /* Wait until the receive buffer is not empty */ + + spi_wait_status(priv, GD32_SPI_STAT_OFFSET, SPI_STAT_RBNE); + + /* Return the data */ + + return spi_getreg16(priv, GD32_SPI_DATA_OFFSET); +} + +/**************************************************************************** + * Name: spi_writeword + * + * Description: + * Write 16 bit word from SPI DATA + * + * Input Parameters: + * priv - Device-specific state data + * word - 16 bit word to send + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void spi_writeword(struct gd32_spidev_s *priv, + uint16_t word) +{ + /* Wait until the transmit buffer is empty */ + + spi_wait_status(priv, GD32_SPI_STAT_OFFSET, SPI_STAT_TBE); + + /* Then send the word */ + + spi_putreg(priv, GD32_SPI_DATA_OFFSET, (uint32_t)word); +} + +/**************************************************************************** + * Name: spi_lock + * + * Description: + * On SPI buses where there are multiple devices, it will be necessary to + * lock SPI to have exclusive access to the buses for a sequence of + * transfers. The bus should be locked before the chip is selected. After + * locking the SPI bus, the caller should then also call the setfrequency, + * setbits, and setmode methods to make sure that the SPI is properly + * configured for the device. If the SPI bus is being shared, then it + * may have been left in an incompatible state. + * + * Input Parameters: + * dev - Device-specific state data + * lock - true: Lock spi bus, false: unlock SPI bus + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int spi_lock(struct spi_dev_s *dev, bool lock) +{ + struct gd32_spidev_s *priv = (struct gd32_spidev_s *)dev; + int ret; + + if (lock) + { + ret = nxsem_wait_uninterruptible(&priv->exclsem); + } + else + { + ret = nxsem_post(&priv->exclsem); + } + + return ret; +} + +/**************************************************************************** + * Name: spi_setfrequency + * + * Description: + * Set the SPI frequency. + * + * Input Parameters: + * dev - Device-specific state data + * frequency - The SPI frequency requested + * + * Returned Value: + * Returns the actual frequency selected + * + ****************************************************************************/ + +static uint32_t spi_setfrequency(struct spi_dev_s *dev, + uint32_t frequency) +{ + struct gd32_spidev_s *priv = (struct gd32_spidev_s *)dev; + + uint16_t setbits; + uint32_t actual; + uint32_t plk_div; + + /* Check if the requested frequence is the same as the frequency + * selection. + */ + + if (priv->frequency == frequency) + { + /* We are already at this frequency. Return the actual. */ + + return priv->actual; + } + + /* Check if requested frequency reasonable */ + + if (frequency > GD32_SPI_CLK_MAX) + { + frequency = GD32_SPI_CLK_MAX; + } + else if (frequency == 0) + { + frequency = GD32_SPI_CLK_INIT; + } + + /* Configure SCK frequency. + * + * SCK frequency = PCLK / plk_div, or plk_div = PCLK / frequency + */ + + plk_div = priv->spiclock / frequency; + + if (plk_div < 2) + { + plk_div = 2; + } + else if (plk_div > 256) + { + plk_div = 256; + } + + if (plk_div > 128) + { + setbits = SPI_CTL0_PSC_256; + } + else if (plk_div > 64) + { + setbits = SPI_CTL0_PSC_128; + } + else if (plk_div > 32) + { + setbits = SPI_CTL0_PSC_64; + } + else if (plk_div > 16) + { + setbits = SPI_CTL0_PSC_32; + } + else if (plk_div > 8) + { + setbits = SPI_CTL0_PSC_16; + } + else if (plk_div > 4) + { + setbits = SPI_CTL0_PSC_8; + } + else if (plk_div > 2) + { + setbits = SPI_CTL0_PSC_4; + } + else + { + setbits = SPI_CTL0_PSC_2; + } + + spi_modifyreg(priv, GD32_SPI_CTL0_OFFSET, 0, SPI_CTL0_SPIEN); + spi_modifyreg(priv, GD32_SPI_CTL0_OFFSET, setbits, SPI_CTL0_PSC_MASK); + spi_modifyreg(priv, GD32_SPI_CTL0_OFFSET, SPI_CTL0_SPIEN, 0); + + actual = priv->spiclock >> ((setbits >> SPI_CTL0_PSC_SHIFT) + 1); + + /* Save the frequency selection so that subsequent reconfigurations + * will be faster. + */ + + spiinfo("Frequency %" PRIu32 "->%" PRIu32 "\n", frequency, actual); + + priv->frequency = frequency; + priv->actual = actual; + + return priv->actual; +} + +/**************************************************************************** + * Name: spi_setmode + * + * Description: + * Set the SPI mode. see enum spi_mode_e for mode definitions + * + * Input Parameters: + * dev - Device-specific state data + * mode - The SPI mode requested + * + * Returned Value: + * Returns the actual frequency selected + * + ****************************************************************************/ + +static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode) +{ + struct gd32_spidev_s *priv = (struct gd32_spidev_s *)dev; + + uint32_t regval0; + uint32_t regval1; + + spiinfo("mode=%d\n", mode); + + /* Has the mode changed? */ + + if (mode != priv->mode) + { + /* Yes... Set CTL0 appropriately */ + + regval0 = spi_getreg(priv, GD32_SPI_CTL0_OFFSET); + regval0 &= ~(SPI_CTL0_CKPH | SPI_CTL0_CKPL); + regval1 = spi_getreg(priv, GD32_SPI_CTL1_OFFSET); + regval1 &= ~ SPI_CTL1_TMOD; + + switch (mode) + { + case SPIDEV_MODE0: /* CKPL=0, CKPH=0 */ + break; + + case SPIDEV_MODE1: /* CKPL=0, CKPH=1 */ + regval0 |= SPI_CTL0_CKPH; + break; + + case SPIDEV_MODE2: /* CKPL=1, CKPH=0 */ + regval0 |= SPI_CTL0_CKPL; + break; + + case SPIDEV_MODE3: /* CKPL=1, CKPH=1 */ + regval0 |= (SPI_CTL0_CKPH | SPI_CTL0_CKPL); + break; + +#ifdef SPI_TMOD_EN /* If MCU TI Synchronous Serial Frame Format enable */ + case SPIDEV_MODETI: + regval0 = (SPI_CTL0_CKPH | SPI_CTL0_CKPL); + regval1 | SPI_CTL1_TMOD; + break; +#endif + + default: + return; + } + + spi_modifyreg(priv, GD32_SPI_CTL0_OFFSET, 0, SPI_CTL0_SPIEN); + spi_putreg(priv, GD32_SPI_CTL0_OFFSET, regval0); + spi_putreg(priv, GD32_SPI_CTL1_OFFSET, regval1); + spi_modifyreg(priv, GD32_SPI_CTL0_OFFSET, SPI_CTL0_SPIEN, 0); + + /* Save the mode so that subsequent re-configurations will be + * faster + */ + + priv->mode = mode; + } +} + +/**************************************************************************** + * Name: spi_setbits + * + * Description: + * Set the number of bits per word. + * + * Input Parameters: + * dev - Device-specific state data + * nbits - The number of bits requested + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void spi_setbits(struct spi_dev_s *dev, int nbits) +{ + struct gd32_spidev_s *priv = (struct gd32_spidev_s *)dev; + + uint32_t regval; + + spiinfo("nbits=%d\n", nbits); + + /* Has the number of bits changed? */ + + if (nbits != priv->nbits) + { + /* Yes... Set the number of bits (16 or 8) */ + + regval = spi_getreg(priv, GD32_SPI_CTL0_OFFSET); + regval &= ~ SPI_CTL0_FF16; + + if (nbits == 16) + { + regval |= SPI_CTL0_FF16; + } + + spi_modifyreg(priv, GD32_SPI_CTL0_OFFSET, 0, SPI_CTL0_SPIEN); + spi_putreg(priv, GD32_SPI_CTL0_OFFSET, regval); + spi_modifyreg(priv, GD32_SPI_CTL0_OFFSET, SPI_CTL0_SPIEN, 0); + + /* Save the selection so that subsequent re-configurations will be + * faster. + */ + + priv->nbits = nbits; + } +} + +/**************************************************************************** + * Name: spi_hwfeatures + * + * Description: + * Set hardware-specific feature flags. + * + * Input Parameters: + * dev - Device-specific state data + * features - H/W feature flags + * + * Returned Value: + * Zero (OK) if the selected H/W features are enabled; A negated errno + * value if any H/W feature is not supportable. + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_HWFEATURES +static int spi_hwfeatures(struct spi_dev_s *dev, + spi_hwfeatures_t features) +{ +#if defined(CONFIG_SPI_BITORDER) || defined(CONFIG_SPI_TRIGGER) + struct gd32_spidev_s *priv = (struct gd32_spidev_s *)dev; +#endif + +#ifdef CONFIG_SPI_BITORDER + uint16_t setbits; + uint16_t clrbits; + uint32_t regval; + + spiinfo("features=%08x\n", features); + + regval = spi_getreg(priv, GD32_SPI_CTL0_OFFSET); + regval &= ~ SPI_CTL0_LF; + + /* Transfer data LSB first? */ + + if ((features & HWFEAT_LSBFIRST) != 0) + { + regval |= SPI_CTL0_LF; + } + + spi_modifyreg(priv, GD32_SPI_CTL0_OFFSET, 0, SPI_CTL0_SPIEN); + spi_putreg(priv, GD32_SPI_CTL0_OFFSET, regval); + spi_modifyreg(priv, GD32_SPI_CTL0_OFFSET, SPI_CTL0_SPIEN, 0); + + features &= ~HWFEAT_LSBFIRST; +#endif + + /* Other H/W features are not supported */ + + return (features == 0) ? OK : -ENOSYS; +} +#endif + +/**************************************************************************** + * Name: spi_send_data + * + * Description: + * Exchange one word on SPI + * + * Input Parameters: + * dev - Device-specific state data + * wd - The word to send. the size of the data is determined by the + * number of bits selected for the SPI interface. + * + * Returned Value: + * response + * + ****************************************************************************/ + +static uint32_t spi_send_data(struct gd32_spidev_s *priv, uint16_t wd) +{ + uint32_t regval; + uint32_t ret; + + DEBUGASSERT(priv && priv->spibase); + + spi_writeword(priv, (uint32_t)(wd & 0xffff)); + ret = (uint32_t)spi_readword(priv); + + /* Check and clear any error flags + * (Reading from the STAT clears the error flags) + */ + + regval = spi_getreg(priv, GD32_SPI_STAT_OFFSET); + + if ((regval&SPI_STAT_CRCERR) == SPI_STAT_CRCERR) + { + spi_modifyreg(priv, GD32_SPI_STAT_OFFSET, 0, SPI_STAT_CRCERR); + } + + spiinfo("Sent: %02" PRIx16 " Return: %04" PRIx32 + " Status: %04" PRIx32 "\n", wd, ret, regval); + UNUSED(regval); + + return ret; +} + +/**************************************************************************** + * Name: spi_send + * + * Description: + * Exchange one word on SPI + * + * Input Parameters: + * dev - Device-specific state data + * wd - The word to send. the size of the data is determined by the + * number of bits selected for the SPI interface. + * + * Returned Value: + * response + * + ****************************************************************************/ + +static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd) +{ + struct gd32_spidev_s *priv = (struct gd32_spidev_s *)dev; + + return (uint32_t)spi_send_data(priv, (uint16_t)wd); +} + +/**************************************************************************** + * Name: spi_exchange (no DMA). aka spi_exchange_nodma + * + * Description: + * Exchange a block of data on SPI without using DMA + * + * REVISIT: + * This function could be much more efficient by exploiting (1) RX and TX + * FIFOs and (2) the GD32F4 F3 data packing. + * + * Input Parameters: + * dev - Device-specific state data + * txbuffer - A pointer to the buffer of data to be sent + * rxbuffer - A pointer to a buffer in which to receive data + * nwords - the length of data to be exchanged in units of words. + * The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. If nbits <= 8, the data is + * packed into uint8_t's; if nbits >8, the data is packed into + * uint16_t's + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if !defined(CONFIG_GD32F4_SPI_DMA) || defined(CONFIG_GD32F4_SPI_DMATHRESHOLD) +#if !defined(CONFIG_GD32F4_SPI_DMA) +static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, + void *rxbuffer, size_t nwords) +#else +static void spi_exchange_nodma(struct spi_dev_s *dev, + const void *txbuffer, + void *rxbuffer, size_t nwords) +#endif +{ + struct gd32_spidev_s *priv = (struct gd32_spidev_s *)dev; + DEBUGASSERT(priv && priv->spibase); + + uint8_t *brxptr = (uint8_t *)rxbuffer; + const uint8_t *btxptr = (uint8_t *)txbuffer; + uint16_t *wrxptr = (uint16_t *)rxbuffer; + const uint16_t *wtxptr = (const uint16_t *)txbuffer; + uint8_t byte; + uint16_t word; + + spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords); + + /* 8- or 16-bit mode? */ + + if (priv->nbits > 8) + { + /* 16-bit mode */ + + while (nwords-- > 0) + { + /* Get the next word to write. Is there a source buffer? */ + + if (wtxptr) + { + word = *wtxptr++; + } + else + { + word = 0xffff; + } + + /* Exchange one word */ + + word = (uint16_t)spi_send(dev, (uint32_t)word); + + /* Is there a buffer to receive the return value? */ + + if (wrxptr) + { + *wrxptr++ = word; + } + } + } + else + { + /* 8-bit mode */ + + while (nwords-- > 0) + { + /* Get the next word to write. Is there a source buffer? */ + + if (btxptr) + { + byte = *btxptr++; + } + else + { + byte = 0xff; + } + + /* Exchange one word */ + + byte = (uint8_t)spi_send(dev, (uint32_t)byte); + + /* Is there a buffer to receive the return value? */ + + if (brxptr) + { + *brxptr++ = byte; + } + } + } +} +#endif /* !CONFIG_GD32F4_SPI_DMA || CONFIG_GD32F4_SPI_DMATHRESHOLD */ + +/**************************************************************************** + * Name: spi_exchange (with DMA capability) + * + * Description: + * Exchange a block of data on SPI using DMA + * + * Input Parameters: + * dev - Device-specific state data + * txbuffer - A pointer to the buffer of data to be sent + * rxbuffer - A pointer to a buffer in which to receive data + * nwords - the length of data to be exchanged in units of words. + * The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. If nbits <= 8, the data is + * packed into uint8_t's; if nbits >8, the data is packed into + * uint16_t's + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_GD32F4_SPI_DMA +static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, + void *rxbuffer, size_t nwords) +{ + struct gd32_spidev_s *priv = (struct gd32_spidev_s *)dev; + void *xbuffer = rxbuffer; + size_t nbytes; + int ret; + static uint16_t rxdummy = 0xffff; + static const uint16_t txdummy = 0xffff; + + DEBUGASSERT(priv && priv->spibase); + + /* Convert the number of word to a number of bytes */ + + nbytes = (priv->nbits > 8) ? nwords << 1 : nwords; + + if ((priv->rxdma == NULL) || (priv->txdma == NULL) || + up_interrupt_context() +#ifdef CONFIG_GD32F4_SPI_DMATHRESHOLD + /* If this is a small SPI transfer, then let spi_exchange_nodma() + * work do the. + */ + + || (nbytes <= CONFIG_GD32F4_SPI_DMATHRESHOLD) +#endif + ) + { + /* Invalid DMA channels, or interrupt context, fall + * back to non-DMA method. + */ + + spi_exchange_nodma(dev, txbuffer, rxbuffer, nwords); + return; + } + + { + spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", + txbuffer, rxbuffer, nwords); + + /* Setup DMAs */ + + /* If this bus uses a in driver buffers we will incur 2 copies, + * The copy cost is << less the non DMA transfer time and having + * the buffer in the driver ensures DMA can be used. This is because + * the API does not support passing the buffer extent so the only + * extent is buffer + the transfer size. These can sizes be less than + * the cache line size, and not aligned and typically greater then 4 + * bytes, which is about the break even point for the DMA IO overhead. + */ + + if (txbuffer && priv->txbuf) + { + if (nbytes > priv->buflen) + { + nbytes = priv->buflen; + } + + memcpy(priv->txbuf, txbuffer, nbytes); + txbuffer = priv->txbuf; + rxbuffer = rxbuffer ? priv->rxbuf : rxbuffer; + } + + spi_dmarxsetup(priv, rxbuffer, &rxdummy, nwords); + spi_dmatxsetup(priv, txbuffer, &txdummy, nwords); + +#ifdef CONFIG_SPI_TRIGGER + /* Is deferred triggering in effect? */ + + if (!priv->defertrig) + { + /* No.. Start the DMAs */ + + spi_dmarxstart(priv); + spi_dmatxstart(priv); + } + else + { + /* Yes.. indicated that we are ready to be started */ + + priv->trigarmed = true; + } +#else + /* Start the DMAs */ + + spi_dmarxstart(priv); + spi_dmatxstart(priv); +#endif + + /* Then wait for each to complete */ + + ret = spi_dmarxwait(priv); + if (ret < 0) + { + ret = spi_dmatxwait(priv); + } + + if (rxbuffer != NULL && priv->rxbuf != NULL && ret >= 0) + { + memcpy(xbuffer, priv->rxbuf, nbytes); + } + +#ifdef CONFIG_SPI_TRIGGER + priv->trigarmed = false; +#endif + } +} +#endif /* CONFIG_GD32F4_SPI_DMA */ + +/**************************************************************************** + * Name: spi_trigger + * + * Description: + * Trigger a previously configured DMA transfer. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * OK - Trigger was fired + * ENOTSUP - Trigger not fired due to lack of DMA support + * EIO - Trigger not fired because not previously primed + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_TRIGGER +static int spi_trigger(struct spi_dev_s *dev) +{ +#ifdef CONFIG_GD32F4_SPI_DMA + struct gd32_spidev_s *priv = (struct gd32_spidev_s *)dev; + + if (!priv->trigarmed) + { + return -EIO; + } + + spi_dmarxstart(priv); + spi_dmatxstart(priv); + + return OK; +#else + return -ENOSYS; +#endif +} +#endif + +/**************************************************************************** + * Name: spi_sndblock + * + * Description: + * Send a block of data on SPI + * + * Input Parameters: + * dev - Device-specific state data + * txbuffer - A pointer to the buffer of data to be sent + * nwords - the length of data to send from the buffer in number of + * words. + * The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. If nbits <= 8, the data is + * packed into uint8_t's; if nbits >8, the data is packed into + * uint16_t's + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifndef CONFIG_SPI_EXCHANGE +static void spi_sndblock(struct spi_dev_s *dev, + const void *txbuffer, + size_t nwords) +{ + spiinfo("txbuffer=%p nwords=%d\n", txbuffer, nwords); + return spi_exchange(dev, txbuffer, NULL, nwords); +} +#endif + +/**************************************************************************** + * Name: spi_recvblock + * + * Description: + * Receive a block of data from SPI + * + * Input Parameters: + * dev - Device-specific state data + * rxbuffer - A pointer to the buffer in which to receive data + * nwords - the length of data that can be received in the buffer in + * number of words. The wordsize is determined by the number + * of bits-per-word selected for the SPI interface. If + * nbits <= 8, the data is packed into uint8_t's; if nbits >8, + * the data is packed into uint16_t's + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifndef CONFIG_SPI_EXCHANGE +static void spi_recvblock(struct spi_dev_s *dev, + void *rxbuffer, + size_t nwords) +{ + spiinfo("rxbuffer=%p nwords=%d\n", rxbuffer, nwords); + return spi_exchange(dev, NULL, rxbuffer, nwords); +} +#endif + +/**************************************************************************** + * Name: spi_dmarxwait + * + * Description: + * Wait for DMA to complete. + * + ****************************************************************************/ + +#ifdef CONFIG_GD32F4_SPI_DMA +static int spi_dmarxwait(struct gd32_spidev_s *priv) +{ + int ret; + + /* Take the semaphore (perhaps waiting). If the result is zero, then the + * DMA must not really have completed??? + */ + + do + { + ret = nxsem_wait_uninterruptible(&priv->rxsem); + + /* The only expected error is ECANCELED which would occur if the + * calling thread were canceled. + */ + + DEBUGASSERT(ret == OK || ret == -ECANCELED); + } + while (priv->rxresult == 0 && ret == OK); + + return ret; +} + +/**************************************************************************** + * Name: spi_dmatxwait + * + * Description: + * Wait for DMA to complete. + * + ****************************************************************************/ + +static int spi_dmatxwait(struct gd32_spidev_s *priv) +{ + int ret; + + /* Take the semaphore (perhaps waiting). If the result is zero, then the + * DMA must not really have completed??? + */ + + do + { + ret = nxsem_wait_uninterruptible(&priv->txsem); + + /* The only expected error is ECANCELED which would occur if the + * calling thread were canceled. + */ + + DEBUGASSERT(ret == OK || ret == -ECANCELED); + } + while (priv->txresult == 0 && ret == OK); + + return ret; +} + +/**************************************************************************** + * Name: spi_dmarxcallback + * + * Description: + * Called when the RX DMA completes + * + ****************************************************************************/ + +static void spi_dmarxcallback(DMA_HANDLE handle, uint16_t isr, void *arg) +{ + struct gd32_spidev_s *priv = (struct gd32_spidev_s *)arg; + + /* Wake-up the SPI driver */ + + priv->rxresult = isr | 0x0080; /* OR'ed with 0x0080 to assure non-zero */ + + nxsem_post(&priv->txsem); +} + +/**************************************************************************** + * Name: spi_dmatxcallback + * + * Description: + * Called when the RX DMA completes + * + ****************************************************************************/ + +static void spi_dmatxcallback(DMA_HANDLE handle, uint16_t isr, void *arg) +{ + struct gd32_spidev_s *priv = (struct gd32_spidev_s *)arg; + + /* Wake-up the SPI driver */ + + priv->txresult = isr | 0x0080; /* OR'ed with 0x80 to assure non-zero */ + + nxsem_post(&priv->txsem); +} + +/**************************************************************************** + * Name: spi_dmarxsetup + * + * Description: + * Setup to perform RX DMA + * + ****************************************************************************/ + +static void spi_dmarxsetup(struct gd32_spidev_s *priv, + void *rxbuffer, + void *rxdummy, size_t nwords) +{ + uint32_t regval; + dma_single_data_parameter_struct dma_init_struct; + + /* Enable SPI RX DMA */ + + regval = spi_getreg(priv, GD32_SPI_CTL1_OFFSET); + regval |= SPI_CTL1_DMAREN; + spi_putreg(priv, GD32_SPI_CTL1_OFFSET, regval); + + /* 8- or 16-bit mode? */ + + if (priv->nbits > 8) + { + /* 16-bit mode -- is there a buffer to receive data in? */ + + if (rxbuffer) + { + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + } + else + { + rxbuffer = rxdummy; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_DISABLE; + } + + dma_init_struct.periph_memory_width = DMA_WIDTH_16BITS_SELECT; + } + else + { + /* 8-bit mode -- is there a buffer to receive data in? */ + + if (rxbuffer) + { + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + } + else + { + rxbuffer = rxdummy; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_DISABLE; + } + + dma_init_struct.periph_memory_width = DMA_WIDTH_8BITS_SELECT; + } + + dma_init_struct.direction = DMA_PERIPH_TO_MEMORY; + dma_init_struct.memory0_addr = (uint32_t)rxbuffer; + dma_init_struct.number = nwords; + dma_init_struct.periph_addr = GD32_SPI_DATA(priv->spibase); + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.priority = SPI_DMA_PRIO; + + /* Configure the RX DMA */ + + gd32_dma_setup(priv->rxdma, &dma_init_struct, 1); +} + +/**************************************************************************** + * Name: spi_dmatxsetup + * + * Description: + * Setup to perform TX DMA + * + ****************************************************************************/ + +static void spi_dmatxsetup(struct gd32_spidev_s *priv, + const void *txbuffer, + const void *txdummy, size_t nwords) +{ + uint32_t regval; + dma_single_data_parameter_struct dma_init_struct; + + /* Enable SPI TX DMA */ + + regval = spi_getreg(priv, GD32_SPI_CTL1_OFFSET); + regval |= SPI_CTL1_DMATEN; + spi_putreg(priv, GD32_SPI_CTL1_OFFSET, regval); + + /* 8- or 16-bit mode? */ + + if (priv->nbits > 8) + { + /* 16-bit mode -- is there a buffer to transfer data from? */ + + if (txbuffer) + { + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + } + else + { + txbuffer = txdummy; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_DISABLE; + } + + dma_init_struct.periph_memory_width = DMA_WIDTH_16BITS_SELECT; + } + else + { + /* 8-bit mode -- is there a buffer to transfer data from? */ + + if (txbuffer) + { + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + } + else + { + txbuffer = txdummy; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_DISABLE; + } + + dma_init_struct.periph_memory_width = DMA_WIDTH_8BITS_SELECT; + } + + dma_init_struct.direction = DMA_MEMORY_TO_PERIPH; + dma_init_struct.memory0_addr = (uint32_t)txbuffer; + dma_init_struct.number = nwords; + dma_init_struct.periph_addr = GD32_SPI_DATA(priv->spibase); + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.priority = SPI_DMA_PRIO; + + /* Setup the TX DMA */ + + gd32_dma_setup(priv->txdma, &dma_init_struct, 1); +} + +/**************************************************************************** + * Name: spi_dmarxstart + * + * Description: + * Start RX DMA + * + ****************************************************************************/ + +static inline void spi_dmarxstart(struct gd32_spidev_s *priv) +{ + priv->rxresult = 0; + gd32_dma_start(priv->rxdma, spi_dmarxcallback, priv, SPI_DMA_INTEN); +} + +/**************************************************************************** + * Name: spi_dmatxstart + * + * Description: + * Start TX DMA + * + ****************************************************************************/ + +static inline void spi_dmatxstart(struct gd32_spidev_s *priv) +{ + priv->txresult = 0; + gd32_dma_start(priv->txdma, spi_dmatxcallback, priv, SPI_DMA_INTEN); +} +#endif + +/**************************************************************************** + * Name: spi_bus_initialize + * + * Description: + * Initialize the selected SPI bus in its default state (Master, 8-bit, + * mode 0, etc.) + * + * Input Parameters: + * priv - private SPI device structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void spi_bus_initialize(struct gd32_spidev_s *priv) +{ + uint32_t regval; + + /* Configure CTL0. Default configuration: + * Mode 0: CKPH=0 and CKPL=0 + * Master: SPI_MASTER + * 8-bit: FF16=0 + * MSB transmitted first: LF=0 + * NSS software mode: SWNSSEN=1 + * RECV and TRANS at duplex: SPI_TRANSMODE_FULLDUPLEX + * + */ + + regval = spi_getreg(priv, GD32_SPI_CTL0_OFFSET); + regval &= SPI_INIT_MASK; + regval |= (SPI_MASTER | SPI_CTL0_SWNSSEN); + spi_putreg(priv, GD32_SPI_CTL0_OFFSET, regval); + + priv->frequency = 0; + priv->nbits = 8; + priv->mode = SPIDEV_MODE0; + + /* Select a default frequency of approx. 400KHz */ + + spi_setfrequency((struct spi_dev_s *)priv, 400000); + + /* Initialize the SPI semaphore that enforces mutually exclusive access */ + + nxsem_init(&priv->exclsem, 0, 1); + +#ifdef CONFIG_GD32F4_SPI_DMA + /* Initialize the SPI semaphores that is used to wait for DMA completion. + * This semaphore is used for signaling and, hence, should not have + * priority inheritance enabled. + */ + + if (priv->rxch && priv->txch) + { + if (priv->txdma == NULL && priv->rxdma == NULL) + { + nxsem_init(&priv->rxsem, 0, 0); + nxsem_init(&priv->txsem, 0, 0); + + nxsem_set_protocol(&priv->rxsem, SEM_PRIO_NONE); + nxsem_set_protocol(&priv->txsem, SEM_PRIO_NONE); + + /* Get DMA channels */ + + priv->rxdma = gd32_dma_channel_alloc(priv->rxch); + priv->txdma = gd32_dma_channel_alloc(priv->txch); + DEBUGASSERT(priv->rxdma && priv->txdma); + } + } + else + { + priv->rxdma = NULL; + priv->txdma = NULL; + } +#endif + + /* Enable SPI */ + + spi_modifyreg(priv, GD32_SPI_CTL0_OFFSET, SPI_CTL0_SPIEN, 0); +} + +/**************************************************************************** + * Name: gd32_spi_gpio_config + * + * Description: + * Configure GPIO pins for SPI. + * + ****************************************************************************/ + +static void gd32_spi_gpio_config(uint32_t spibase) +{ + /* Determine which SPI to configure */ + + switch (spibase) + { + default: + break; +#ifdef CONFIG_GD32F4_SPI0 + case GD32_SPI0: + + /* Configure GPIO pins for SPI0: SCK, MISO, and MOSI */ + + gd32_gpio_config(GPIO_SPI0_SCK_PIN); + gd32_gpio_config(GPIO_SPI0_MISO_PIN); + gd32_gpio_config(GPIO_SPI0_MOSI_PIN); + break; +#endif +#ifdef CONFIG_GD32F4_SPI1 + case GD32_SPI1: + + /* Configure GPIO pins for SPI1: SCK, MISO, and MOSI */ + + gd32_gpio_config(GPIO_SPI1_SCK_PIN); + gd32_gpio_config(GPIO_SPI1_MISO_PIN); + gd32_gpio_config(GPIO_SPI1_MOSI_PIN); + break; +#endif +#ifdef CONFIG_GD32F4_SPI2 + case GD32_SPI2: + + /* Configure GPIO pins for SPI2: SCK, MISO, and MOSI */ + + gd32_gpio_config(GPIO_SPI2_SCK_PIN); + gd32_gpio_config(GPIO_SPI2_MISO_PIN); + gd32_gpio_config(GPIO_SPI2_MOSI_PIN); + break; +#endif +#ifdef CONFIG_GD32F4_SPI3 + case GD32_SPI3: + + /* Configure GPIO pins for SPI3: SCK, MISO, and MOSI */ + + gd32_gpio_config(GPIO_SPI3_SCK_PIN); + gd32_gpio_config(GPIO_SPI3_MISO_PIN); + gd32_gpio_config(GPIO_SPI3_MOSI_PIN); + break; +#endif +#ifdef CONFIG_GD32F4_SPI4 + case GD32_SPI4: + + /* Configure GPIO pins for SPI4: SCK, MISO, and MOSI */ + + gd32_gpio_config(GPIO_SPI4_SCK_PIN); + gd32_gpio_config(GPIO_SPI4_MISO_PIN); + gd32_gpio_config(GPIO_SPI4_MOSI_PIN); + break; +#endif +#ifdef CONFIG_GD32F4_SPI5 + case GD32_SPI5: + + /* Configure GPIO pins for SPI5: SCK, MISO, and MOSI */ + + gd32_gpio_config(GPIO_SPI5_SCK_PIN); + gd32_gpio_config(GPIO_SPI5_MISO_PIN); + gd32_gpio_config(GPIO_SPI5_MOSI_PIN); + gd32_gpio_config(GPIO_SPI5_IO2_PIN); + gd32_gpio_config(GPIO_SPI5_IO3_PIN); + break; +#endif + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_spibus_initialize + * + * Description: + * Initialize the selected SPI port + * + * Input Parameters: + * Port number (for hardware that has multiple SPI interfaces) + * + * Returned Value: + * Valid SPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct spi_dev_s *gd32_spibus_initialize(int port) +{ + struct gd32_spidev_s *priv = NULL; + + /* Configure multiplexed pins as connected on the board. Chip select pins + * must be configured by board-specific logic. Most SPI pins multiple, + * alternative pin selection. Definitions in the board.h file must be\ + * provided to resolve the board-specific pin configuration like: + * + * #define PIN_SPI0_SCK PIN_SPI0_SCK_1 + */ + + irqstate_t flags = enter_critical_section(); + +#ifdef CONFIG_GD32F4_SPI0 + if (port == 0) + { + /* Select SPI0 */ + + priv = &g_spi0dev; + } + else +#endif +#ifdef CONFIG_GD32F4_SPI1 + if (port == 1) + { + /* Select SPI1 */ + + priv = &g_spi1dev; + } + else +#endif +#ifdef CONFIG_GD32F4_SPI2 + if (port == 2) + { + /* Select SPI2 */ + } + else +#endif +#ifdef CONFIG_GD32F4_SPI3 + if (port == 3) + { + /* Select SPI3 */ + + priv = &g_spi3dev; + } + else +#endif +#ifdef CONFIG_GD32F4_SPI4 + if (port == 4) + { + /* Select SPI4 */ + + priv = &g_spi4dev; + } + else +#endif +#ifdef CONFIG_GD32F4_SPI5 + if (port == 5) + { + /* Select SPI5 */ + + priv = &g_spi5dev; + } + else +#endif + { + spierr("ERROR: Unsupported SPI port: %d\n", port); + } + + /* Check if the port is seclected and has not been configured */ + + if ((priv != NULL) && (!priv->initialized)) + { + /* Configure GPIO pins for SPI */ + + gd32_spi_gpio_config(priv->spibase); + + /* Enable clock for SPI */ + + gd32_spi_clock_enable(priv->spibase); + + /* Set up default configuration */ + + spi_bus_initialize(priv); + + priv->initialized = true; + } + + leave_critical_section(flags); + + return (struct spi_dev_s *)priv; +} + +/**************************************************************************** + * Name: gd32_spibus_deinitialize + * + * Description: + * Deinitialize the selected SPI port + * + * Input Parameters: + * Port number (for hardware that has multiple SPI interfaces) + * + ****************************************************************************/ + +void gd32_spibus_deinitialize(int port) +{ + struct gd32_spidev_s *priv = NULL; + +#ifdef CONFIG_GD32F4_SPI0 + if (port == 0) + { + /* Select SPI0 */ + + priv = &g_spi0dev; + } + else +#endif +#ifdef CONFIG_GD32F4_SPI1 + if (port == 1) + { + /* Select SPI1 */ + + priv = &g_spi1dev; + } + else +#endif +#ifdef CONFIG_GD32F4_SPI2 + if (port == 2) + { + /* Select SPI2 */ + + priv = &g_spi2dev; + } + else +#endif +#ifdef CONFIG_GD32F4_SPI3 + if (port == 3) + { + /* Select SPI3 */ + + priv = &g_spi3dev; + } + else +#endif +#ifdef CONFIG_GD32F4_SPI4 + if (port == 4) + { + /* Select SPI4 */ + + priv = &g_spi4dev; + } + else +#endif +#ifdef CONFIG_GD32F4_SPI5 + if (port == 5) + { + /* Select SPI5 */ + + priv = &g_spi5dev; + } + else +#endif + { + spierr("ERROR: Unsupported SPI port: %d\n", port); + } + + /* Check if the port is seclected and has been configured */ + + if ((priv != NULL) && (priv->initialized)) + { + gd32_spi_clock_disable(priv->spibase); + + gd32_spi_reset(priv->spibase); + + priv->initialized = false; + } +} + +#endif /* CONFIG_GD32F4_SPI0 || CONFIG_GD32F4_SPI1 || CONFIG_GD32F4_SPI2 || + * CONFIG_GD32F4_SPI3 || CONFIG_GD32F4_SPI4 || CONFIG_GD32F4_SPI5 + */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_spi.h b/arch/arm/src/gd32f4/gd32f4xx_spi.h new file mode 100644 index 0000000000..9ec71f38fa --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_spi.h @@ -0,0 +1,233 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_spi.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_SPI_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_SPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "chip.h" +#include "hardware/gd32f4xx_spi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +struct spi_dev_s; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_spibus_initialize + * + * Description: + * Initialize the selected SPI bus + * + * Input Parameters: + * bus number (for hardware that has multiple SPI interfaces) + * + * Returned Value: + * Valid SPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct spi_dev_s *gd32_spibus_initialize(int bus); + +/**************************************************************************** + * Name: gd32_spibus_deinitialize + * + * Description: + * Deinitialize the selected SPI port + * + * Input Parameters: + * Port number (for hardware that has multiple SPI interfaces) + * + ****************************************************************************/ + +void gd32_spibus_deinitialize(int port); + +/**************************************************************************** + * Name: gd32_spibus_deinitialize + * + * Description: + * Deinitialize the selected SPI port + * + * Input Parameters: + * Port number (for hardware that has multiple SPI interfaces) + * + ****************************************************************************/ + +void gd32_spibus_deinitialize(int port); + +/**************************************************************************** + * Name: gd32_spi[n] select and gd32_spi[n] status + * + * Description: + * The external functions, gd32_spi[n]select, gd32_spi[n]status, + * and gd32_spi[n]cmddata must be provided by board-specific logic. + * These are implementations of the select, status, and cmddata methods of + * the SPI interface defined by struct spi_ops_s (see + * include/nuttx/spi/spi.h). All other methods (including + * gd32_spibus_initialize()) are provided by common GD32F4 logic. + * To use this common SPI logic on your board: + * + * 1. Provide logic in gd32_boardinitialize() to configure SPI chip + * select pins. + * 2. Provide gd32_spi[n]select() and gd32_spi[n] status() functions + * in your board-specific logic. These functions will perform chip + * selection and status operations using GPIOs in the way your board + * is configured. + * 3. If CONFIG_SPI_CMDDATA is defined in the NuttX configuration, then + * provide gd32_spi[n]cmddata() functions in your board-specific + * logic. These functions will perform cmd/data selection operations + * using GPIOs in the way your board is configured. + * 4. Add a calls to gd32_spibus_initialize() in your low level + * application initialization logic + * 5. The handle returned by gd32_spibus_initialize() may then be used to + * bind the SPI driver to higher level logic (e.g., calling + * mmcsd_spislotinitialize(), for example, will bind the SPI driver to + * the SPI MMC/SD driver). + * + ****************************************************************************/ + +#ifdef CONFIG_GD32F4_SPI0 +void gd32_spi0select(struct spi_dev_s *dev, uint32_t devid, + bool selected); +uint8_t gd32_spi0status(struct spi_dev_s *dev, uint32_t devid); +int gd32_spi0cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +#ifdef CONFIG_GD32F4_SPI1 +void gd32_spi1select(struct spi_dev_s *dev, uint32_t devid, + bool selected); +uint8_t gd32_spi1status(struct spi_dev_s *dev, uint32_t devid); +int gd32_spi1cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +#ifdef CONFIG_GD32F4_SPI2 +void gd32_spi2select(struct spi_dev_s *dev, uint32_t devid, + bool selected); +uint8_t gd32_spi2status(struct spi_dev_s *dev, uint32_t devid); +int gd32_spi2cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +#ifdef CONFIG_GD32F4_SPI3 +void gd32_spi3select(struct spi_dev_s *dev, uint32_t devid, + bool selected); +uint8_t gd32_spi3status(struct spi_dev_s *dev, uint32_t devid); +int gd32_spi3cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +#ifdef CONFIG_GD32F4_SPI4 +void gd32_spi4select(struct spi_dev_s *dev, uint32_t devid, + bool selected); +uint8_t gd32_spi4status(struct spi_dev_s *dev, uint32_t devid); +int gd32_spi4cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +#ifdef CONFIG_GD32F4_SPI5 +void gd32_spi5select(struct spi_dev_s *dev, uint32_t devid, + bool selected); +uint8_t gd32_spi5status(struct spi_dev_s *dev, uint32_t devid); +int gd32_spi5cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +/**************************************************************************** + * Name: gd32_spi[n]register + * + * Description: + * If the board supports a card detect callback to inform the SPI-based + * MMC/SD driver when an SD card is inserted or removed, then + * CONFIG_SPI_CALLBACK should be defined and the following function(s) + * must be implemented. These functions implements the registercallback + * method of the SPI interface (see include/nuttx/spi/spi.h for details) + * + * Input Parameters: + * dev - Device-specific state data + * callback - The function to call on the media change + * arg - A caller provided value to return with the callback + * + * Returned Value: + * 0 on success; negated errno on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_CALLBACK +#ifdef CONFIG_GD32F4_SPI0 +int gd32_spi0register(struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +#endif + +#ifdef CONFIG_GD32F4_SPI1 +int gd32_spi1register(struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +#endif + +#ifdef CONFIG_GD32F4_SPI2 +int gd32_spi2register(struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +#endif + +#ifdef CONFIG_GD32F4_SPI3 +int gd32_spi3register(struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +#endif + +#ifdef CONFIG_GD32F4_SPI4 +int gd32_spi4register(struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +#endif + +#ifdef CONFIG_GD32F4_SPI5 +int gd32_spi5register(struct spi_dev_s *dev, spi_mediachange_t callback, + void *arg); +#endif +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_SPI_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_start.c b/arch/arm/src/gd32f4/gd32f4xx_start.c new file mode 100644 index 0000000000..644e77f373 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_start.c @@ -0,0 +1,284 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_start.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "arm_internal.h" +#include "nvic.h" +#include "mpu.h" + +#include "gd32f4xx.h" +#include "gd32f4xx_gpio.h" +#include "gd32f4xx_start.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* .data is positioned first in the primary RAM followed immediately by .bss. + * The IDLE thread stack lies just after .bss and has size give by + * CONFIG_IDLETHREAD_STACKSIZE; The heap then begins just after the IDLE. + * ARM EABI requires 64 bit stack alignment. + */ + +#define HEAP_BASE ((uintptr_t)&_ebss + CONFIG_IDLETHREAD_STACKSIZE) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* g_idle_topstack: _sbss is the start of the BSS region as defined by the + * linker script. _ebss lies at the end of the BSS region. The idle task + * stack starts at the end of BSS and is of size CONFIG_IDLETHREAD_STACKSIZE. + * The IDLE thread is the thread that the system boots on and, eventually, + * becomes the IDLE, do nothing task that runs only when there is nothing + * else to run. The heap continues from there until the end of memory. + * g_idle_topstack is a read-only variable the provides this computed + * address. + */ + +const uintptr_t g_idle_topstack = HEAP_BASE; + +/**************************************************************************** + * Private Function prototypes + ****************************************************************************/ + +#ifdef CONFIG_ARCH_FPU +static inline void gd32_fpuconfig(void); +#endif + +/**************************************************************************** + * Public Function prototypes + ****************************************************************************/ +#ifdef CONFIG_ARMV7M_STACKCHECK +/* we need to get r10 set before we can allow instrumentation calls */ + +void __start(void) noinstrument_function; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: showprogress + * + * Description: + * Print a character on the UART to show boot status. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +# define showprogress(c) arm_lowputc(c) +#else +# define showprogress(c) +#endif + +/**************************************************************************** + * Name: gd32_fpuconfig + * + * Description: + * Configure the FPU. Relative bit settings: + * + * CPACR: Enables access to CP10 and CP11 + * CONTROL.FPCA: Determines whether the FP extension is active in the + * current context: + * FPCCR.ASPEN: Enables automatic FP state preservation, then the + * processor sets this bit to 1 on successful completion of any FP + * instruction. + * FPCCR.LSPEN: Enables lazy context save of FP state. When this is + * done, the processor reserves space on the stack for the FP state, + * but does not save that state information to the stack. + * + * Software must not change the value of the ASPEN bit or LSPEN bit either: + * - the CPACR permits access to CP10 and CP11, that give access to the FP + * extension, or + * - the CONTROL.FPCA bit is set to 1 + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_FPU +#ifndef CONFIG_ARMV7M_LAZYFPU + +static inline void gd32_fpuconfig(void) +{ + uint32_t regval; + + /* Set CONTROL.FPCA so that we always get the extended context frame + * with the volatile FP registers stacked above the basic context. + */ + + regval = getcontrol(); + regval |= CONTROL_FPCA; + setcontrol(regval); + + /* Ensure that FPCCR.LSPEN is disabled, so that we don't have to contend + * with the lazy FP context save behaviour. Clear FPCCR.ASPEN since we + * are going to turn on CONTROL.FPCA for all contexts. + */ + + regval = getreg32(NVIC_FPCCR); + regval &= ~(NVIC_FPCCR_ASPEN | NVIC_FPCCR_LSPEN); + putreg32(regval, NVIC_FPCCR); + + /* Enable full access to CP10 and CP11 */ + + regval = getreg32(NVIC_CPACR); + regval |= NVIC_CPACR_CP_FULL(10) | NVIC_CPACR_CP_FULL(11); + putreg32(regval, NVIC_CPACR); +} + +#else + +static inline void gd32_fpuconfig(void) +{ + uint32_t regval; + + /* Clear CONTROL.FPCA so that we do not get the extended context frame + * with the volatile FP registers stacked in the saved context. + */ + + regval = getcontrol(); + regval &= ~CONTROL_FPCA; + setcontrol(regval); + + /* Ensure that FPCCR.LSPEN is disabled, so that we don't have to contend + * with the lazy FP context save behaviour. Clear FPCCR.ASPEN since we + * are going to keep CONTROL.FPCA off for all contexts. + */ + + regval = getreg32(NVIC_FPCCR); + regval &= ~(NVIC_FPCCR_ASPEN | NVIC_FPCCR_LSPEN); + putreg32(regval, NVIC_FPCCR); + + /* Enable full access to CP10 and CP11 */ + + regval = getreg32(NVIC_CPACR); + regval |= NVIC_CPACR_CP_FULL(10) | NVIC_CPACR_CP_FULL(11); + putreg32(regval, NVIC_CPACR); +} + +#endif + +#else +# define gd32_fpuconfig() +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _start + * + * Description: + * This is the reset entry point. + * + ****************************************************************************/ + +void __start(void) +{ + const uint32_t *src; + uint32_t *dest; + +#ifdef CONFIG_ARMV7M_STACKCHECK + /* Set the stack limit before we attempt to call any functions */ + + __asm__ volatile("sub r10, sp, %0" : : + "r"(CONFIG_IDLETHREAD_STACKSIZE - 64) :); +#endif + + /* Clear .bss. We'll do this inline (vs. calling memset) just to be + * certain that there are no issues with the state of global variables. + */ + + for (dest = &_sbss; dest < &_ebss; ) + { + *dest++ = 0; + } + + /* Move the initialized data section from his temporary holding spot in + * FLASH into the correct place in SRAM. The correct place in SRAM is + * give by _sdata and _edata. The temporary location is in FLASH at the + * end of all of the other read-only data (.text, .rodata) at _eronly. + */ + + for (src = &_eronly, dest = &_sdata; dest < &_edata; ) + { + *dest++ = *src++; + } + + /* Configure the UART so that we can get debug output as soon as possible */ + + gd32_clockconfig(); + gd32_fpuconfig(); + gd32_lowsetup(); + showprogress('A'); + +#ifdef CONFIG_ARMV7M_ITMSYSLOG + /* Perform ARMv7-M ITM SYSLOG initialization */ + + itm_syslog_initialize(); +#endif + + /* Perform early serial initialization */ + +#ifdef USE_EARLYSERIALINIT + arm_earlyserialinit(); +#endif + showprogress('B'); + + /* For the case of the separate user-/kernel-space build, perform whatever + * platform specific initialization of the user memory is required. + * Normally this just means initializing the user space .data and .bss + * segments. + */ + +#ifdef CONFIG_BUILD_PROTECTED + gd32_userspace(); + showprogress('C'); +#endif + + /* Initialize onboard resources */ + + gd32_boardinitialize(); + showprogress('D'); + + /* Then start NuttX */ + + showprogress('\r'); + showprogress('\n'); + + nx_start(); + + /* Shouldn't get here */ + + for (; ; ); +} diff --git a/arch/arm/src/gd32f4/gd32f4xx_start.h b/arch/arm/src/gd32f4/gd32f4xx_start.h new file mode 100644 index 0000000000..3dbd0d1dc6 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_start.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_start.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_START_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_START_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_boardinitialize + * + * Description: + * All GD32 architectures must provide the following entry point. This + * entry point is called early in the initialization -- after clocking + * and memory have been configured but before caches have been enabled + * and before any devices have been initialized. + * + ****************************************************************************/ + +void gd32_boardinitialize(void); + +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_START_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_syscfg.c b/arch/arm/src/gd32f4/gd32f4xx_syscfg.c new file mode 100644 index 0000000000..84f32ddf2f --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_syscfg.c @@ -0,0 +1,248 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_syscfg.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include + +#include +#include +#include +#include +#include + +#include + +#include "arm_internal.h" + +#include "chip.h" +#include "gd32f4xx_syscfg.h" +#include "gd32f4xx_rcu.h" + +#ifdef CONFIG_GD32F4_SYSCFG + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_syscfg_bootmode_config + * + * Description: + * This function configure the boot mode. + * + ****************************************************************************/ + +void gd32_syscfg_bootmode_config(uint8_t syscfg_bootmode) +{ + uint32_t regval; + + regval = getreg32(GD32_SYSCFG_CFG0); + regval &= ~ SYSCFG_CFG0_BOOT_MODE_MASK; + regval |= (uint32_t)syscfg_bootmode; + putreg32(regval, GD32_SYSCFG_CFG0); +} + +/**************************************************************************** + * Name: gd32_syscfg_fmc_swap_config + * + * Description: + * This function configure FMC memory mapping swap. + * + ****************************************************************************/ + +void gd32_syscfg_fmc_swap_config(uint32_t syscfg_fmc_swap) +{ + uint32_t regval; + regval = getreg32(GD32_SYSCFG_CFG0); + regval &= ~SYSCFG_CFG0_FMC_SWP_MASK; + regval |= syscfg_fmc_swap; + putreg32(regval, GD32_SYSCFG_CFG0); +} + +/**************************************************************************** + * Name: gd32_syscfg_exmc_swap_config + * + * Description: + * This function configure EXMC memory mapping swap. + * + ****************************************************************************/ + +void gd32_syscfg_exmc_swap_config(uint32_t syscfg_exmc_swap) +{ + uint32_t regval; + + regval = getreg32(GD32_SYSCFG_CFG0); + regval &= ~SYSCFG_CFG0_EXMC_SWP_MASK; + regval |= syscfg_exmc_swap; + putreg32(regval, GD32_SYSCFG_CFG0); +} + +/**************************************************************************** + * Name: gd32_syscfg_exti_line_config + * + * Description: + * This function configure the GPIO pin as EXTI Line. + * + ****************************************************************************/ + +void gd32_syscfg_exti_line_config(uint8_t exti_port, uint8_t exti_pin) +{ + uint32_t regval; + uint32_t regaddr; + + switch (exti_pin / SYSCFG_EXTI_SS_JSTEP) + { + /* EXTI source line(0..3) */ + + case SYSCFG_EXTISS0: + regaddr = GD32_SYSCFG_EXTISS0; + break; + + /* EXTI source line(4..7) */ + + case SYSCFG_EXTISS1: + regaddr = GD32_SYSCFG_EXTISS1; + break; + + /* EXTI source line(8..11) */ + + case SYSCFG_EXTISS2: + regaddr = GD32_SYSCFG_EXTISS2; + break; + + /* EXTI source line(12..15) */ + + case SYSCFG_EXTISS3: + regaddr = GD32_SYSCFG_EXTISS3; + break; + default: + break; + } + + regval = getreg32(regaddr); + regval &= ~(SYSCFG_EXTI_SS_MASK << (SYSCFG_EXTI_SS_MSTEP(exti_pin))); + regval |= ((exti_port) << (SYSCFG_EXTI_SS_MSTEP(exti_pin))); + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Name: gd32_syscfg_enet_phy_interface_config + * + * Description: + * This function configure the PHY interface for the ethernet MAC. + * + ****************************************************************************/ + +void +gd32_syscfg_enet_phy_interface_config(uint32_t syscfg_enet_phy_interface) +{ + uint32_t regval; + + regval = getreg32(GD32_SYSCFG_CFG1); + regval &= ~SYSCFG_CFG1_ENET_PHY_SEL_MASK; + regval |= syscfg_enet_phy_interface; + putreg32(regval, GD32_SYSCFG_CFG1); +} + +/**************************************************************************** + * Name: gd32_syscfg_compensation_config + * + * Description: + * This function configure the I/O compensation cell. + * + ****************************************************************************/ + +void gd32_syscfg_compensation_config(uint32_t syscfg_compensation) +{ + uint32_t regval; + + regval = getreg32(GD32_SYSCFG_CPSCTL); + regval &= ~SYSCFG_CPSCTL_CPS_EN_MASK; + regval |= syscfg_compensation; + putreg32(regval, GD32_SYSCFG_CPSCTL); +} + +/**************************************************************************** + * Name: gd32_syscfg_flag_get + * + * Description: + * This function checks whether the I/O compensation cell ready flag + * is set or not. + * + ****************************************************************************/ + +bool gd32_syscfg_flag_get(void) +{ + bool regval; + + regval = getreg32(GD32_SYSCFG_CPSCTL); + return (bool)(regval & SYSCFG_CPSCTL_CPS_RDY_MASK); +} + +/**************************************************************************** + * Name: gd32_syscfg_clock_enable + * + * Description: + * Enable SYSCFG clock + ****************************************************************************/ + +void gd32_syscfg_clock_enable(void) +{ + uint32_t rcu_en; + uint32_t regaddr; + + rcu_en = RCU_APB2EN_SYSCFGEN; + + regaddr = GD32_RCU_APB2EN; + + /* Check clock if alreay enable. */ + + if (rcu_en != (rcu_en & getreg32(regaddr))) + { + /* Enable/disable APB2 clock for SYSCFG */ + + modifyreg32(regaddr, 0, rcu_en); + } +} + +/**************************************************************************** + * Name: gd32_syscfg_clock_disable + * + * Description: + * Dinable SYSCFG clock + ****************************************************************************/ + +void gd32_syscfg_clock_disable(void) +{ + uint32_t rcu_en; + uint32_t regaddr; + + rcu_en = RCU_APB2EN_SYSCFGEN; + + regaddr = GD32_RCU_APB2EN; + + /* Disable APB2 clock for SYSCFG */ + + modifyreg32(regaddr, rcu_en, 0); +} + +#endif /* CONFIG_GD32F4_SYSCFG */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_syscfg.h b/arch/arm/src/gd32f4/gd32f4xx_syscfg.h new file mode 100644 index 0000000000..c8d36b98b8 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_syscfg.h @@ -0,0 +1,131 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_syscfg.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_GD32F4XX_SYSCFG_H +#define __ARCH_ARM_SRC_GD32F4_GD32F4XX_SYSCFG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip.h" + +#if defined(CONFIG_GD32F4_GD32F4XX) +# include "hardware/gd32f4xx_syscfg.h" +#else +# error "Unknown GD32 Chip" +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_syscfg_bootmode_config + * + * Description: + * This function configure the boot mode. + * + ****************************************************************************/ + +void gd32_syscfg_bootmode_config(uint8_t syscfg_bootmode); + +/**************************************************************************** + * Name: gd32_syscfg_fmc_swap_config + * + * Description: + * This function configure FMC memory mapping swap. + * + ****************************************************************************/ + +void gd32_syscfg_fmc_swap_config(uint32_t syscfg_fmc_swap); + +/**************************************************************************** + * Name: gd32_syscfg_exmc_swap_config + * + * Description: + * This function configure EXMC memory mapping swap. + * + ****************************************************************************/ + +void gd32_syscfg_exmc_swap_config(uint32_t syscfg_exmc_swap); + +/**************************************************************************** + * Name: gd32_syscfg_exti_line_config + * + * Description: + * This function configure the GPIO pin as EXTI Line. + * + ****************************************************************************/ + +void gd32_syscfg_exti_line_config(uint8_t exti_port, uint8_t exti_pin); + +/**************************************************************************** + * Name: gd32_syscfg_enet_phy_interface_config + * + * Description: + * This function configure the PHY interface for the ethernet MAC. + * + ****************************************************************************/ + +void +gd32_syscfg_enet_phy_interface_config(uint32_t syscfg_enet_phy_interface); + +/**************************************************************************** + * Name: gd32_syscfg_compensation_config + * + * Description: + * This function configure the I/O compensation cell. + * + ****************************************************************************/ + +void gd32_syscfg_compensation_config(uint32_t syscfg_compensation); + +/**************************************************************************** + * Name: gd32_syscfg_flag_get + * + * Description: + * This function checks whether the I/O compensation cell ready flag + * is set or not. + * + ****************************************************************************/ + +bool gd32_syscfg_flag_get(void); + +/**************************************************************************** + * Name: gd32_syscfg_clock_enable + * + * Description: + * Enable SYSCFG clock + ****************************************************************************/ + +void gd32_syscfg_clock_enable(void); + +/**************************************************************************** + * Name: gd32_syscfg_clock_disable + * + * Description: + * Dinable SYSCFG clock + ****************************************************************************/ + +void gd32_syscfg_clock_disable(void); + +#endif /* __ARCH_ARM_SRC_GD32F4_GD32F4XX_SYSCFG_H */ diff --git a/arch/arm/src/gd32f4/gd32f4xx_timerisr.c b/arch/arm/src/gd32f4/gd32f4xx_timerisr.c new file mode 100644 index 0000000000..bb5c9695eb --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_timerisr.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_timerisr.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "nvic.h" +#include "clock/clock.h" +#include "arm_internal.h" + +#include "chip.h" +#include "gd32f4xx.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The desired timer interrupt frequency is provided by the definition + * CLK_TCK (see include/time.h). CLK_TCK defines the desired number of + * system clock ticks per second. That value is a user configurable setting + * that defaults to 100 (100 ticks per second = 10 MS interval). + * + * The RCU feeds the Cortex System Timer (SysTick) with the AHB clock (HCLK) + * divided by 8. The SysTick can work either with this clock or with the + * Cortex clock (HCLK), configurable in the SysTick Control and Status + * register. + */ + +#define SYSTICK_RELOAD ((GD32_SYSCLK_FREQUENCY / CLK_TCK) - 1) + +/* The size of the reload field is 24 bits. Verify that the reload value + * will fit in the reload register. + */ + +#if SYSTICK_RELOAD > 0x00ffffff +# error SYSTICK_RELOAD exceeds the range of the RELOAD register +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: gd32_timerisr + * + * Description: + * The timer ISR will perform a variety of services for various portions + * of the systems. + * + ****************************************************************************/ + +#if !defined(CONFIG_ARMV7M_SYSTICK) && !defined(CONFIG_TIMER_ARCH) +static int gd32_timerisr(int irq, uint32_t *regs, void *arg) +{ + /* Process timer interrupt */ + + nxsched_process_timer(); + return 0; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize + * the timer interrupt. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + uint32_t regval; + + /* Set the SysTick interrupt to the default priority */ + + regval = getreg32(NVIC_SYSH12_15_PRIORITY); + regval &= ~NVIC_SYSH_PRIORITY_PR15_MASK; + regval |= (NVIC_SYSH_PRIORITY_DEFAULT << NVIC_SYSH_PRIORITY_PR15_SHIFT); + putreg32(regval, NVIC_SYSH12_15_PRIORITY); + + /* Make sure that the SYSTICK clock source is set correctly */ + +#if defined(CONFIG_ARMV7M_SYSTICK) && defined(CONFIG_TIMER_ARCH) + up_timer_set_lowerhalf(systick_initialize(true, GD32_SYSCLK_FREQUENCY, + -1)); +#else + /* Configure SysTick to interrupt at the requested rate */ + + putreg32(SYSTICK_RELOAD, NVIC_SYSTICK_RELOAD); + + /* Attach the timer interrupt vector */ + + irq_attach(GD32_IRQ_SYSTICK, (xcpt_t)gd32_timerisr, NULL); + + /* Enable SysTick interrupts */ + + putreg32((NVIC_SYSTICK_CTRL_CLKSOURCE | NVIC_SYSTICK_CTRL_TICKINT | + NVIC_SYSTICK_CTRL_ENABLE), NVIC_SYSTICK_CTRL); + + /* And enable the timer interrupt */ + + up_enable_irq(GD32_IRQ_SYSTICK); +#endif +} diff --git a/arch/arm/src/gd32f4/gd32f4xx_usart.h b/arch/arm/src/gd32f4/gd32f4xx_usart.h new file mode 100644 index 0000000000..3fade45d76 --- /dev/null +++ b/arch/arm/src/gd32f4/gd32f4xx_usart.h @@ -0,0 +1,594 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/gd32f4xx_usart.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_GD32F4_GD32F4XX_USART_H +#define __ARCH_ARM_GD32F4_GD32F4XX_USART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" + +#if defined(CONFIG_GD32F4_GD32F4XX) +# include "hardware/gd32f4xx_uart.h" +#else +# error "Unsupported GD32 UART" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Make sure that we have not enabled more U[S]ARTs than are supported by the + * device. + */ + +#if GD32_NUSART < 8 || !defined(CONFIG_GD32F4_HAVE_UART7) +# undef CONFIG_GD32F4_UART7 +#endif +#if GD32_NUSART < 7 || !defined(CONFIG_GD32F4_HAVE_UART6) +# undef CONFIG_GD32F4_UART6 +#endif + +#if GD32_NUSART < 6 +# undef CONFIG_GD32F4_USART5 +#endif +#if GD32_NUSART < 5 +# undef CONFIG_GD32F4_UART4 +#endif +#if GD32_NUSART < 4 +# undef CONFIG_GD32F4_UART3 +#endif +#if GD32_NUSART < 3 +# undef CONFIG_GD32F4_USART2 +#endif +#if GD32_NUSART < 2 +# undef CONFIG_GD32F4_USART1 +#endif +#if GD32_NUSART < 1 +# undef CONFIG_GD32F4_USART0 +#endif + +/* Sanity checks */ + +#if !defined(CONFIG_GD32F4_USART0) +# undef CONFIG_GD32F4_USART0_SERIALDRIVER +# undef CONFIG_GD32F4_USART0_1WIREDRIVER +#endif +#if !defined(CONFIG_GD32F4_USART1) +# undef CONFIG_GD32F4_USART1_SERIALDRIVER +# undef CONFIG_GD32F4_USART1_1WIREDRIVER +#endif +#if !defined(CONFIG_GD32F4_USART2) +# undef CONFIG_GD32F4_USART2_SERIALDRIVER +# undef CONFIG_GD32F4_USART2_1WIREDRIVER +#endif +#if !defined(CONFIG_GD32F4_UART3) +# undef CONFIG_GD32F4_UART3_SERIALDRIVER +# undef CONFIG_GD32F4_UART3_1WIREDRIVER +#endif +#if !defined(CONFIG_GD32F4_UART4) +# undef CONFIG_GD32F4_UART4_SERIALDRIVER +# undef CONFIG_GD32F4_UART4_1WIREDRIVER +#endif +#if !defined(CONFIG_GD32F4_USART5) +# undef CONFIG_GD32F4_USART5_SERIALDRIVER +# undef CONFIG_GD32F4_USART5_1WIREDRIVER +#endif +#if !defined(CONFIG_GD32F4_UART6) +# undef CONFIG_GD32F4_UART6_SERIALDRIVER +# undef CONFIG_GD32F4_UART6_1WIREDRIVER +#endif +#if !defined(CONFIG_GD32F4_UART7) +# undef CONFIG_GD32F4_UART7_SERIALDRIVER +# undef CONFIG_GD32F4_UART7_1WIREDRIVER +#endif + +/* Check 1-Wire and U(S)ART conflicts */ + +#if defined(CONFIG_GD32F4_USART0_1WIREDRIVER) && defined(CONFIG_GD32F4_USART0_SERIALDRIVER) +# error "Both CONFIG_GD32F4_USART0_1WIREDRIVER and CONFIG_GD32F4_USART0_SERIALDRIVER defined" +# undef CONFIG_GD32F4_USART0_1WIREDRIVER +#endif +#if defined(CONFIG_GD32F4_USART1_1WIREDRIVER) && defined(CONFIG_GD32F4_USART1_SERIALDRIVER) +# error "Both CONFIG_GD32F4_USART1_1WIREDRIVER and CONFIG_GD32F4_USART1_SERIALDRIVER defined" +# undef CONFIG_GD32F4_USART1_1WIREDRIVER +#endif +#if defined(CONFIG_GD32F4_USART2_1WIREDRIVER) && defined(CONFIG_GD32F4_USART2_SERIALDRIVER) +# error "Both CONFIG_GD32F4_USART2_1WIREDRIVER and CONFIG_GD32F4_USART2_SERIALDRIVER defined" +# undef CONFIG_GD32F4_USART2_1WIREDRIVER +#endif +#if defined(CONFIG_GD32F4_UART3_1WIREDRIVER) && defined(CONFIG_GD32F4_UART3_SERIALDRIVER) +# error "Both CONFIG_GD32F4_UART3_1WIREDRIVER and CONFIG_GD32F4_UART3_SERIALDRIVER defined" +# undef CONFIG_GD32F4_UART3_1WIREDRIVER +#endif +#if defined(CONFIG_GD32F4_UART4_1WIREDRIVER) && defined(CONFIG_GD32F4_UART4_SERIALDRIVER) +# error "Both CONFIG_GD32F4_UART4_1WIREDRIVER and CONFIG_GD32F4_UART4_SERIALDRIVER defined" +# undef CONFIG_GD32F4_UART4_1WIREDRIVER +#endif +#if defined(CONFIG_GD32F4_USART5_1WIREDRIVER) && defined(CONFIG_GD32F4_USART5_SERIALDRIVER) +# error "Both CONFIG_GD32F4_USART5_1WIREDRIVER and CONFIG_GD32F4_USART5_SERIALDRIVER defined" +# undef CONFIG_GD32F4_USART5_1WIREDRIVER +#endif +#if defined(CONFIG_GD32F4_UART6_1WIREDRIVER) && defined(CONFIG_GD32F4_UART6_SERIALDRIVER) +# error "Both CONFIG_GD32F4_UART6_1WIREDRIVER and CONFIG_GD32F4_UART6_SERIALDRIVER defined" +# undef CONFIG_GD32F4_UART6_1WIREDRIVER +#endif +#if defined(CONFIG_GD32F4_UART7_1WIREDRIVER) && defined(CONFIG_GD32F4_UART7_SERIALDRIVER) +# error "Both CONFIG_GD32F4_UART7_1WIREDRIVER and CONFIG_GD32F4_UART7_SERIALDRIVER defined" +# undef CONFIG_GD32F4_UART7_1WIREDRIVER +#endif + +/* Is the serial driver enabled? */ + +#if defined(CONFIG_GD32F4_USART0_SERIALDRIVER) || defined(CONFIG_GD32F4_USART1_SERIALDRIVER) || \ + defined(CONFIG_GD32F4_USART2_SERIALDRIVER) || defined(CONFIG_GD32F4_UART3_SERIALDRIVER) || \ + defined(CONFIG_GD32F4_UART4_SERIALDRIVER) || defined(CONFIG_GD32F4_USART5_SERIALDRIVER) || \ + defined(CONFIG_GD32F4_UART6_SERIALDRIVER) || defined(CONFIG_GD32F4_UART7_SERIALDRIVER) +# define HAVE_SERIALDRIVER 1 +#endif + +/* Is the 1-Wire driver? */ + +#if defined(CONFIG_GD32F4_USART0_1WIREDRIVER) || defined(CONFIG_GD32F4_USART1_1WIREDRIVER) || \ + defined(CONFIG_GD32F4_USART2_1WIREDRIVER) || defined(CONFIG_GD32F4_UART3_1WIREDRIVER) || \ + defined(CONFIG_GD32F4_UART4_1WIREDRIVER) || defined(CONFIG_GD32F4_USART5_1WIREDRIVER) || \ + defined(CONFIG_GD32F4_UART6_1WIREDRIVER) || defined(CONFIG_GD32F4_UART7_1WIREDRIVER) +# define HAVE_1WIREDRIVER 1 +#endif + +/* Is there a serial console? */ + +#if defined(CONFIG_USART0_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART0_SERIALDRIVER) +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define CONSOLE_UART 0 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_USART1_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART1_SERIALDRIVER) +# undef CONFIG_USART0_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define CONSOLE_UART 1 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_USART2_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART2_SERIALDRIVER) +# undef CONFIG_USART0_SERIAL_CONSOLE +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define CONSOLE_UART 2 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART3_SERIALDRIVER) +# undef CONFIG_USART0_SERIAL_CONSOLE +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define CONSOLE_UART 3 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_UART4_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART4_SERIALDRIVER) +# undef CONFIG_USART0_SERIAL_CONSOLE +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define CONSOLE_UART 4 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_USART5_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART5_SERIALDRIVER) +# undef CONFIG_USART0_SERIAL_CONSOLE +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define CONSOLE_UART 5 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_UART6_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART6_SERIALDRIVER) +# undef CONFIG_USART0_SERIAL_CONSOLE +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define CONSOLE_UART 6 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_UART7_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART7_SERIALDRIVER) +# undef CONFIG_USART0_SERIAL_CONSOLE +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# define CONSOLE_UART 7 +# define HAVE_CONSOLE 1 +#else +# undef CONFIG_USART0_SERIAL_CONSOLE +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_USART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# undef CONSOLE_UART +# undef HAVE_CONSOLE +#endif + +/* DMA support is only provided if CONFIG_ARCH_DMA is in the + * NuttX configuration + */ + +#if !defined(HAVE_SERIALDRIVER) || !defined(CONFIG_ARCH_DMA) +# undef CONFIG_GD32F4_USART0_RXDMA +# undef CONFIG_GD32F4_USART0_TXDMA +# undef CONFIG_GD32F4_USART1_RXDMA +# undef CONFIG_GD32F4_USART1_TXDMA +# undef CONFIG_GD32F4_USART2_RXDMA +# undef CONFIG_GD32F4_USART2_TXDMA +# undef CONFIG_GD32F4_UART3_RXDMA +# undef CONFIG_GD32F4_UART3_TXDMA +# undef CONFIG_GD32F4_UART4_RXDMA +# undef CONFIG_GD32F4_UART4_TXDMA +# undef CONFIG_GD32F4_USART5_RXDMA +# undef CONFIG_GD32F4_USART5_TXDMA +# undef CONFIG_GD32F4_UART6_RXDMA +# undef CONFIG_GD32F4_UART6_TXDMA +# undef CONFIG_GD32F4_UART7_RXDMA +# undef CONFIG_GD32F4_UART7_TXDMA +#endif + +/* Disable the DMA configuration on all unused USARTs */ + +#ifndef CONFIG_GD32F4_USART0_SERIALDRIVER +# undef CONFIG_GD32F4_USART0_RXDMA +# undef CONFIG_GD32F4_USART0_TXDMA +#endif + +#ifndef CONFIG_GD32F4_USART1_SERIALDRIVER +# undef CONFIG_GD32F4_USART1_RXDMA +# undef CONFIG_GD32F4_USART1_TXDMA +#endif + +#ifndef CONFIG_GD32F4_USART2_SERIALDRIVER +# undef CONFIG_GD32F4_USART2_RXDMA +# undef CONFIG_GD32F4_USART2_TXDMA +#endif + +#ifndef CONFIG_GD32F4_UART3_SERIALDRIVER +# undef CONFIG_GD32F4_UART3_RXDMA +# undef CONFIG_GD32F4_UART3_TXDMA +#endif + +#ifndef CONFIG_GD32F4_UART4_SERIALDRIVER +# undef CONFIG_GD32F4_UART4_RXDMA +# undef CONFIG_GD32F4_UART4_TXDMA +#endif + +#ifndef CONFIG_GD32F4_USART5_SERIALDRIVER +# undef CONFIG_GD32F4_USART5_RXDMA +# undef CONFIG_GD32F4_USART5_TXDMA +#endif + +#ifndef CONFIG_GD32F4_UART6_SERIALDRIVER +# undef CONFIG_GD32F4_UART6_RXDMA +# undef CONFIG_GD32F4_UART6_TXDMA +#endif + +#ifndef CONFIG_GD32F4_UART7_SERIALDRIVER +# undef CONFIG_GD32F4_UART7_RXDMA +# undef CONFIG_GD32F4_UART7_TXDMA +#endif + +/* Is DMA available on any (enabled) USART? */ + +#undef SERIAL_HAVE_RXDMA +#if defined(CONFIG_GD32F4_USART0_RXDMA) || defined(CONFIG_GD32F4_USART1_RXDMA) || \ + defined(CONFIG_GD32F4_USART2_RXDMA) || defined(CONFIG_GD32F4_UART3_RXDMA) || \ + defined(CONFIG_GD32F4_UART4_RXDMA) || defined(CONFIG_GD32F4_USART5_RXDMA) || \ + defined(CONFIG_GD32F4_UART6_RXDMA) || defined(CONFIG_GD32F4_UART7_RXDMA) +# define SERIAL_HAVE_RXDMA 1 +#endif + +/* Is TX DMA available on any (enabled) USART? */ + +#undef SERIAL_HAVE_TXDMA +#if defined(CONFIG_GD32F4_USART0_TXDMA) || defined(CONFIG_GD32F4_USART1_TXDMA) || \ + defined(CONFIG_GD32F4_USART2_TXDMA) || defined(CONFIG_GD32F4_UART3_TXDMA) || \ + defined(CONFIG_GD32F4_UART4_TXDMA) || defined(CONFIG_GD32F4_USART5_TXDMA) || \ + defined(CONFIG_GD32F4_UART6_TXDMA) || defined(CONFIG_GD32F4_UART7_TXDMA) +# define SERIAL_HAVE_TXDMA 1 +#endif + +/* Is RX DMA used on the console UART? */ + +#undef SERIAL_HAVE_CONSOLE_RXDMA +#if defined(CONFIG_USART0_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART0_RXDMA) +# define SERIAL_HAVE_CONSOLE_RXDMA 1 +#elif defined(CONFIG_USART1_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART1_RXDMA) +# define SERIAL_HAVE_CONSOLE_RXDMA 1 +#elif defined(CONFIG_USART2_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART2_RXDMA) +# define SERIAL_HAVE_CONSOLE_RXDMA 1 +#elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART3_RXDMA) +# define SERIAL_HAVE_CONSOLE_RXDMA 1 +#elif defined(CONFIG_UART4_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART4_RXDMA) +# define SERIAL_HAVE_CONSOLE_RXDMA 1 +#elif defined(CONFIG_USART5_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART5_RXDMA) +# define SERIAL_HAVE_CONSOLE_RXDMA 1 +#elif defined(CONFIG_UART6_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART6_RXDMA) +# define SERIAL_HAVE_CONSOLE_RXDMA 1 +#elif defined(CONFIG_UART7_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART7_RXDMA) +# define SERIAL_HAVE_CONSOLE_RXDMA 1 +#endif + +/* Is TX DMA used on the console UART? */ + +#undef SERIAL_HAVE_CONSOLE_TXDMA +#if defined(CONFIG_USART0_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART0_TXDMA) +# define SERIAL_HAVE_CONSOLE_TXDMA 1 +#elif defined(CONFIG_USART1_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART1_TXDMA) +# define SERIAL_HAVE_CONSOLE_TXDMA 1 +#elif defined(CONFIG_USART2_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART2_TXDMA) +# define SERIAL_HAVE_CONSOLE_TXDMA 1 +#elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART3_TXDMA) +# define SERIAL_HAVE_CONSOLE_TXDMA 1 +#elif defined(CONFIG_UART4_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART4_TXDMA) +# define SERIAL_HAVE_CONSOLE_TXDMA 1 +#elif defined(CONFIG_USART5_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_USART5_TXDMA) +# define SERIAL_HAVE_CONSOLE_TXDMA 1 +#elif defined(CONFIG_UART6_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART6_TXDMA) +# define SERIAL_HAVE_CONSOLE_TXDMA 1 +#elif defined(CONFIG_UART7_SERIAL_CONSOLE) && defined(CONFIG_GD32F4_UART7_TXDMA) +# define SERIAL_HAVE_CONSOLE_TXDMA 1 +#endif + +/* No DMA */ + +#undef SERIAL_NOT_HAVE_DMA +#if defined(CONFIG_GD32F4_USART0) && !defined(CONFIG_GD32F4_USART0_RXDMA) && \ + !defined(CONFIG_GD32F4_USART0_TXDMA) +# define SERIAL_NOT_HAVE_DMA +#elif defined(CONFIG_GD32F4_USART1) && !defined(CONFIG_GD32F4_USART1_RXDMA) && \ + !defined(CONFIG_GD32F4_USART1_TXDMA) +# define SERIAL_NOT_HAVE_DMA +#elif defined(CONFIG_GD32F4_USART2) && !defined(CONFIG_GD32F4_USART2_RXDMA) && \ + !defined(CONFIG_GD32F4_USART2_TXDMA) +# define SERIAL_NOT_HAVE_DMA +#elif defined(CONFIG_GD32F4_UART3) && !defined(CONFIG_GD32F4_UART3_RXDMA) && \ + !defined(CONFIG_GD32F4_UART3_TXDMA) +# define SERIAL_NOT_HAVE_DMA +#elif defined(CONFIG_GD32F4_UART4) && !defined(CONFIG_GD32F4_UART4_RXDMA) && \ + !defined(CONFIG_GD32F4_UART4_TXDMA) +# define SERIAL_NOT_HAVE_DMA +#elif defined(CONFIG_GD32F4_USART5) && !defined(CONFIG_GD32F4_USART5_RXDMA) && \ + !defined(CONFIG_GD32F4_USART5_TXDMA) +# define SERIAL_NOT_HAVE_DMA +#elif defined(CONFIG_GD32F4_UART6) && !defined(CONFIG_GD32F4_UART6_RXDMA) && \ + !defined(CONFIG_GD32F4_UART6_TXDMA) +# define SERIAL_NOT_HAVE_DMA +#elif defined(CONFIG_GD32F4_UART7) && !defined(CONFIG_GD32F4_UART7_RXDMA) && \ + !defined(CONFIG_GD32F4_UART7_TXDMA) +# define SERIAL_NOT_HAVE_DMA +#endif + +/* RX DMA */ + +#undef SERIAL_HAVE_RX_DMA +#if defined(CONFIG_GD32F4_USART0_RXDMA) && !defined(CONFIG_GD32F4_USART0_TXDMA) +# define SERIAL_HAVE_RX_DMA +#elif defined(CONFIG_GD32F4_USART1_RXDMA) && !defined(CONFIG_GD32F4_USART1_TXDMA) +# define SERIAL_HAVE_RX_DMA +#elif defined(CONFIG_GD32F4_USART2_RXDMA) && !defined(CONFIG_GD32F4_USART2_TXDMA) +# define SERIAL_HAVE_RX_DMA +#elif defined(CONFIG_GD32F4_UART3_RXDMA) && !defined(CONFIG_GD32F4_UART3_TXDMA) +# define SERIAL_HAVE_RX_DMA +#elif defined(CONFIG_GD32F4_UART4_RXDMA) && !defined(CONFIG_GD32F4_UART4_TXDMA) +# define SERIAL_HAVE_RX_DMA +#elif defined(CONFIG_GD32F4_USART5_RXDMA) && !defined(CONFIG_GD32F4_USART5_TXDMA) +# define SERIAL_HAVE_RX_DMA +#elif defined(CONFIG_GD32F4_UART6_RXDMA) && !defined(CONFIG_GD32F4_UART6_TXDMA) +# define SERIAL_HAVE_RX_DMA +#elif defined(CONFIG_GD32F4_UART7_RXDMA) && !defined(CONFIG_GD32F4_UART7_TXDMA) +# define SERIAL_HAVE_RX_DMA +#endif + +/* TX DMA */ + +#undef SERIAL_HAVE_TX_DMA +#if !defined(CONFIG_GD32F4_USART0_RXDMA) && defined(CONFIG_GD32F4_USART0_TXDMA) +# define SERIAL_HAVE_TX_DMA +#elif !defined(CONFIG_GD32F4_USART1_RXDMA) && defined(CONFIG_GD32F4_USART1_TXDMA) +# define SERIAL_HAVE_TX_DMA +#elif !defined(CONFIG_GD32F4_USART2_RXDMA) && defined(CONFIG_GD32F4_USART2_TXDMA) +# define SERIAL_HAVE_TX_DMA +#elif !defined(CONFIG_GD32F4_UART3_RXDMA) && defined(CONFIG_GD32F4_UART3_TXDMA) +# define SERIAL_HAVE_TX_DMA +#elif !defined(CONFIG_GD32F4_UART4_RXDMA) && defined(CONFIG_GD32F4_UART4_TXDMA) +# define SERIAL_HAVE_TX_DMA +#elif !defined(CONFIG_GD32F4_USART5_RXDMA) && defined(CONFIG_GD32F4_USART5_TXDMA) +# define SERIAL_HAVE_TX_DMA +#elif !defined(CONFIG_GD32F4_UART6_RXDMA) && defined(CONFIG_GD32F4_UART6_TXDMA) +# define SERIAL_HAVE_TX_DMA +#elif !defined(CONFIG_GD32F4_UART7_RXDMA) && defined(CONFIG_GD32F4_UART7_TXDMA) +# define SERIAL_HAVE_TX_DMA +#endif + +/* RX and TX DMA */ + +#undef SERIAL_HAVE_RXTX_DMA +#if defined(CONFIG_GD32F4_USART0_RXDMA) && defined(CONFIG_GD32F4_USART0_TXDMA) +# define SERIAL_HAVE_RXTX_DMA +#elif defined(CONFIG_GD32F4_USART1_RXDMA) && defined(CONFIG_GD32F4_USART1_TXDMA) +# define SERIAL_HAVE_RXTX_DMA +#elif defined(CONFIG_GD32F4_USART2_RXDMA) && defined(CONFIG_GD32F4_USART2_TXDMA) +# define SERIAL_HAVE_RXTX_DMA +#elif defined(CONFIG_GD32F4_UART3_RXDMA) && defined(CONFIG_GD32F4_UART3_TXDMA) +# define SERIAL_HAVE_RXTX_DMA +#elif defined(CONFIG_GD32F4_UART4_RXDMA) && defined(CONFIG_GD32F4_UART4_TXDMA) +# define SERIAL_HAVE_RXTX_DMA +#elif defined(CONFIG_GD32F4_USART5_RXDMA) && defined(CONFIG_GD32F4_USART5_TXDMA) +# define SERIAL_HAVE_RXTX_DMA +#elif defined(CONFIG_GD32F4_UART6_RXDMA) && defined(CONFIG_GD32F4_UART6_TXDMA) +# define SERIAL_HAVE_RXTX_DMA +#elif defined(CONFIG_GD32F4_UART7_RXDMA) && defined(CONFIG_GD32F4_UART7_TXDMA) +# define SERIAL_HAVE_RXTX_DMA +#endif + +/* Is RS-485 used? */ + +#if defined(CONFIG_USART0_RS485) || defined(CONFIG_USART1_RS485) || \ + defined(CONFIG_USART2_RS485) || defined(CONFIG_UART3_RS485) || \ + defined(CONFIG_UART4_RS485) || defined(CONFIG_USART5_RS485) || \ + defined(CONFIG_UART6_RS485) || defined(CONFIG_UART7_RS485) +# define HAVE_RS485 1 +#endif + +/* Usart oversample mode. */ + +#define USART_OVSMOD_16 (0) +#define USART_OVSMOD_8 (USART_CTL0_OVSMOD) + +/* USART interrupts maps, each interrupt of the USART can be individually + * configured by software. The following definitions provide the bit + * encodingthat used to define the interrupt and control register offset. + * + * 24-bit Encoding: 2222 2222 1111 1111 1100 0000 0000 + * 7654 3210 9876 5432 1098 7654 3210 + * ENCODING SHIF + * + * CTL SHIFT: Bit24-27, CTL2 int: Bit8-23, CTL3 int: Bit6-7, + * CTL1 int: Bit5, CTL0 int: Bit0-4, + */ + +#define USART_CFG_SHIFT (24) +#define USART_CFG_CTL0_INT (1) +#define USART_CFG_CTL1_INT (2) +#define USART_CFG_CTL2_INT (4) +#define USART_CFG_CTL3_INT (8) +#define USART_CFG_CTL_MASK (0xf) + +/* USART interrupt in CTL0 register */ +#define USART_CFG_CTL0_INT_SHIFT (4) +# define USART_CFG_CTL0_INT_IDLIE ((USART_CFG_CTL0_INT << USART_CFG_SHIFT) | (USART_CTL0_IDLEIE >> USART_CFG_CTL0_INT_SHIFT)) +# define USART_CFG_CTL0_INT_RBNEIE ((USART_CFG_CTL0_INT << USART_CFG_SHIFT) | (USART_CTL0_RBNEIE >> USART_CFG_CTL0_INT_SHIFT)) +# define USART_CFG_CTL0_INT_TCIE ((USART_CFG_CTL0_INT << USART_CFG_SHIFT) | (USART_CTL0_TCIE >> USART_CFG_CTL0_INT_SHIFT)) +# define USART_CFG_CTL0_INT_TBEIE ((USART_CFG_CTL0_INT << USART_CFG_SHIFT) | (USART_CTL0_TBEIE >> USART_CFG_CTL0_INT_SHIFT)) +# define USART_CFG_CTL0_INT_PERRIE ((USART_CFG_CTL0_INT << USART_CFG_SHIFT) | (USART_CTL0_PERRIE >> USART_CFG_CTL0_INT_SHIFT)) + +/* USART interrupt in CTL1 register */ + +#define USART_CFG_CTL1_INT_SHIFT (1) +# define USART_CFG_CTL1_INT_LBDIE ((USART_CFG_CTL1_INT << USART_CFG_SHIFT) | (USART_CTL1_LBDIE >> USART_CFG_CTL0_INT_SHIFT)) + +/* USART interrupt in CTL2 register */ + +#define USART_CFG_CTL2_INT_SHIFT (8) +# define USART_CFG_CTL2_INT_ERRIE ((USART_CFG_CTL2_INT << USART_CFG_SHIFT) | (USART_CTL2_ERRIE << USART_CFG_CTL0_INT_SHIFT)) +# define USART_CFG_CTL2_INT_CTSIE ((USART_CFG_CTL2_INT << USART_CFG_SHIFT) | (USART_CTL2_CTSIE << USART_CFG_CTL0_INT_SHIFT)) + +/* USART interrupt in CTL3 register */ + +#define USART_CFG_CTL3_INT_SHIFT (2) +# define USART_CFG_CTL3_INT_RTIE ((USART_CFG_CTL3_INT << USART_CFG_SHIFT) | USART_CTL3_RTIE << USART_CFG_CTL3_INT_SHIFT) +# define USART_CFG_CTL3_INT_EBIE ((USART_CFG_CTL3_INT << USART_CFG_SHIFT) | USART_CTL3_EBIE << USART_CFG_CTL3_INT_SHIFT) + +#define USART_CTL0_USED_INTS USART_CTL0_INT_MASK +#define USART_CTL1_USED_INTS USART_CTL1_INT_MASK +#define USART_CTL2_USED_INTS USART_CTL2_INT_MASK +#define USART_CTL3_USED_INTS USART_CTL3_INT_MASK + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_serial_get_uart + * + * Description: + * Get serial driver structure for GD32 USART + * + ****************************************************************************/ + +uart_dev_t *gd32_serial_get_uart(int uart_num); + +/**************************************************************************** + * Name: gd32_serial_dma_poll + * + * Description: + * Must be called periodically if any GD32 UART is configured for DMA. + * The DMA callback is triggered for each fifo size/2 bytes, but this can + * result in some bytes being transferred but not collected if the incoming + * data is not a whole multiple of half the FIFO size. + * + * May be safely called from either interrupt or thread context. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_RXDMA +void gd32_serial_dma_poll(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_GD32F4_GD32F4XX_USART_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f450_memorymap.h b/arch/arm/src/gd32f4/hardware/gd32f450_memorymap.h new file mode 100644 index 0000000000..769c192616 --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f450_memorymap.h @@ -0,0 +1,138 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f450_memorymap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F450_MEMORYMAP_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F450_MEMORYMAP_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* GD32F4XX Address Blocks **************************************************/ + +#define GD32_CODE_BASE 0x00000000 /* 0x00000000-0x1fffffff: 512Mb code block */ +#define GD32_SRAM_BASE 0x20000000 /* 0x20000000-0x3fffffff: 512Mb sram block */ +#define GD32_PERIPH_BASE 0x40000000 /* 0x40000000-0x5fffffff: 512Mb peripheral block */ + +#define GD32_EXMC_REG_BASE 0xa0000000 /* 0xa0000000-0xbfffffff: 512Mb EXMC register block */ +#define GD32_EXMC_BASE 0x60000000 /* 0x60000000-0x7fffffff: EXMC base */ +#define GD32_EXMC_BANK0 0x60000000 /* 0x60000000-0x6fffffff: 256Mb NOR/PSRAM/SRAM */ +#define GD32_EXMC_BANK1 0x70000000 /* 0x70000000-0x7fffffff: 256Mb NAND FLASH */ +#define GD32_EXMC_BANK2 0x80000000 /* 0x80000000-0x8fffffff: 256Mb NAND FLASH */ +#define GD32_EXMC_BANK3 0x90000000 /* 0x90000000-0x9fffffff: 256Mb PC CARD*/ +#define GD32_EXMC_BANK4 0xc0000000 /* 0xc0000000-0xcfffffff: 256Mb SDRAM */ +#define GD32_EXMC_BANK5 0xd0000000 /* 0xd0000000-0xdfffffff: 256Mb SDRAM */ + +#define GD32_CORTEX_BASE 0xe0000000 /* 0xe0000000-0xffffffff: 512Mb Cortex-M4 block */ + +#define GD32_REGION_MASK 0xf0000000 +#define GD32_IS_SRAM(a) ((((uint32_t)(a)) & GD32_REGION_MASK) == GD32_SRAM_BASE) +#define GD32_IS_EXTSRAM(a) ((((uint32_t)(a)) & GD32_REGION_MASK) == GD32_EXMC_BANK0) + +/* Code Base Addresses ******************************************************/ + +#define GD32_BOOT_BASE 0x00000000 /* 0x00000000-0x007ffffff: Aliased to the boot device */ +#define GD32_FLASH_BASE 0x08000000 /* 0x08000000-0x082fffff: Main flash */ + /* 0x08100000-0x0fffffff: Reserved */ +#define GD32_TCMSRAM_BASE 0x10000000 /* 0x10000000-0x1000ffff: 64Kb TCMSRAM */ + /* 0x10010000-0x1ffebfff: Reserved */ +#define GD32_OPBYTE_BANK1 0x1ffec000 /* 0x1ffec000-0x1ffec00f: 16b Option bytes */ + /* 0x1ffec010-0x1ffeffff: Reserved */ +#define GD32_BOOTLD_BASE 0x1fff0000 /* 0x1fff0000-0x1fff77ff: 30Kb Boot loader */ +#define GD32_OTP_BASE 0x1fff7800 /* 0x1fff7800-0x1fff7a0f: 528b OTP block */ + /* 0x1fff7a10-0x1fffbfff: Reserved */ +#define GD32_OPBYTE_BANK0 0x1fffc000 /* 0x1fffc000-0x1fffc00f: 16b Option bytes */ + /* 0x1fffc010-0x1fffffff: Reserved */ + +/* System Memory Addresses **************************************************/ + +#define GD32_UNIQUE_ID 0x1fff7a10 /* The 96-bit unique device ID */ +#define GD32_FLASH_DENSITY 0x1fff7a20 /* The memory density information, indicates the size of + * the device Flash or RAM memory expressed in + * Kbytes. Example: 0x020 corresponds + * to 32 Kbytes. + */ + +/* SRAM Base Addresses ******************************************************/ + +/* 0x20000000-0x2001bfff: + * 112Kb aliased by bit-banding + */ + +/* 0x2001c000-0x2001ffff: + * 16Kb aliased by bit-banding + */ + +#define GD32_SRAMBB_BASE 0x22000000 /* 0x22000000- : SRAM bit-band region */ + +/* Peripheral Base Addresses ************************************************/ + +#define GD32_APB1_BUS_BASE 0x40000000 /* APB1 base address */ +#define GD32_APB2_BUS_BASE 0x40010000 /* APB2 base address */ +#define GD32_AHB1_BUS_BASE 0x40020000 /* AHB1 base address */ +#define GD32_AHB2_BUS_BASE 0x50000000 /* AHB2 base address */ + +/* APB1 Base Addresses ******************************************************/ + +#define GD32_TIMER_BASE (GD32_APB1_BUS_BASE + 0x00000000U) /* TIMER base address */ +#define GD32_RTC_BASE (GD32_APB1_BUS_BASE + 0x00002800U) /* RTC base address */ +#define GD32_WWDGT_BASE (GD32_APB1_BUS_BASE + 0x00002C00U) /* WWDGT base address */ +#define GD32_FWDGT_BASE (GD32_APB1_BUS_BASE + 0x00003000U) /* FWDGT base address */ +#define GD32_I2S_ADD_BASE (GD32_APB1_BUS_BASE + 0x00003400U) /* I2S1_add base address */ +#define GD32_SPI_BASE (GD32_APB1_BUS_BASE + 0x00003800U) /* SPI base address */ +#define GD32_USART_BASE (GD32_APB1_BUS_BASE + 0x00004400U) /* USART base address */ +#define GD32_I2C_BASE (GD32_APB1_BUS_BASE + 0x00005400U) /* I2C base address */ +#define GD32_CAN_BASE (GD32_APB1_BUS_BASE + 0x00006400U) /* CAN base address */ +#define GD32_CTC_BASE (GD32_APB1_BUS_BASE + 0x00006C00U) /* CTC base address */ +#define GD32_PMU_BASE (GD32_APB1_BUS_BASE + 0x00007000U) /* PMU base address */ +#define GD32_DAC_BASE (GD32_APB1_BUS_BASE + 0x00007400U) /* DAC base address */ +#define GD32_IREF_BASE (GD32_APB1_BUS_BASE + 0x0000C400U) /* IREF base address */ + +/* APB2 Base Addresses ******************************************************/ + +#define GD32_TLI_BASE (GD32_APB2_BUS_BASE + 0x00006800U) /* TLI base address */ +#define GD32_SYSCFG_BASE (GD32_APB2_BUS_BASE + 0x00003800U) /* SYSCFG base address */ +#define GD32_EXTI_BASE (GD32_APB2_BUS_BASE + 0x00003C00U) /* EXTI base address*/ +#define GD32_SDIO_BASE (GD32_APB2_BUS_BASE + 0x00002C00U) /* SDIO base address */ +#define GD32_ADC_BASE (GD32_APB2_BUS_BASE + 0x00002000U) /* ADC base address */ + +/* AHB1 Base Addresses ******************************************************/ + +#define GD32_GPIO_BASE (GD32_AHB1_BUS_BASE + 0x00000000U) /* GPIO base address*/ +#define GD32_CRC_BASE (GD32_AHB1_BUS_BASE + 0x00003000U) /* CRC base address */ +#define GD32_RCU_BASE (GD32_AHB1_BUS_BASE + 0x00003800U) /* RCU base address */ +#define GD32_FMC_BASE (GD32_AHB1_BUS_BASE + 0x00003C00U) /* FMC base address */ +#define GD32_BKPSRAM_BASE (GD32_AHB1_BUS_BASE + 0x00004000U) /* BKPSRAM base address */ +#define GD32_DMA_BASE (GD32_AHB1_BUS_BASE + 0x00006000U) /* DMA base address */ +#define GD32_ENET_BASE (GD32_AHB1_BUS_BASE + 0x00008000U) /* ENET base address */ +#define GD32_IPA_BASE (GD32_AHB1_BUS_BASE + 0x0000B000U) /* IPA base address */ +#define GD32_USBHS_BASE (GD32_AHB1_BUS_BASE + 0x00020000U) /* USBHS base address */ + +/* AHB2 Base Addresses ******************************************************/ + +#define GD32_USBFS_BASE (GD32_AHB2_BUS_BASE + 0x00000000U) /* USBFS base address */ +#define GD32_DCI_BASE (GD32_AHB2_BUS_BASE + 0x00050000U) /* DCI base address */ +#define GD32_TRNG_BASE (GD32_AHB2_BUS_BASE + 0x00060800U) /* TRNG base address */ + +/* DBG register Base Addresses **********************************************/ + +#define GD32_DBG_BASE 0xe0042000 + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F450_MEMORYMAP_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f450_pinmap.h b/arch/arm/src/gd32f4/hardware/gd32f450_pinmap.h new file mode 100644 index 0000000000..ccd216021e --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f450_pinmap.h @@ -0,0 +1,847 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f450_pinmap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F450_PINMAP_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F450_PINMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "gd32f4xx_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Alternate Pin Functions. + * + * Alternative pin selections are provided with a numeric suffix like _1, _2, + * etc. Drivers, however, will use the pin selection without the numeric + * suffix. Additional definitions are required in the board.h file. For + * example, if USART0_TX connects via PA9 on some board, then the following + * definitions should appear in the board.h header file for that board: + * + * #define GPIO_USART0_TX GPIO_USART0_TX_1 + * + * The driver will then automatically configure PA9 as the USART0_TX pin. + */ + +/* General GPIO output */ +#define GPIO_PIN0_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_0) +#define GPIO_PIN1_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_1) +#define GPIO_PIN2_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_2) +#define GPIO_PIN3_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_3) +#define GPIO_PIN4_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_4) +#define GPIO_PIN5_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_5) +#define GPIO_PIN6_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_6) +#define GPIO_PIN7_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_7) +#define GPIO_PIN8_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_8) +#define GPIO_PIN9_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_9) +#define GPIO_PIN10_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_10) +#define GPIO_PIN11_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_11) +#define GPIO_PIN12_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_12) +#define GPIO_PIN13_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_13) +#define GPIO_PIN14_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_14) +#define GPIO_PIN15_OUTPUT (GPIO_CFG_MODE_OUTPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_PIN_15) + +/* General GPIO input */ +#define GPIO_PIN0_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_0) +#define GPIO_PIN1_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_1) +#define GPIO_PIN2_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_2) +#define GPIO_PIN3_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_3) +#define GPIO_PIN4_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_4) +#define GPIO_PIN5_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_5) +#define GPIO_PIN6_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_6) +#define GPIO_PIN7_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_7) +#define GPIO_PIN8_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_8) +#define GPIO_PIN9_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_9) +#define GPIO_PIN10_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_10) +#define GPIO_PIN11_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_11) +#define GPIO_PIN12_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_12) +#define GPIO_PIN13_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_13) +#define GPIO_PIN14_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_14) +#define GPIO_PIN15_INPUT (GPIO_CFG_MODE_INPUT|GPIO_CFG_PUPD_NONE|GPIO_CFG_PIN_15) + +/* Analog-to-digital converter (ADC) */ + +#define GPIO_ADC0_IN0 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_0) +#define GPIO_ADC0_IN1 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_1) +#define GPIO_ADC0_IN2 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_2) +#define GPIO_ADC0_IN3 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_3) +#define GPIO_ADC0_IN4 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_4) +#define GPIO_ADC0_IN5 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_5) +#define GPIO_ADC0_IN6 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_6) +#define GPIO_ADC0_IN7 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_7) +#define GPIO_ADC0_IN8 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_ADC0_IN9 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_B|GPIO_CFG_PIN_1) +#define GPIO_ADC0_IN10 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_0) +#define GPIO_ADC0_IN11 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_1) +#define GPIO_ADC0_IN12 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_2) +#define GPIO_ADC0_IN13 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_3) +#define GPIO_ADC0_IN14 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_4) +#define GPIO_ADC0_IN15 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_5) + +#define GPIO_ADC1_IN0 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_0) +#define GPIO_ADC1_IN1 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_1) +#define GPIO_ADC1_IN2 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_2) +#define GPIO_ADC1_IN3 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_3) +#define GPIO_ADC1_IN4 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_4) +#define GPIO_ADC1_IN5 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_5) +#define GPIO_ADC1_IN6 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_6) +#define GPIO_ADC1_IN7 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_7) +#define GPIO_ADC1_IN8 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_ADC1_IN9 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_B|GPIO_CFG_PIN_1) +#define GPIO_ADC1_IN10 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_0) +#define GPIO_ADC1_IN11 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_1) +#define GPIO_ADC1_IN12 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_2) +#define GPIO_ADC1_IN13 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_3) +#define GPIO_ADC1_IN14 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_4) +#define GPIO_ADC1_IN15 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_5) + +#define GPIO_ADC2_IN0 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_0) +#define GPIO_ADC2_IN1 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_1) +#define GPIO_ADC2_IN2 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_2) +#define GPIO_ADC2_IN3 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_3) +#define GPIO_ADC2_IN4 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_F|GPIO_CFG_PIN_6) +#define GPIO_ADC2_IN5 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_F|GPIO_CFG_PIN_7) +#define GPIO_ADC2_IN6 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_F|GPIO_CFG_PIN_8) +#define GPIO_ADC2_IN7 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_F|GPIO_CFG_PIN_9) +#define GPIO_ADC2_IN8 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_F|GPIO_CFG_PIN_10) +#define GPIO_ADC2_IN9 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_F|GPIO_CFG_PIN_3) +#define GPIO_ADC2_IN10 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_0) +#define GPIO_ADC2_IN11 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_1) +#define GPIO_ADC2_IN12 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_2) +#define GPIO_ADC2_IN13 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_C|GPIO_CFG_PIN_3) +#define GPIO_ADC2_IN14 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_F|GPIO_CFG_PIN_4) +#define GPIO_ADC2_IN15 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_F|GPIO_CFG_PIN_5) + +/* Controller area network (CAN) */ + +#define GPIO_CAN0_RX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_A|GPIO_CFG_PIN_11) +#define GPIO_CAN0_RX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_8) +#define GPIO_CAN0_RX_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_D|GPIO_CFG_PIN_0) +#define GPIO_CAN0_RX_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_I|GPIO_CFG_PIN_9) +#define GPIO_CAN0_TX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_A|GPIO_CFG_PIN_12) +#define GPIO_CAN0_TX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_9) +#define GPIO_CAN0_TX_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_D|GPIO_CFG_PIN_1) +#define GPIO_CAN0_TX_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_H|GPIO_CFG_PIN_13) + +#define GPIO_CAN1_RX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_12) +#define GPIO_CAN1_RX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_5) +#define GPIO_CAN1_TX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_13) +#define GPIO_CAN1_TX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_6) + +/* Clock output */ + +#define GPIO_CKOUT0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_0|GPIO_CFG_PORT_A|GPIO_CFG_PIN_8) +#define GPIO_CKOUT1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_0|GPIO_CFG_PORT_C|GPIO_CFG_PIN_9) + +/* Digital-to-analog converter (DAC) */ + +#define GPIO_DAC_OUT1 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_4) +#define GPIO_DAC_OUT2 (GPIO_CFG_MODE_ANALOG|GPIO_CFG_PUPD_NONE|GPIO_CFG_PORT_A|GPIO_CFG_PIN_5) + +/* Digital camera interface (DCI) */ + +#define GPIO_DCI_D0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_A|GPIO_CFG_PIN_9) +#define GPIO_DCI_D0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_C|GPIO_CFG_PIN_6) +#define GPIO_DCI_D0_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_H|GPIO_CFG_PIN_9) +#define GPIO_DCI_D1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_A|GPIO_CFG_PIN_10) +#define GPIO_DCI_D1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_C|GPIO_CFG_PIN_7) +#define GPIO_DCI_D1_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_H|GPIO_CFG_PIN_10) +#define GPIO_DCI_D2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_C|GPIO_CFG_PIN_8) +#define GPIO_DCI_D2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_E|GPIO_CFG_PIN_0) +#define GPIO_DCI_D2_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_G|GPIO_CFG_PIN_10) +#define GPIO_DCI_D2_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_H|GPIO_CFG_PIN_11) +#define GPIO_DCI_D3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_C|GPIO_CFG_PIN_9) +#define GPIO_DCI_D3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_E|GPIO_CFG_PIN_1) +#define GPIO_DCI_D3_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_G|GPIO_CFG_PIN_11) +#define GPIO_DCI_D3_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_H|GPIO_CFG_PIN_12) +#define GPIO_DCI_D4_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_C|GPIO_CFG_PIN_11) +#define GPIO_DCI_D4_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_E|GPIO_CFG_PIN_4) +#define GPIO_DCI_D4_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_H|GPIO_CFG_PIN_14) +#define GPIO_DCI_D5_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_B|GPIO_CFG_PIN_6) +#define GPIO_DCI_D5_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_D|GPIO_CFG_PIN_3) +#define GPIO_DCI_D5_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_I|GPIO_CFG_PIN_4) +#define GPIO_DCI_D6_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_B|GPIO_CFG_PIN_8) +#define GPIO_DCI_D6_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_E|GPIO_CFG_PIN_5) +#define GPIO_DCI_D6_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_I|GPIO_CFG_PIN_6) +#define GPIO_DCI_D7_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_B|GPIO_CFG_PIN_9) +#define GPIO_DCI_D7_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_E|GPIO_CFG_PIN_6) +#define GPIO_DCI_D7_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_I|GPIO_CFG_PIN_7) +#define GPIO_DCI_D8_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_C|GPIO_CFG_PIN_10) +#define GPIO_DCI_D8_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_H|GPIO_CFG_PIN_6) +#define GPIO_DCI_D8_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_I|GPIO_CFG_PIN_1) +#define GPIO_DCI_D9_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_C|GPIO_CFG_PIN_12) +#define GPIO_DCI_D9_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_H|GPIO_CFG_PIN_7) +#define GPIO_DCI_D9_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_I|GPIO_CFG_PIN_2) +#define GPIO_DCI_D10_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_B|GPIO_CFG_PIN_5) +#define GPIO_DCI_D10_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_D|GPIO_CFG_PIN_6) +#define GPIO_DCI_D10_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_I|GPIO_CFG_PIN_3) +#define GPIO_DCI_D11_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_D|GPIO_CFG_PIN_2) +#define GPIO_DCI_D11_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_F|GPIO_CFG_PIN_10) +#define GPIO_DCI_D11_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_H|GPIO_CFG_PIN_15) +#define GPIO_DCI_D12_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_F|GPIO_CFG_PIN_11) +#define GPIO_DCI_D12_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_G|GPIO_CFG_PIN_6) +#define GPIO_DCI_D13_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_G|GPIO_CFG_PIN_7) +#define GPIO_DCI_D13_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_G|GPIO_CFG_PIN_15) +#define GPIO_DCI_D13_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_I|GPIO_CFG_PIN_0) +#define GPIO_DCI_HSYNC_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_A|GPIO_CFG_PIN_4) +#define GPIO_DCI_HSYNC_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_H|GPIO_CFG_PIN_8) +#define GPIO_DCI_PIXCLK (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_A|GPIO_CFG_PIN_6) +#define GPIO_DCI_VSYNC_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_B|GPIO_CFG_PIN_7) +#define GPIO_DCI_VSYNC_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_G|GPIO_CFG_PIN_9) +#define GPIO_DCI_VSYNC_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_13|GPIO_CFG_PORT_I|GPIO_CFG_PIN_5) + +/* ENET MAC */ + +#define GPIO_ENET_MDC (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_C|GPIO_CFG_PIN_1) +#define GPIO_ENET_MDIO (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_A|GPIO_CFG_PIN_2) +#define GPIO_ENET_MII_COL_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_A|GPIO_CFG_PIN_3) +#define GPIO_ENET_MII_COL_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_H|GPIO_CFG_PIN_3) +#define GPIO_ENET_MII_CRS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_A|GPIO_CFG_PIN_0) +#define GPIO_ENET_MII_CRS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_H|GPIO_CFG_PIN_2) +#define GPIO_ENET_MII_RXD0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_C|GPIO_CFG_PIN_4) +#define GPIO_ENET_MII_RXD1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_C|GPIO_CFG_PIN_5) +#define GPIO_ENET_MII_RXD2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_ENET_MII_RXD2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_H|GPIO_CFG_PIN_6) +#define GPIO_ENET_MII_RXD3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_B|GPIO_CFG_PIN_1) +#define GPIO_ENET_MII_RXD3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_H|GPIO_CFG_PIN_7) +#define GPIO_ENET_MII_RX_CLK (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_A|GPIO_CFG_PIN_1) +#define GPIO_ENET_MII_RX_DV (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_A|GPIO_CFG_PIN_7) +#define GPIO_ENET_MII_RX_ER_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_B|GPIO_CFG_PIN_10) +#define GPIO_ENET_MII_RX_ER_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_I|GPIO_CFG_PIN_10) +#define GPIO_ENET_MII_TXD0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_B|GPIO_CFG_PIN_12) +#define GPIO_ENET_MII_TXD0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_G|GPIO_CFG_PIN_13) +#define GPIO_ENET_MII_TXD1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_B|GPIO_CFG_PIN_13) +#define GPIO_ENET_MII_TXD1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_G|GPIO_CFG_PIN_14) +#define GPIO_ENET_MII_TXD2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_C|GPIO_CFG_PIN_2) +#define GPIO_ENET_MII_TXD3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_B|GPIO_CFG_PIN_8) +#define GPIO_ENET_MII_TXD3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_E|GPIO_CFG_PIN_2) +#define GPIO_ENET_MII_TX_CLK (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_C|GPIO_CFG_PIN_3) +#define GPIO_ENET_MII_TX_EN_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_B|GPIO_CFG_PIN_11) +#define GPIO_ENET_MII_TX_EN_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_G|GPIO_CFG_PIN_11) +#define GPIO_ENET_PPS_OUT_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_B|GPIO_CFG_PIN_5) +#define GPIO_ENET_PPS_OUT_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_G|GPIO_CFG_PIN_8) +#define GPIO_ENET_RMII_CRS_DV (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_A|GPIO_CFG_PIN_7) +#define GPIO_ENET_RMII_REF_CLK (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_A|GPIO_CFG_PIN_1) +#define GPIO_ENET_RMII_RXD0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_C|GPIO_CFG_PIN_4) +#define GPIO_ENET_RMII_RXD1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_C|GPIO_CFG_PIN_5) +#define GPIO_ENET_RMII_TXD0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_B|GPIO_CFG_PIN_12) +#define GPIO_ENET_RMII_TXD0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_G|GPIO_CFG_PIN_13) +#define GPIO_ENET_RMII_TXD1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_B|GPIO_CFG_PIN_13) +#define GPIO_ENET_RMII_TXD1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_G|GPIO_CFG_PIN_14) +#define GPIO_ENET_RMII_TX_EN_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_B|GPIO_CFG_PIN_11) +#define GPIO_ENET_RMII_TX_EN_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_11|GPIO_CFG_PORT_G|GPIO_CFG_PIN_11) + +/* External memory controller (EXMC) */ + +#define GPIO_EXMC_A0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_0) +#define GPIO_EXMC_A1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_1) +#define GPIO_EXMC_A2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_2) +#define GPIO_EXMC_A3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_3) +#define GPIO_EXMC_A4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_4) +#define GPIO_EXMC_A5 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_5) +#define GPIO_EXMC_A6 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_12) +#define GPIO_EXMC_A7 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_13) +#define GPIO_EXMC_A8 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_14) +#define GPIO_EXMC_A9 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_15) +#define GPIO_EXMC_A10 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_0) +#define GPIO_EXMC_A11 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_1) +#define GPIO_EXMC_A12 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_2) +#define GPIO_EXMC_A13 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_3) +#define GPIO_EXMC_A14 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_4) +#define GPIO_EXMC_A15 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_5) +#define GPIO_EXMC_A16 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_11) +#define GPIO_EXMC_A17 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_12) +#define GPIO_EXMC_A18 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_13) +#define GPIO_EXMC_A19 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_3) +#define GPIO_EXMC_A20 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_4) +#define GPIO_EXMC_A21 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_5) +#define GPIO_EXMC_A22 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_6) +#define GPIO_EXMC_A23 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_2) +#define GPIO_EXMC_A24 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_13) +#define GPIO_EXMC_A25 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_14) +#define GPIO_EXMC_CLK (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_3) +#define GPIO_EXMC_CD (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_9) +#define GPIO_EXMC_D0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_14) +#define GPIO_EXMC_D1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_15) +#define GPIO_EXMC_D2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_0) +#define GPIO_EXMC_D3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_1) +#define GPIO_EXMC_D4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_7) +#define GPIO_EXMC_D5 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_8) +#define GPIO_EXMC_D6 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_9) +#define GPIO_EXMC_D7 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_10) +#define GPIO_EXMC_D8 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_11) +#define GPIO_EXMC_D9 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_12) +#define GPIO_EXMC_D10 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_13) +#define GPIO_EXMC_D11 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_14) +#define GPIO_EXMC_D12 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_15) +#define GPIO_EXMC_D13 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_8) +#define GPIO_EXMC_D14 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_9) +#define GPIO_EXMC_D15 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_10) +#define GPIO_EXMC_D16 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_8) +#define GPIO_EXMC_D17 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_9) +#define GPIO_EXMC_D18 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_10) +#define GPIO_EXMC_D19 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_11) +#define GPIO_EXMC_D20 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_12) +#define GPIO_EXMC_D21 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_13) +#define GPIO_EXMC_D22 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_14) +#define GPIO_EXMC_D23 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_15) +#define GPIO_EXMC_D24 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_I|GPIO_CFG_PIN_0) +#define GPIO_EXMC_D25 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_I|GPIO_CFG_PIN_1) +#define GPIO_EXMC_D26 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_I|GPIO_CFG_PIN_2) +#define GPIO_EXMC_D27 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_I|GPIO_CFG_PIN_3) +#define GPIO_EXMC_D28 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_I|GPIO_CFG_PIN_6) +#define GPIO_EXMC_D29 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_I|GPIO_CFG_PIN_7) +#define GPIO_EXMC_D30 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_I|GPIO_CFG_PIN_9) +#define GPIO_EXMC_D31 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_I|GPIO_CFG_PIN_10) +#define GPIO_EXMC_INT1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_6) +#define GPIO_EXMC_INT2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_7) +#define GPIO_EXMC_INTR (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_10) +#define GPIO_EXMC_NBL0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_0) +#define GPIO_EXMC_NBL1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_E|GPIO_CFG_PIN_1) +#define GPIO_EXMC_NBL2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_I|GPIO_CFG_PIN_4) +#define GPIO_EXMC_NBL3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_I|GPIO_CFG_PIN_5) +#define GPIO_EXMC_NCE1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_7) +#define GPIO_EXMC_NCE2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_9) +#define GPIO_EXMC_NCE3_0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_10) +#define GPIO_EXMC_NCE3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_11) +#define GPIO_EXMC_NE0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_7) +#define GPIO_EXMC_NE1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_9) +#define GPIO_EXMC_NE2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_10) +#define GPIO_EXMC_NE3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_12) +#define GPIO_EXMC_NL (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_7) +#define GPIO_EXMC_NIORD (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_6) +#define GPIO_EXMC_NIOWR (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_8) +#define GPIO_EXMC_NOE (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_4) +#define GPIO_EXMC_NREG (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_7) +#define GPIO_EXMC_NWE (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_5) +#define GPIO_EXMC_NWAIT (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_6) +#define GPIO_EXMC_SDCKE0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_3) +#define GPIO_EXMC_SDCKE0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_5) +#define GPIO_EXMC_SDCKE0_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_2) +#define GPIO_EXMC_SDCKE1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_5) +#define GPIO_EXMC_SDCKE1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_7) +#define GPIO_EXMC_SDCLK (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_8) +#define GPIO_EXMC_SDNCAS (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_G|GPIO_CFG_PIN_15) +#define GPIO_EXMC_SDNE0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_2) +#define GPIO_EXMC_SDNE0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_4) +#define GPIO_EXMC_SDNE0_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_3) +#define GPIO_EXMC_SDNE1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_6) +#define GPIO_EXMC_SDNE1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_6) +#define GPIO_EXMC_SDNRAS (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_F|GPIO_CFG_PIN_11) +#define GPIO_EXMC_SDNWE_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_A|GPIO_CFG_PIN_7) +#define GPIO_EXMC_SDNWE_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_0) +#define GPIO_EXMC_SDNWE_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_H|GPIO_CFG_PIN_5) + +/* Inter-integrated circuit interface (I2C) */ + +#define GPIO_I2C0_SCL_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_B|GPIO_CFG_PIN_6) +#define GPIO_I2C0_SCL_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_B|GPIO_CFG_PIN_8) +#define GPIO_I2C0_SDA_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_B|GPIO_CFG_PIN_7) +#define GPIO_I2C0_SDA_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_B|GPIO_CFG_PIN_9) +#define GPIO_I2C0_SMBA (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_B|GPIO_CFG_PIN_5) +#define GPIO_I2C0_TXFRAME (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_B|GPIO_CFG_PIN_4) + +#define GPIO_I2C1_SCL_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_B|GPIO_CFG_PIN_10) +#define GPIO_I2C1_SCL_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_F|GPIO_CFG_PIN_1) +#define GPIO_I2C1_SCL_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_H|GPIO_CFG_PIN_4) +#define GPIO_I2C1_SDA_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_3) +#define GPIO_I2C1_SDA_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_B|GPIO_CFG_PIN_11) +#define GPIO_I2C1_SDA_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_C|GPIO_CFG_PIN_12) +#define GPIO_I2C1_SDA_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_F|GPIO_CFG_PIN_0) +#define GPIO_I2C1_SDA_5 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_H|GPIO_CFG_PIN_5) +#define GPIO_I2C1_SMBA_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_B|GPIO_CFG_PIN_12) +#define GPIO_I2C1_SMBA_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_F|GPIO_CFG_PIN_2) +#define GPIO_I2C1_SMBA_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_H|GPIO_CFG_PIN_6) +#define GPIO_I2C1_TXFRAME_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_B|GPIO_CFG_PIN_13) +#define GPIO_I2C1_TXFRAME_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_F|GPIO_CFG_PIN_3) +#define GPIO_I2C1_TXFRAME_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_H|GPIO_CFG_PIN_3) + +#define GPIO_I2C2_SCL_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_A|GPIO_CFG_PIN_8) +#define GPIO_I2C2_SCL_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_H|GPIO_CFG_PIN_7) +#define GPIO_I2C2_SDA_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_4) +#define GPIO_I2C2_SDA_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_C|GPIO_CFG_PIN_9) +#define GPIO_I2C2_SDA_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_H|GPIO_CFG_PIN_8) +#define GPIO_I2C2_SMBA_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_A|GPIO_CFG_PIN_9) +#define GPIO_I2C2_SMBA_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_H|GPIO_CFG_PIN_9) +#define GPIO_I2C2_TXFRAME_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_A|GPIO_CFG_PIN_10) +#define GPIO_I2C2_TXFRAME_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_4|GPIO_CFG_PORT_H|GPIO_CFG_PIN_10) + +/* JTAG, SWD */ + +#define GPIO_JTCK (GPIO_CFG_MODE_AF|GPIO_CFG_AF_0|GPIO_CFG_PORT_A|GPIO_CFG_PIN_14) +#define GPIO_JTDI (GPIO_CFG_MODE_AF|GPIO_CFG_AF_0|GPIO_CFG_PORT_A|GPIO_CFG_PIN_15) +#define GPIO_JTDO (GPIO_CFG_MODE_AF|GPIO_CFG_AF_0|GPIO_CFG_PORT_B|GPIO_CFG_PIN_3) +#define GPIO_JTMS (GPIO_CFG_MODE_AF|GPIO_CFG_AF_0|GPIO_CFG_PORT_A|GPIO_CFG_PIN_13) +#define GPIO_NJTRST (GPIO_CFG_MODE_AF|GPIO_CFG_AF_0|GPIO_CFG_PORT_B|GPIO_CFG_PIN_4) + +#define GPIO_SWCLK (GPIO_CFG_MODE_AF|GPIO_CFG_AF_0|GPIO_CFG_PORT_A|GPIO_CFG_PIN_14) +#define GPIO_SSWDIO (GPIO_CFG_MODE_AF|GPIO_CFG_AF_0|GPIO_CFG_PORT_A|GPIO_CFG_PIN_13) + +/* RTC */ + +#define GPIO_RTC_REFIN (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_0|GPIO_CFG_PORT_C|GPIO_CFG_PIN_15) + +/* Secure digital input/output interface (SDIO) */ + +#define GPIO_SDIO_CMD_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_A|GPIO_CFG_PIN_6) +#define GPIO_SDIO_CMD_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_D|GPIO_CFG_PIN_2) +#define GPIO_SDIO_CK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_2) +#define GPIO_SDIO_CK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_12) +#define GPIO_SDIO_D0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_4) +#define GPIO_SDIO_D0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_8) +#define GPIO_SDIO_D1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_A|GPIO_CFG_PIN_8) +#define GPIO_SDIO_D1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_SDIO_D1_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_9) +#define GPIO_SDIO_D2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_A|GPIO_CFG_PIN_9) +#define GPIO_SDIO_D2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_1) +#define GPIO_SDIO_D2_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_10) +#define GPIO_SDIO_D3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_11) +#define GPIO_SDIO_D4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_8) +#define GPIO_SDIO_D5 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_9) +#define GPIO_SDIO_D6 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_6) +#define GPIO_SDIO_D7 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_C|GPIO_CFG_PIN_7) + +/* Serial peripheral interface/Inter-IC sound (SPI/I2S) */ + +/* I2S */ + +#define GPIO_I2S1_ADD_SD_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_14) +#define GPIO_I2S1_ADD_SD_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_C|GPIO_CFG_PIN_2) +#define GPIO_I2S1_ADD_SD_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_I|GPIO_CFG_PIN_2) +#define GPIO_I2S1_CK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_A|GPIO_CFG_PIN_9) +#define GPIO_I2S1_CK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_10) +#define GPIO_I2S1_CK_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_13) +#define GPIO_I2S1_CK_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_C|GPIO_CFG_PIN_7) +#define GPIO_I2S1_CK_5 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_D|GPIO_CFG_PIN_3) +#define GPIO_I2S1_CK_6 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_I|GPIO_CFG_PIN_1) +#define GPIO_I2S1_MCK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_A|GPIO_CFG_PIN_3) +#define GPIO_I2S1_MCK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_A|GPIO_CFG_PIN_6) +#define GPIO_I2S1_MCK_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_C|GPIO_CFG_PIN_6) +#define GPIO_I2S1_SD_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_15) +#define GPIO_I2S1_SD_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_C|GPIO_CFG_PIN_1) +#define GPIO_I2S1_SD_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_C|GPIO_CFG_PIN_3) +#define GPIO_I2S1_SD_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_I|GPIO_CFG_PIN_3) +#define GPIO_I2S1_WS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_9) +#define GPIO_I2S1_WS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_12) +#define GPIO_I2S1_WS_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_1) +#define GPIO_I2S1_WS_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_I|GPIO_CFG_PIN_0) + +#define GPIO_I2S2_ADD_SD_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_4) +#define GPIO_I2S2_ADD_SD_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_C|GPIO_CFG_PIN_11) +#define GPIO_I2S2_CK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_3) +#define GPIO_I2S2_CK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_C|GPIO_CFG_PIN_10) +#define GPIO_I2S2_MCK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_10) +#define GPIO_I2S2_MCK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_C|GPIO_CFG_PIN_7) +#define GPIO_I2S2_SD_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_I2S2_SD_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_2) +#define GPIO_I2S2_SD_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_5) +#define GPIO_I2S2_SD_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_C|GPIO_CFG_PIN_1) +#define GPIO_I2S2_SD_5 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_C|GPIO_CFG_PIN_12) +#define GPIO_I2S2_SD_6 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_D|GPIO_CFG_PIN_0) +#define GPIO_I2S2_SD_7 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_D|GPIO_CFG_PIN_6) +#define GPIO_I2S2_WS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_A|GPIO_CFG_PIN_4) +#define GPIO_I2S2_WS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_A|GPIO_CFG_PIN_15) + +#define GPIO_I2S_CKIN_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_A|GPIO_CFG_PIN_2) +#define GPIO_I2S_CKIN_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_11) +#define GPIO_I2S_CKIN_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_25MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_C|GPIO_CFG_PIN_9) + +/* SPI */ +#define GPIO_SPI0_MISO_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_A|GPIO_CFG_PIN_6) +#define GPIO_SPI0_MISO_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_4) +#define GPIO_SPI0_MOSI_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_A|GPIO_CFG_PIN_7) +#define GPIO_SPI0_MOSI_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_5) +#define GPIO_SPI0_NSS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_A|GPIO_CFG_PIN_4) +#define GPIO_SPI0_NSS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_A|GPIO_CFG_PIN_15) +#define GPIO_SPI0_SCK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_A|GPIO_CFG_PIN_5) +#define GPIO_SPI0_SCK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_3) + +#define GPIO_SPI1_MISO_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_14) +#define GPIO_SPI1_MISO_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_C|GPIO_CFG_PIN_2) +#define GPIO_SPI1_MISO_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_I|GPIO_CFG_PIN_2) +#define GPIO_SPI1_MOSI_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_15) +#define GPIO_SPI1_MOSI_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_C|GPIO_CFG_PIN_1) +#define GPIO_SPI1_MOSI_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_C|GPIO_CFG_PIN_3) +#define GPIO_SPI1_MOSI_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_I|GPIO_CFG_PIN_3) +#define GPIO_SPI1_NSS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_9) +#define GPIO_SPI1_NSS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_12) +#define GPIO_SPI1_NSS_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_1) +#define GPIO_SPI1_NSS_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_I|GPIO_CFG_PIN_0) +#define GPIO_SPI1_SCK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_A|GPIO_CFG_PIN_9) +#define GPIO_SPI1_SCK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_10) +#define GPIO_SPI1_SCK_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_B|GPIO_CFG_PIN_13) +#define GPIO_SPI1_SCK_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_C|GPIO_CFG_PIN_7) +#define GPIO_SPI1_SCK_5 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_D|GPIO_CFG_PIN_3) +#define GPIO_SPI1_SCK_6 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_I|GPIO_CFG_PIN_1) + +#define GPIO_SPI2_MISO_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_4) +#define GPIO_SPI2_MISO_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_C|GPIO_CFG_PIN_11) +#define GPIO_SPI2_MOSI_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_SPI2_MOSI_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_2) +#define GPIO_SPI2_MOSI_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_5) +#define GPIO_SPI2_MOSI_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_C|GPIO_CFG_PIN_1) +#define GPIO_SPI2_MOSI_5 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_C|GPIO_CFG_PIN_12) +#define GPIO_SPI2_MOSI_6 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_D|GPIO_CFG_PIN_0) +#define GPIO_SPI2_MOSI_7 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_D|GPIO_CFG_PIN_6) +#define GPIO_SPI2_NSS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_A|GPIO_CFG_PIN_4) +#define GPIO_SPI2_NSS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_A|GPIO_CFG_PIN_15) +#define GPIO_SPI2_SCK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_3) +#define GPIO_SPI2_SCK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_C|GPIO_CFG_PIN_10) + +#define GPIO_SPI3_MISO_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_A|GPIO_CFG_PIN_11) +#define GPIO_SPI3_MISO_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_D|GPIO_CFG_PIN_0) +#define GPIO_SPI3_MISO_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_E|GPIO_CFG_PIN_5) +#define GPIO_SPI3_MISO_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_E|GPIO_CFG_PIN_13) +#define GPIO_SPI3_MISO_5 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_G|GPIO_CFG_PIN_12) +#define GPIO_SPI3_MOSI_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_A|GPIO_CFG_PIN_1) +#define GPIO_SPI3_MOSI_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_E|GPIO_CFG_PIN_6) +#define GPIO_SPI3_MOSI_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_E|GPIO_CFG_PIN_14) +#define GPIO_SPI3_MOSI_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_G|GPIO_CFG_PIN_13) +#define GPIO_SPI3_NSS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_12) +#define GPIO_SPI3_NSS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_E|GPIO_CFG_PIN_4) +#define GPIO_SPI3_NSS_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_E|GPIO_CFG_PIN_11) +#define GPIO_SPI3_NSS_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_G|GPIO_CFG_PIN_14) +#define GPIO_SPI3_SCK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_13) +#define GPIO_SPI3_SCK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_E|GPIO_CFG_PIN_2) +#define GPIO_SPI3_SCK_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_E|GPIO_CFG_PIN_12) +#define GPIO_SPI3_SCK_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_G|GPIO_CFG_PIN_11) + +#define GPIO_SPI4_MISO_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_A|GPIO_CFG_PIN_12) +#define GPIO_SPI4_MISO_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_E|GPIO_CFG_PIN_13) +#define GPIO_SPI4_MISO_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_F|GPIO_CFG_PIN_8) +#define GPIO_SPI4_MISO_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_H|GPIO_CFG_PIN_7) +#define GPIO_SPI4_MOSI_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_A|GPIO_CFG_PIN_10) +#define GPIO_SPI4_MOSI_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_8) +#define GPIO_SPI4_MOSI_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_E|GPIO_CFG_PIN_14) +#define GPIO_SPI4_MOSI_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_F|GPIO_CFG_PIN_9) +#define GPIO_SPI4_MOSI_5 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_F|GPIO_CFG_PIN_11) +#define GPIO_SPI4_NSS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_1) +#define GPIO_SPI4_NSS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_E|GPIO_CFG_PIN_11) +#define GPIO_SPI4_NSS_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_F|GPIO_CFG_PIN_6) +#define GPIO_SPI4_NSS_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_H|GPIO_CFG_PIN_5) +#define GPIO_SPI4_SCK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_SPI4_SCK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_6|GPIO_CFG_PORT_E|GPIO_CFG_PIN_12) +#define GPIO_SPI4_SCK_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_F|GPIO_CFG_PIN_7) +#define GPIO_SPI4_SCK_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_H|GPIO_CFG_PIN_6) + +#define GPIO_SPI5_MISO (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_G|GPIO_CFG_PIN_12) +#define GPIO_SPI5_MOSI (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_G|GPIO_CFG_PIN_14) +#define GPIO_SPI5_IO2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_G|GPIO_CFG_PIN_10) +#define GPIO_SPI5_IO3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_G|GPIO_CFG_PIN_11) +#define GPIO_SPI5_NSS (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_G|GPIO_CFG_PIN_8) +#define GPIO_SPI5_SCK (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_5|GPIO_CFG_PORT_G|GPIO_CFG_PIN_13) + +/* TFT-LCD interface (TLI) */ + +#define GPIO_TLI_B0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_E|GPIO_CFG_PIN_4) +#define GPIO_TLI_B1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_G|GPIO_CFG_PIN_12) +#define GPIO_TLI_B2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_D|GPIO_CFG_PIN_6) +#define GPIO_TLI_B2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_G|GPIO_CFG_PIN_10) +#define GPIO_TLI_B3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_D|GPIO_CFG_PIN_10) +#define GPIO_TLI_B3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_G|GPIO_CFG_PIN_11) +#define GPIO_TLI_B4_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_E|GPIO_CFG_PIN_12) +#define GPIO_TLI_B4_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_G|GPIO_CFG_PIN_12) +#define GPIO_TLI_B4_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_I|GPIO_CFG_PIN_4) +#define GPIO_TLI_B5_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_A|GPIO_CFG_PIN_3) +#define GPIO_TLI_B5_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_I|GPIO_CFG_PIN_5) +#define GPIO_TLI_B6_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_B|GPIO_CFG_PIN_8) +#define GPIO_TLI_B6_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_I|GPIO_CFG_PIN_6) +#define GPIO_TLI_B7_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_B|GPIO_CFG_PIN_9) +#define GPIO_TLI_B7_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_I|GPIO_CFG_PIN_7) + +#define GPIO_TLI_G0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_E|GPIO_CFG_PIN_5) +#define GPIO_TLI_G1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_E|GPIO_CFG_PIN_6) +#define GPIO_TLI_G2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_A|GPIO_CFG_PIN_6) +#define GPIO_TLI_G2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_H|GPIO_CFG_PIN_13) +#define GPIO_TLI_G3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_E|GPIO_CFG_PIN_11) +#define GPIO_TLI_G3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_G|GPIO_CFG_PIN_10) +#define GPIO_TLI_G3_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_PORTH|GPIO_CFG_PIN_14) +#define GPIO_TLI_G4_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_B|GPIO_CFG_PIN_10) +#define GPIO_TLI_G4_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_H|GPIO_CFG_PIN_15) +#define GPIO_TLI_G5_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_B|GPIO_CFG_PIN_11) +#define GPIO_TLI_G5_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_I|GPIO_CFG_PIN_0) +#define GPIO_TLI_G6_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_C|GPIO_CFG_PIN_7) +#define GPIO_TLI_G6_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_I|GPIO_CFG_PIN_1) +#define GPIO_TLI_G7_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_D|GPIO_CFG_PIN_3) +#define GPIO_TLI_G7_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_I|GPIO_CFG_PIN_2) + +#define GPIO_TLI_R0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_H|GPIO_CFG_PIN_2) +#define GPIO_TLI_R1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_H|GPIO_CFG_PIN_3) +#define GPIO_TLI_R2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_C|GPIO_CFG_PIN_10) +#define GPIO_TLI_R2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_H|GPIO_CFG_PIN_8) +#define GPIO_TLI_R3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_TLI_R3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_H|GPIO_CFG_PIN_9) +#define GPIO_TLI_R4_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_A|GPIO_CFG_PIN_11) +#define GPIO_TLI_R4_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_H|GPIO_CFG_PIN_10) +#define GPIO_TLI_R5_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_A|GPIO_CFG_PIN_12) +#define GPIO_TLI_R5_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_H|GPIO_CFG_PIN_11) +#define GPIO_TLI_R6_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_A|GPIO_CFG_PIN_8) +#define GPIO_TLI_R6_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_1) +#define GPIO_TLI_R6_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_H|GPIO_CFG_PIN_12) +#define GPIO_TLI_R7_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_E|GPIO_CFG_PIN_15) +#define GPIO_TLI_R7_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_G|GPIO_CFG_PIN_6) + +#define GPIO_TLI_VSYNC_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_A|GPIO_CFG_PIN_4) +#define GPIO_TLI_VSYNC_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_I|GPIO_CFG_PIN_9) + +#define GPIO_TLI_HSYNC_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_C|GPIO_CFG_PIN_6) +#define GPIO_TLI_HSYNC_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_I|GPIO_CFG_PIN_10) + +#define GPIO_TLI_DE_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_E|GPIO_CFG_PIN_13) +#define GPIO_TLI_DE_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_F|GPIO_CFG_PIN_10) + +#define GPIO_TLI_PIXCLK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_E|GPIO_CFG_PIN_14) +#define GPIO_TLI_PIXCLK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_14|GPIO_CFG_PORT_G|GPIO_CFG_PIN_7) + +/* TIMER */ + +/* Advanced timer (TIMERx, x=0, 7) */ + +#define GPIO_TIMER0_BRKIN_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_6) +#define GPIO_TIMER0_BRKIN_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_12) +#define GPIO_TIMER0_BRKIN_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_E|GPIO_CFG_PIN_15) +#define GPIO_TIMER0_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_8) +#define GPIO_TIMER0_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_E|GPIO_CFG_PIN_9) +#define GPIO_TIMER0_CH0_ON_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_7) +#define GPIO_TIMER0_CH0_ON_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_13) +#define GPIO_TIMER0_CH0_ON_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_E|GPIO_CFG_PIN_8) +#define GPIO_TIMER0_CH1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_9) +#define GPIO_TIMER0_CH1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_E|GPIO_CFG_PIN_11) +#define GPIO_TIMER0_CH1_ON_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_TIMER0_CH1_ON_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_14) +#define GPIO_TIMER0_CH1_ON_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_E|GPIO_CFG_PIN_1) +#define GPIO_TIMER0_CH1_ON_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_E|GPIO_CFG_PIN_10) +#define GPIO_TIMER0_CH2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_10) +#define GPIO_TIMER0_CH2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_E|GPIO_CFG_PIN_13) +#define GPIO_TIMER0_CH2_ON_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_1) +#define GPIO_TIMER0_CH2_ON_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_15) +#define GPIO_TIMER0_CH2_ON_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_E|GPIO_CFG_PIN_12) +#define GPIO_TIMER0_CH3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_11) +#define GPIO_TIMER0_CH3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_E|GPIO_CFG_PIN_14) +#define GPIO_TIMER0_ETI_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_12) +#define GPIO_TIMER0_ETI_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_E|GPIO_CFG_PIN_7) + +#define GPIO_TIMER7_BRKIN_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_A|GPIO_CFG_PIN_6) +#define GPIO_TIMER7_BRKIN_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_I|GPIO_CFG_PIN_4) +#define GPIO_TIMER7_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_C|GPIO_CFG_PIN_6) +#define GPIO_TIMER7_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_I|GPIO_CFG_PIN_5) +#define GPIO_TIMER7_CH0_ON_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_A|GPIO_CFG_PIN_5) +#define GPIO_TIMER7_CH0_ON_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_A|GPIO_CFG_PIN_7) +#define GPIO_TIMER7_CH0_ON_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_H|GPIO_CFG_PIN_13) +#define GPIO_TIMER7_CH1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_C|GPIO_CFG_PIN_7) +#define GPIO_TIMER7_CH1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_I|GPIO_CFG_PIN_6) +#define GPIO_TIMER7_CH1_ON_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_TIMER7_CH1_ON_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_B|GPIO_CFG_PIN_14) +#define GPIO_TIMER7_CH1_ON_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_H|GPIO_CFG_PIN_14) +#define GPIO_TIMER7_CH2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_C|GPIO_CFG_PIN_8) +#define GPIO_TIMER7_CH2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_I|GPIO_CFG_PIN_7) +#define GPIO_TIMER7_CH2_ON_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_B|GPIO_CFG_PIN_1) +#define GPIO_TIMER7_CH2_ON_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_B|GPIO_CFG_PIN_15) +#define GPIO_TIMER7_CH2_ON_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_H|GPIO_CFG_PIN_15) +#define GPIO_TIMER7_CH3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_C|GPIO_CFG_PIN_9) +#define GPIO_TIMER7_CH3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_I|GPIO_CFG_PIN_2) +#define GPIO_TIMER7_ETI1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_A|GPIO_CFG_PIN_0) +#define GPIO_TIMER7_ETI_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_I|GPIO_CFG_PIN_3) + +/* General level0 timer (TIMERx, x=1, 2, 3, 4) */ + +#define GPIO_TIMER1_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_0) +#define GPIO_TIMER1_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_5) +#define GPIO_TIMER1_CH0_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_15) +#define GPIO_TIMER1_CH0_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_8) +#define GPIO_TIMER1_CH1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_1) +#define GPIO_TIMER1_CH1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_3) +#define GPIO_TIMER1_CH1_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_9) +#define GPIO_TIMER1_CH2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_2) +#define GPIO_TIMER1_CH2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_10) +#define GPIO_TIMER1_CH3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_3) +#define GPIO_TIMER1_CH3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_2) +#define GPIO_TIMER1_CH3_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_11) +#define GPIO_TIMER1_ETI_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_0) +#define GPIO_TIMER1_ETI_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_5) +#define GPIO_TIMER1_ETI_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_A|GPIO_CFG_PIN_15) +#define GPIO_TIMER1_ETI_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_1|GPIO_CFG_PORT_B|GPIO_CFG_PIN_8) + +#define GPIO_TIMER2_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_A|GPIO_CFG_PIN_6) +#define GPIO_TIMER2_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_B|GPIO_CFG_PIN_4) +#define GPIO_TIMER2_CH0_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_C|GPIO_CFG_PIN_6) +#define GPIO_TIMER2_CH1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_A|GPIO_CFG_PIN_7) +#define GPIO_TIMER2_CH1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_B|GPIO_CFG_PIN_5) +#define GPIO_TIMER2_CH1_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_C|GPIO_CFG_PIN_7) +#define GPIO_TIMER2_CH2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_TIMER2_CH2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_C|GPIO_CFG_PIN_8) +#define GPIO_TIMER2_CH3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_B|GPIO_CFG_PIN_1) +#define GPIO_TIMER2_CH3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_C|GPIO_CFG_PIN_9) +#define GPIO_TIMER2_ETI (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_D|GPIO_CFG_PIN_2) + +#define GPIO_TIMER3_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_B|GPIO_CFG_PIN_6) +#define GPIO_TIMER3_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_D|GPIO_CFG_PIN_12) +#define GPIO_TIMER3_CH1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_B|GPIO_CFG_PIN_7) +#define GPIO_TIMER3_CH1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_D|GPIO_CFG_PIN_13) +#define GPIO_TIMER3_CH2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_B|GPIO_CFG_PIN_8) +#define GPIO_TIMER3_CH2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_D|GPIO_CFG_PIN_14) +#define GPIO_TIMER3_CH3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_B|GPIO_CFG_PIN_9) +#define GPIO_TIMER3_CH3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_D|GPIO_CFG_PIN_15) +#define GPIO_TIMER3_ETI (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_E|GPIO_CFG_PIN_0) + +#define GPIO_TIMER4_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_A|GPIO_CFG_PIN_0) +#define GPIO_TIMER4_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_H|GPIO_CFG_PIN_10) +#define GPIO_TIMER4_CH1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_A|GPIO_CFG_PIN_1) +#define GPIO_TIMER4_CH1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_H|GPIO_CFG_PIN_11) +#define GPIO_TIMER4_CH2_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_A|GPIO_CFG_PIN_2) +#define GPIO_TIMER4_CH2_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_H|GPIO_CFG_PIN_12) +#define GPIO_TIMER4_CH3_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_A|GPIO_CFG_PIN_3) +#define GPIO_TIMER4_CH3_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_2|GPIO_CFG_PORT_I|GPIO_CFG_PIN_0) + +/* General level1 timer (TIMERx, x=8, 11) */ +#define GPIO_TIMER8_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_A|GPIO_CFG_PIN_2) +#define GPIO_TIMER8_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_E|GPIO_CFG_PIN_5) +#define GPIO_TIMER8_CH1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_A|GPIO_CFG_PIN_3) +#define GPIO_TIMER8_CH1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_E|GPIO_CFG_PIN_6) + +#define GPIO_TIMER11_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_14) +#define GPIO_TIMER11_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_H|GPIO_CFG_PIN_6) +#define GPIO_TIMER11_CH1_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_B|GPIO_CFG_PIN_15) +#define GPIO_TIMER11_CH1_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_H|GPIO_CFG_PIN_9) + +/* General level2 timer (TIMERx, x=9, 10, 12, 13) */ + +#define GPIO_TIMER9_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_B|GPIO_CFG_PIN_8) +#define GPIO_TIMER9_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_F|GPIO_CFG_PIN_6) + +#define GPIO_TIMER10_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_B|GPIO_CFG_PIN_9) +#define GPIO_TIMER10_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_3|GPIO_CFG_PORT_F|GPIO_CFG_PIN_7) + +#define GPIO_TIMER12_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_A|GPIO_CFG_PIN_6) +#define GPIO_TIMER12_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_F|GPIO_CFG_PIN_8) + +#define GPIO_TIMER13_CH0_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_A|GPIO_CFG_PIN_7) +#define GPIO_TIMER13_CH0_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_9|GPIO_CFG_PORT_F|GPIO_CFG_PIN_9) + +/* Instrumentation Trace Macrocell (ITM) */ +#define GPIO_TRACECK (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_0|GPIO_CFG_PORT_E|GPIO_CFG_PIN_2) +#define GPIO_TRACESWO (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_0|GPIO_CFG_PORT_B|GPIO_CFG_PIN_3) + +/* Universal synchronous/asynchronous receiver /transmitter (USART/UART) */ + +/* USART */ + +#define GPIO_USART0_CK (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_A|GPIO_CFG_PIN_8) +#define GPIO_USART0_CTS (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_A|GPIO_CFG_PIN_11) +#define GPIO_USART0_RTS (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_A|GPIO_CFG_PIN_12) +#define GPIO_USART0_RX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_A|GPIO_CFG_PIN_10) +#define GPIO_USART0_RX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_3) +#define GPIO_USART0_RX_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_7) +#define GPIO_USART0_TX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_A|GPIO_CFG_PIN_9) +#define GPIO_USART0_TX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_A|GPIO_CFG_PIN_15) +#define GPIO_USART0_TX_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_6) + +#define GPIO_USART1_CK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_A|GPIO_CFG_PIN_4) +#define GPIO_USART1_CK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_7) +#define GPIO_USART1_CTS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_A|GPIO_CFG_PIN_0) +#define GPIO_USART1_CTS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_3) +#define GPIO_USART1_RTS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_A|GPIO_CFG_PIN_1) +#define GPIO_USART1_RTS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_4) +#define GPIO_USART1_RX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_A|GPIO_CFG_PIN_3) +#define GPIO_USART1_RX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_6) +#define GPIO_USART1_TX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_A|GPIO_CFG_PIN_2) +#define GPIO_USART1_TX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_5) + +#define GPIO_USART2_CK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_12) +#define GPIO_USART2_CK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_C|GPIO_CFG_PIN_12) +#define GPIO_USART2_CK_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_10) +#define GPIO_USART2_CTS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_13) +#define GPIO_USART2_CTS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_11) +#define GPIO_USART2_RTS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_14) +#define GPIO_USART2_RTS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_12) +#define GPIO_USART2_RX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_11) +#define GPIO_USART2_RX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_C|GPIO_CFG_PIN_5) +#define GPIO_USART2_RX_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_C|GPIO_CFG_PIN_11) +#define GPIO_USART2_RX_4 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_9) +#define GPIO_USART2_TX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_B|GPIO_CFG_PIN_10) +#define GPIO_USART2_TX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_C|GPIO_CFG_PIN_10) +#define GPIO_USART2_TX_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_7|GPIO_CFG_PORT_D|GPIO_CFG_PIN_8) + +#define GPIO_USART5_CK_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_C|GPIO_CFG_PIN_8) +#define GPIO_USART5_CK_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_G|GPIO_CFG_PIN_7) +#define GPIO_USART5_CTS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_G|GPIO_CFG_PIN_13) +#define GPIO_USART5_CTS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_G|GPIO_CFG_PIN_15) +#define GPIO_USART5_RTS_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_G|GPIO_CFG_PIN_8) +#define GPIO_USART5_RTS_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_G|GPIO_CFG_PIN_12) +#define GPIO_USART5_RX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_A|GPIO_CFG_PIN_12) +#define GPIO_USART5_RX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_C|GPIO_CFG_PIN_7) +#define GPIO_USART5_RX_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_G|GPIO_CFG_PIN_9) +#define GPIO_USART5_TX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_A|GPIO_CFG_PIN_11) +#define GPIO_USART5_TX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_C|GPIO_CFG_PIN_6) +#define GPIO_USART5_TX_3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_G|GPIO_CFG_PIN_14) + +/* UART */ + +#define GPIO_UART3_RX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_A|GPIO_CFG_PIN_1) +#define GPIO_UART3_RX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_C|GPIO_CFG_PIN_11) +#define GPIO_UART3_TX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_A|GPIO_CFG_PIN_0) +#define GPIO_UART3_TX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_C|GPIO_CFG_PIN_10) + +#define GPIO_UART4_RX (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_D|GPIO_CFG_PIN_2) +#define GPIO_UART4_TX (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_C|GPIO_CFG_PIN_12) + +#define GPIO_UART6_RX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_E|GPIO_CFG_PIN_7) +#define GPIO_UART6_RX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_F|GPIO_CFG_PIN_6) +#define GPIO_UART6_TX_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_E|GPIO_CFG_PIN_8) +#define GPIO_UART6_TX_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_F|GPIO_CFG_PIN_7) + +#define GPIO_UART7_RX (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_E|GPIO_CFG_PIN_0) +#define GPIO_UART7_TX (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_PP|GPIO_CFG_SPEED_50MHZ|GPIO_CFG_AF_8|GPIO_CFG_PORT_E|GPIO_CFG_PIN_1) + +/* Universal serial bus full-speed interface (USBFS) */ + +#define GPIO_USBFS_DM (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_A|GPIO_CFG_PIN_11) +#define GPIO_USBFS_DP (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_A|GPIO_CFG_PIN_12) +#define GPIO_USBFS_ID (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_A|GPIO_CFG_PIN_10) +#define GPIO_USBFS_SOF (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_A|GPIO_CFG_PIN_8) + +/* Universal serial bus high-speed interface (USBHS) */ +#define GPIO_USBHS_DM (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_14) +#define GPIO_USBHS_DP (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_15) +#define GPIO_USBHS_ID (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_PULLUP|GPIO_CFG_OD|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_B|GPIO_CFG_PIN_12) +#define GPIO_USBHS_SOF (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_12|GPIO_CFG_PORT_A|GPIO_CFG_PIN_4) +#define GPIO_USBHS_ULPI_CK (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_A|GPIO_CFG_PIN_5) +#define GPIO_USBHS_ULPI_D0 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_A|GPIO_CFG_PIN_3) +#define GPIO_USBHS_ULPI_D1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_B|GPIO_CFG_PIN_0) +#define GPIO_USBHS_ULPI_D2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_B|GPIO_CFG_PIN_1) +#define GPIO_USBHS_ULPI_D3 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_B|GPIO_CFG_PIN_10) +#define GPIO_USBHS_ULPI_D4_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_B|GPIO_CFG_PIN_2) +#define GPIO_USBHS_ULPI_D4_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_B|GPIO_CFG_PIN_11) +#define GPIO_USBHS_ULPI_D5 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_B|GPIO_CFG_PIN_12) +#define GPIO_USBHS_ULPI_D6 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_B|GPIO_CFG_PIN_13) +#define GPIO_USBHS_ULPI_D7 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_B|GPIO_CFG_PIN_5) +#define GPIO_USBHS_ULPI_DIR_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_C|GPIO_CFG_PIN_2) +#define GPIO_USBHS_ULPI_DIR_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_I|GPIO_CFG_PIN_11) +#define GPIO_USBHS_ULPI_NXT_1 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_C|GPIO_CFG_PIN_3) +#define GPIO_USBHS_ULPI_NXT_2 (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_H|GPIO_CFG_PIN_4) +#define GPIO_USBHS_ULPI_STP (GPIO_CFG_MODE_AF|GPIO_CFG_PUPD_NONE|GPIO_CFG_PP|GPIO_CFG_SPEED_200MHZ|GPIO_CFG_AF_10|GPIO_CFG_PORT_C|GPIO_CFG_PIN_0) + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F450_PINMAP_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_dma.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_dma.h new file mode 100644 index 0000000000..78c2627feb --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_dma.h @@ -0,0 +1,480 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_dma.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_DMA_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_DMA_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* DMA definitions */ +#define GD32_DMA0_BASE (GD32_DMA_BASE+0x00000000) /* DMA0 base address */ +#define GD32_DMA1_BASE (GD32_DMA_BASE+0x00000400) /* DMA1 base address */ + +/* Register Offsets *********************************************************/ +#define GD32_DMA_INTF0_OFFSET 0x0000 /* DMA interrupt flag register 0 offset */ +#define GD32_DMA_INTF1_OFFSET 0x0004 /* DMA interrupt flag register 1 offset */ +#define GD32_DMA_INTC0_OFFSET 0x0008 /* DMA interrupt flag clear register 1 offset */ +#define GD32_DMA_INTC1_OFFSET 0x000C /* DMA interrupt flag clear register 1 offset */ + +#define GD32_DMA_CH0CTL_OFFSET 0x0010 /* DMA channel 0 control register offset */ +#define GD32_DMA_CH0CNT_OFFSET 0x0014 /* DMA channel 0 counter register offset */ +#define GD32_DMA_CH0PADDR_OFFSET 0x0018 /* DMA channel 0 peripheral base address register offset */ +#define GD32_DMA_CH0M0ADDR_OFFSET 0x001C /* DMA channel 0 memory 0 base address register offset */ +#define GD32_DMA_CH0M1ADDR_OFFSET 0x0020 /* DMA channel 0 memory 1 base address register offset */ +#define GD32_DMA_CH0FCTL_OFFSET 0x0024 /* DMA channel 0 FIFO control register offset */ + +#define GD32_DMA_CH1CTL_OFFSET 0x0028 /* DMA channel 1 control register offset */ +#define GD32_DMA_CH1CNT_OFFSET 0x002C /* DMA channel 1 counter register offset */ +#define GD32_DMA_CH1PADDR_OFFSET 0x0030 /* DMA channel 1 peripheral base address register offset */ +#define GD32_DMA_CH1M0ADDR_OFFSET 0x0034 /* DMA channel 1 memory 0 base address register offset */ +#define GD32_DMA_CH1M1ADDR_OFFSET 0x0038 /* DMA channel 1 memory 1 base address register offset */ +#define GD32_DMA_CH1FCTL_OFFSET 0x003C /* DMA channel 1 FIFO control register offset */ + +#define GD32_DMA_CH2CTL_OFFSET 0x0040 /* DMA channel 2 control register offset */ +#define GD32_DMA_CH2CNT_OFFSET 0x0044 /* DMA channel 2 counter register offset */ +#define GD32_DMA_CH2PADDR_OFFSET 0x0048 /* DMA channel 2 peripheral base address register offset */ +#define GD32_DMA_CH2M0ADDR_OFFSET 0x004C /* DMA channel 2 memory 0 base address register offset */ +#define GD32_DMA_CH2M1ADDR_OFFSET 0x0050 /* DMA channel 2 memory 1 base address register offset */ +#define GD32_DMA_CH2FCTL_OFFSET 0x0054 /* DMA channel 2 FIFO control register offset */ + +#define GD32_DMA_CH3CTL_OFFSET 0x0058 /* DMA channel 3 control register offset */ +#define GD32_DMA_CH3CNT_OFFSET 0x005C /* DMA channel 3 counter register offset */ +#define GD32_DMA_CH3PADDR_OFFSET 0x0060 /* DMA channel 3 peripheral base address register offset */ +#define GD32_DMA_CH3M0ADDR_OFFSET 0x0064 /* DMA channel 3 memory 0 base address register offset */ +#define GD32_DMA_CH3M1ADDR_OFFSET 0x0068 /* DMA channel 3 memory 1 base address register offset */ +#define GD32_DMA_CH3FCTL_OFFSET 0x006C /* DMA channel 3 FIFO control register offset */ + +#define GD32_DMA_CH4CTL_OFFSET 0x0070 /* DMA channel 4 control register offset */ +#define GD32_DMA_CH4CNT_OFFSET 0x0074 /* DMA channel 4 counter register offset */ +#define GD32_DMA_CH4PADDR_OFFSET 0x0078 /* DMA channel 4 peripheral base address register offset */ +#define GD32_DMA_CH4M0ADDR_OFFSET 0x007C /* DMA channel 4 memory 0 base address register offset */ +#define GD32_DMA_CH4M1ADDR_OFFSET 0x0080 /* DMA channel 4 memory 1 base address register offset */ +#define GD32_DMA_CH4FCTL_OFFSET 0x0084 /* DMA channel 4 FIFO control register offset */ + +#define GD32_DMA_CH5CTL_OFFSET 0x0088 /* DMA channel 5 control register offset */ +#define GD32_DMA_CH5CNT_OFFSET 0x008C /* DMA channel 5 counter register offset */ +#define GD32_DMA_CH5PADDR_OFFSET 0x0090 /* DMA channel 5 peripheral base address register offset */ +#define GD32_DMA_CH5M0ADDR_OFFSET 0x0094 /* DMA channel 5 memory 0 base address register offset */ +#define GD32_DMA_CH5M1ADDR_OFFSET 0x0098 /* DMA channel 5 memory 1 base address register offset */ +#define GD32_DMA_CH5FCTL_OFFSET 0x009C /* DMA channel 5 FIFO control register offset */ + +#define GD32_DMA_CH6CTL_OFFSET 0x00A0 /* DMA channel 6 control register offset */ +#define GD32_DMA_CH6CNT_OFFSET 0x00A4 /* DMA channel 6 counter register offset */ +#define GD32_DMA_CH6PADDR_OFFSET 0x00A8 /* DMA channel 6 peripheral base address register offset */ +#define GD32_DMA_CH6M0ADDR_OFFSET 0x00AC /* DMA channel 6 memory 0 base address register offset */ +#define GD32_DMA_CH6M1ADDR_OFFSET 0x00B0 /* DMA channel 6 memory 1 base address register offset */ +#define GD32_DMA_CH6FCTL_OFFSET 0x00B4 /* DMA channel 6 FIFO control register offset */ + +#define GD32_DMA_CH7CTL_OFFSET 0x00B8 /* DMA channel 7 control register offset */ +#define GD32_DMA_CH7CNT_OFFSET 0x00BC /* DMA channel 7 counter register offset */ +#define GD32_DMA_CH7PADDR_OFFSET 0x00C0 /* DMA channel 7 peripheral base address register offset */ +#define GD32_DMA_CH7M0ADDR_OFFSET 0x00C4 /* DMA channel 7 memory 0 base address register offset */ +#define GD32_DMA_CH7M1ADDR_OFFSET 0x00C8 /* DMA channel 7 memory 1 base address register offset */ +#define GD32_DMA_CH7FCTL_OFFSET 0x00CC /* DMA channel 7 FIFO control register offset */ + +/* Register Addresses *******************************************************/ + +#define GD32_DMA_INTF0(dmax) ((dmax)+GD32_DMA_INTF0_OFFSET) /* DMA interrupt flag register 0 */ +#define GD32_DMA_INTF1(dmax) ((dmax)+GD32_DMA_INTF1_OFFSET) /* DMA interrupt flag register 1 */ +#define GD32_DMA_INTC0(dmax) ((dmax)+GD32_DMA_INTC0_OFFSET) /* DMA interrupt flag clear register 1 */ +#define GD32_DMA_INTC1(dmax) ((dmax)+GD32_DMA_INTC1_OFFSET) /* DMA interrupt flag clear register 1 */ + +#define GD32_DMA_CH0CTL(dmax) ((dmax)+GD32_DMA_CH0CTL_OFFSET) /* DMA channel 0 control register */ +#define GD32_DMA_CH0CNT(dmax) ((dmax)+GD32_DMA_CH0CNT_OFFSET) /* DMA channel 0 counter register */ +#define GD32_DMA_CH0PADDR(dmax) ((dmax)+GD32_DMA_CH0PADDR_OFFSET) /* DMA channel 0 peripheral base address register */ +#define GD32_DMA_CH0M0ADDR(dmax) ((dmax)+GD32_DMA_CH0M0ADDR_OFFSET) /* DMA channel 0 memory 0 base address register */ +#define GD32_DMA_CH0M1ADDR(dmax) ((dmax)+GD32_DMA_CH0M1ADDR_OFFSET) /* DMA channel 0 memory 1 base address register */ +#define GD32_DMA_CH0FCTL(dmax) ((dmax)+GD32_DMA_CH0FCTL_OFFSET) /* DMA channel 0 FIFO control register */ + +#define GD32_DMA_CH1CTL(dmax) ((dmax)+GD32_DMA_CH1CTL_OFFSET) /* DMA channel 1 control register */ +#define GD32_DMA_CH1CNT(dmax) ((dmax)+GD32_DMA_CH1CNT_OFFSET) /* DMA channel 1 counter register */ +#define GD32_DMA_CH1PADDR(dmax) ((dmax)+GD32_DMA_CH1PADDR_OFFSET) /* DMA channel 1 peripheral base address register */ +#define GD32_DMA_CH1M0ADDR(dmax) ((dmax)+GD32_DMA_CH1M0ADDR_OFFSET) /* DMA channel 1 memory 0 base address register */ +#define GD32_DMA_CH1M1ADDR(dmax) ((dmax)+GD32_DMA_CH1M1ADDR_OFFSET) /* DMA channel 1 memory 1 base address register */ +#define GD32_DMA_CH1FCTL(dmax) ((dmax)+GD32_DMA_CH1FCTL_OFFSET) /* DMA channel 1 FIFO control register */ + +#define GD32_DMA_CH2CTL(dmax) ((dmax)+GD32_DMA_CH2CTL_OFFSET) /* DMA channel 2 control register */ +#define GD32_DMA_CH2CNT(dmax) ((dmax)+GD32_DMA_CH2CNT_OFFSET) /* DMA channel 2 counter register */ +#define GD32_DMA_CH2PADDR(dmax) ((dmax)+GD32_DMA_CH2PADDR_OFFSET) /* DMA channel 2 peripheral base address register */ +#define GD32_DMA_CH2M0ADDR(dmax) ((dmax)+GD32_DMA_CH2M0ADDR_OFFSET) /* DMA channel 2 memory 0 base address register */ +#define GD32_DMA_CH2M1ADDR(dmax) ((dmax)+GD32_DMA_CH2M1ADDR_OFFSET) /* DMA channel 2 memory 1 base address register */ +#define GD32_DMA_CH2FCTL(dmax) ((dmax)+GD32_DMA_CH2FCTL_OFFSET) /* DMA channel 2 FIFO control register */ + +#define GD32_DMA_CH3CTL(dmax) ((dmax)+GD32_DMA_CH3CTL_OFFSET) /* DMA channel 3 control register */ +#define GD32_DMA_CH3CNT(dmax) ((dmax)+GD32_DMA_CH3CNT_OFFSET) /* DMA channel 3 counter register */ +#define GD32_DMA_CH3PADDR(dmax) ((dmax)+GD32_DMA_CH3PADDR_OFFSET) /* DMA channel 3 peripheral base address register */ +#define GD32_DMA_CH3M0ADDR(dmax) ((dmax)+GD32_DMA_CH3M0ADDR_OFFSET) /* DMA channel 3 memory 0 base address register */ +#define GD32_DMA_CH3M1ADDR(dmax) ((dmax)+GD32_DMA_CH3M1ADDR_OFFSET) /* DMA channel 3 memory 1 base address register */ +#define GD32_DMA_CH3FCTL(dmax) ((dmax)+GD32_DMA_CH3FCTL_OFFSET) /* DMA channel 3 FIFO control register */ + +#define GD32_DMA_CH4CTL(dmax) ((dmax)+GD32_DMA_CH4CTL_OFFSET) /* DMA channel 4 control register */ +#define GD32_DMA_CH4CNT(dmax) ((dmax)+GD32_DMA_CH4CNT_OFFSET) /* DMA channel 4 counter register */ +#define GD32_DMA_CH4PADDR(dmax) ((dmax)+GD32_DMA_CH4PADDR_OFFSET) /* DMA channel 4 peripheral base address register */ +#define GD32_DMA_CH4M0ADDR(dmax) ((dmax)+GD32_DMA_CH4M0ADDR_OFFSET) /* DMA channel 4 memory 0 base address register */ +#define GD32_DMA_CH4M1ADDR(dmax) ((dmax)+GD32_DMA_CH4M1ADDR_OFFSET) /* DMA channel 4 memory 1 base address register */ +#define GD32_DMA_CH4FCTL(dmax) ((dmax)+GD32_DMA_CH4FCTL_OFFSET) /* DMA channel 4 FIFO control register */ + +#define GD32_DMA_CH5CTL(dmax) ((dmax)+GD32_DMA_CH5CTL_OFFSET) /* DMA channel 5 control register */ +#define GD32_DMA_CH5CNT(dmax) ((dmax)+GD32_DMA_CH5CNT_OFFSET) /* DMA channel 5 counter register */ +#define GD32_DMA_CH5PADDR(dmax) ((dmax)+GD32_DMA_CH5PADDR_OFFSET) /* DMA channel 5 peripheral base address register */ +#define GD32_DMA_CH5M0ADDR(dmax) ((dmax)+GD32_DMA_CH5M0ADDR_OFFSET) /* DMA channel 5 memory 0 base address register */ +#define GD32_DMA_CH5M1ADDR(dmax) ((dmax)+GD32_DMA_CH5M1ADDR_OFFSET) /* DMA channel 5 memory 1 base address register */ +#define GD32_DMA_CH5FCTL(dmax) ((dmax)+GD32_DMA_CH5FCTL_OFFSET) /* DMA channel 5 FIFO control register */ + +#define GD32_DMA_CH6CTL(dmax) ((dmax)+GD32_DMA_CH6CTL_OFFSET) /* DMA channel 6 control register */ +#define GD32_DMA_CH6CNT(dmax) ((dmax)+GD32_DMA_CH6CNT_OFFSET) /* DMA channel 6 counter register */ +#define GD32_DMA_CH6PADDR(dmax) ((dmax)+GD32_DMA_CH6PADDR_OFFSET) /* DMA channel 6 peripheral base address register */ +#define GD32_DMA_CH6M0ADDR(dmax) ((dmax)+GD32_DMA_CH6M0ADDR_OFFSET) /* DMA channel 6 memory 0 base address register */ +#define GD32_DMA_CH6M1ADDR(dmax) ((dmax)+GD32_DMA_CH6M1ADDR_OFFSET) /* DMA channel 6 memory 1 base address register */ +#define GD32_DMA_CH6FCTL(dmax) ((dmax)+GD32_DMA_CH6FCTL_OFFSET) /* DMA channel 6 FIFO control register */ + +#define GD32_DMA_CH7CTL(dmax) ((dmax)+GD32_DMA_CH7CTL_OFFSET) /* DMA channel 7 control register */ +#define GD32_DMA_CH7CNT(dmax) ((dmax)+GD32_DMA_CH7CNT_OFFSET) /* DMA channel 7 counter register */ +#define GD32_DMA_CH7PADDR(dmax) ((dmax)+GD32_DMA_CH7PADDR_OFFSET) /* DMA channel 7 peripheral base address register */ +#define GD32_DMA_CH7M0ADDR(dmax) ((dmax)+GD32_DMA_CH7M0ADDR_OFFSET) /* DMA channel 7 memory 0 base address register */ +#define GD32_DMA_CH7M1ADDR(dmax) ((dmax)+GD32_DMA_CH7M1ADDR_OFFSET) /* DMA channel 7 memory 1 base address register */ +#define GD32_DMA_CH7FCTL(dmax) ((dmax)+GD32_DMA_CH7FCTL_OFFSET) /* DMA channel 7 FIFO control register */ + +/* DMA channelx register address */ +#define GD32_DMA_CHCTL(dma, channelx) ((dma+0x10) + 0x18*(channelx)) /* The address of DMA channel CHXCTL register */ +#define GD32_DMA_CHCNT(dma, channelx) ((dma+0x14) + 0x18*(channelx)) /* The address of DMA channel CHXCNT register */ +#define GD32_DMA_CHPADDR(dma, channelx) ((dma+0x18) + 0x18*(channelx)) /* The address of DMA channel CHXPADDR register */ +#define GD32_DMA_CHM0ADDR(dma, channelx) ((dma+0x1C) + 0x18*(channelx)) /* The address of DMA channel CHXM0ADDR register */ +#define GD32_DMA_CHM1ADDR(dma, channelx) ((dma+0x20) + 0x18*(channelx)) /* The address of DMA channel CHXM1ADDR register */ +#define GD32_DMA_CHFCTL(dma, channelx) ((dma+0x24) + 0x18*(channelx)) /* The address of DMA channel CHXMADDR register */ + +/* bits definitions */ + +/* DMA_INTF */ +#define DMA_INTF_FEEIF (1 << 0) /* Bit 0: FIFO error and exception flag */ +#define DMA_INTF_SDEIF (1 << 2) /* Bit 2: single data mode exception flag */ +#define DMA_INTF_TAEIF (1 << 3) /* Bit 3: transfer access error flag */ +#define DMA_INTF_HTFIF (1 << 4) /* Bit 4: half transfer finish flag */ +#define DMA_INTF_FTFIF (1 << 5) /* Bit 5: full transger finish flag */ + +/* DMA_INTC */ +#define DMA_INTC_FEEIFC (1 << 0) /* Bit 0: clear FIFO error and exception flag */ +#define DMA_INTC_SDEIFC (1 << 2) /* Bit 2: clear single data mode exception flag */ +#define DMA_INTC_TAEIFC (1 << 3) /* Bit 3: clear single data mode exception flag */ +#define DMA_INTC_HTFIFC (1 << 4) /* Bit 4: clear half transfer finish flag */ +#define DMA_INTC_FTFIFC (1 << 5) /* Bit 5: clear full transger finish flag */ + +/* DMA_CHxCTL,x=0..7 */ +#define DMA_CHXCTL_CHEN (1 << 0) /* Bit 0: channel x enable */ +#define DMA_CHXCTL_SDEIE (1 << 1) /* Bit 1: enable bit for channel x single data mode exception interrupt */ +#define DMA_CHXCTL_TAEIE (1 << 2) /* Bit 2: enable bit for channel x tranfer access error interrupt */ +#define DMA_CHXCTL_HTFIE (1 << 3) /* Bit 3: enable bit for channel x half transfer finish interrupt */ +#define DMA_CHXCTL_FTFIE (1 << 4) /* Bit 4: enable bit for channel x full transfer finish interrupt */ +#define DMA_CHXCTL_TFCS (1 << 5) /* Bit 5: transfer flow controller select */ +#define DMA_CHXCTL_TM_SHIFT (6) /* Bit 6-7: transfer mode */ +#define DMA_CHXCTL_TM_MASK (3 << DMA_CHXCTL_TM_SHIFT) +#define DMA_CHXCTL_TM(n) ((n) << DMA_CHXCTL_TM_SHIFT) +# define DMA_PERIPH_TO_MEMORY DMA_CHXCTL_TM(0) /* 00: read from peripheral and write to memory */ +# define DMA_MEMORY_TO_PERIPH DMA_CHXCTL_TM(1) /* 01: read from peripheral and write to memory */ +# define DMA_MEMORY_TO_MEMORY DMA_CHXCTL_TM(2) /* 02: read from peripheral and write to memory */ + +#define DMA_CHXCTL_CMEN (1 << 8) /* Bit 8: circulation mode */ +#define DMA_CHXCTL_PNAGA (1 << 9) /* Bit 9: next address generation algorithm of peripheral */ +#define DMA_CHXCTL_MNAGA (1 << 10) /* Bit 10: next address generation algorithm of memory */ +#define DMA_CHXCTL_PWIDTH_SHIFT (11) /* Bit 11-12: transfer width of peipheral */ +#define DMA_CHXCTL_PWIDTH_MASK (3 << DMA_CHXCTL_PWIDTH_SHIFT) +#define DMA_CHXCTL_PWIDTH(n) ((n) << DMA_CHXCTL_PWIDTH_SHIFT) +# define DMA_PERIPH_WIDTH_8BIT DMA_CHXCTL_PWIDTH(0) /* 00: transfer data width of peripheral is 8-bit */ +# define DMA_PERIPH_WIDTH_16BIT DMA_CHXCTL_PWIDTH(1) /* 01: transfer data width of peripheral is 16-bit */ +# define DMA_PERIPH_WIDTH_32BIT DMA_CHXCTL_PWIDTH(2) /* 02: transfer data width of peripheral is 32-bit */ + +#define DMA_CHXCTL_MWIDTH_SHIFT (13) /* Bit 13-14: transfer width of memory */ +#define DMA_CHXCTL_MWIDTH_MASK (3 << DMA_CHXCTL_MWIDTH_SHIFT) +#define DMA_CHXCTL_MWIDTH(n) ((n) << DMA_CHXCTL_MWIDTH_SHIFT) +# define DMA_MEMORY_WIDTH_8BIT DMA_CHXCTL_MWIDTH(0) /* 00: transfer data width of memory is 8-bit */ +# define DMA_MEMORY_WIDTH_16BIT DMA_CHXCTL_MWIDTH(1) /* 01: transfer data width of memory is 16-bit */ +# define DMA_MEMORY_WIDTH_32BIT DMA_CHXCTL_MWIDTH(2) /* 02: transfer data width of memory is 32-bit */ + +#define DMA_CHXCTL_PAIF (1 << 15) /* Bit 15: peripheral address increment fixed */ + +#define DMA_CHXCTL_PRIO_SHIFT (16) /* Bit 16-17: priority level */ +#define DMA_CHXCTL_PRIO_MASK (3 << DMA_CHXCTL_PRIO_SHIFT) +#define DMA_CHXCTL_PRIO(n) ((n) << DMA_CHXCTL_PRIO_SHIFT) +# define DMA_PRIORITY_LOW DMA_CHXCTL_PRIO(0) /* 00: low priority */ +# define DMA_PRIORITY_MEDIUM DMA_CHXCTL_PRIO(1) /* 01: medium priority */ +# define DMA_PRIORITY_HIGH DMA_CHXCTL_PRIO(2) /* 10: high priority */ +# define DMA_PRIORITY_ULTRA_HIGH DMA_CHXCTL_PRIO(3) /* 11: ultra high priority */ + +#define DMA_CHXCTL_SBMEN (1 << 18) /* Bit 18: switch-buffer mode enable */ +#define DMA_CHXCTL_MBS (1 << 19) /* Bit19: memory buffer select */ + +#define DMA_CHXCTL_PBURST_SHIFT (21) /* Bit 21-22: transfer burst type of peripheral */ +#define DMA_CHXCTL_PBURST_MASK (3 << DMA_CHXCTL_PBURST_SHIFT) +#define DMA_CHXCTL_PBURST(n) ((n) << DMA_CHXCTL_PBURST_SHIFT) +# define DMA_PERIPH_BURST_SINGLE DMA_CHXCTL_PBURST(0) /* single burst */ +# define DMA_PERIPH_BURST_4_BEAT DMA_CHXCTL_PBURST(1) /* 4-beat burst */ +# define DMA_PERIPH_BURST_8_BEAT DMA_CHXCTL_PBURST(2) /* 8-beat burst */ +# define DMA_PERIPH_BURST_16_BEAT DMA_CHXCTL_PBURST(3) /* 16-beat burst */ + +#define DMA_CHXCTL_MBURST_SHIFT (23) /* Bit 23-24: transfer burst type of memory */ +#define DMA_CHXCTL_MBURST_MASK (3 << DMA_CHXCTL_MBURST_SHIFT) +#define DMA_CHXCTL_MBURST(n) ((n) << DMA_CHXCTL_MBURST_SHIFT) +# define DMA_MEMORY_BURST_SINGLE DMA_CHXCTL_MBURST(0) /* single burst */ +# define DMA_MEMORY_BURST_4_BEAT DMA_CHXCTL_MBURST(1) /* 4-beat burst */ +# define DMA_MEMORY_BURST_8_BEAT DMA_CHXCTL_MBURST(2) /* 8-beat burst */ +# define DMA_MEMORY_BURST_16_BEAT DMA_CHXCTL_MBURST(3) /* 16-beat burst */ + +#define DMA_CHXCTL_PERIEN_SHIFT (25) /* Bit 25-27: peripheral enable */ +#define DMA_CHXCTL_PERIEN_MASK (7 << DMA_CHXCTL_PERIEN_SHIFT) +#define DMA_CHXCTL_PERIEN(n) ((n) << DMA_CHXCTL_PERIEN_SHIFT) +# define DMA_PERIPH_0_SELECT DMA_CHXCTL_PERIEN(0) /* peripheral 0 select */ +# define DMA_PERIPH_1_SELECT DMA_CHXCTL_PERIEN(1) /* peripheral 1 select */ +# define DMA_PERIPH_2_SELECT DMA_CHXCTL_PERIEN(2) /* peripheral 2 select */ +# define DMA_PERIPH_3_SELECT DMA_CHXCTL_PERIEN(3) /* peripheral 3 select */ +# define DMA_PERIPH_4_SELECT DMA_CHXCTL_PERIEN(4) /* peripheral 4 select */ +# define DMA_PERIPH_5_SELECT DMA_CHXCTL_PERIEN(5) /* peripheral 5 select */ +# define DMA_PERIPH_6_SELECT DMA_CHXCTL_PERIEN(6) /* peripheral 6 select */ +# define DMA_PERIPH_7_SELECT DMA_CHXCTL_PERIEN(7) /* peripheral 7 select */ + +/* DMA_CHxCNT, x=0..7 */ +#define DMA_CHXCNT_CNT_MASK (0xffff << 0) /* Bit 0-15: transfer counter */ + +/* DMA_CHxPADDR,x=0..7 */ +#define DMA_CHXPADDR_PADDR_MASK (0xffffffff << 0) /* Bit 0-31: peripheral base address */ + +/* DMA_CHxM0ADDR,x=0..7 */ +#define DMA_CHXM0ADDR_M0ADDR_MASK (0xffffffff << 0) /* Bit 0-31: memory 0 base address */ + +/* DMA_CHxM1ADDR,x=0..7 */ +#define DMA_CHXM1ADDR_M0ADDR_MASK (0xffffffff << 0) /* Bit 0-31: memory 1 base address */ + +/* DMA_CHxFCTL,x=0..7 */ +#define DMA_CHXFCTL_FCCV_SHIFT (0) /* Bit 0-1: FIFO counter critical value */ +#define DMA_CHXFCTL_FCCV_MASK (3 << DMA_CHXFCTL_FCCV_SHIFT) +#define DMA_CHXFCTL_FCCV(n) ((n) << DMA_CHXFCTL_FCCV_SHIFT) +# define DMA_FIFO_1_WORD DMA_CHXFCTL_FCCV(0) /* critical value 1 word */ +# define DMA_FIFO_2_WORD DMA_CHXFCTL_FCCV(1) /* critical value 2 word */ +# define DMA_FIFO_3_WORD DMA_CHXFCTL_FCCV(2) /* critical value 3 word */ +# define DMA_FIFO_4_WORD DMA_CHXFCTL_FCCV(3) /* critical value 4 word */ + +#define DMA_CHXFCTL_MDMEN (1 << 2) /* Bit 2: multi-data mode enable */ +#define DMA_CHXFCTL_FCNT_SHIFT (3) /* Bit 3-5: FIFO counter */ +#define DMA_CHXFCTL_FCNT_MASK (7 << DMA_CHXFCTL_FCNT_SHIFT) +#define DMA_CHXFCTL_FCNT(n) ((n) << DMA_CHXFCTL_FCNT_SHIFT) + +#define DMA_CHXFCTL_FEEIE (1 << 7) /* Bit 3: FIFO exception interrupt enable */ + +#define GD32_DMA_FLAG_ADD(flag,channel) ((uint32_t)((flag)<<((((uint32_t)(channel)*6U))+((uint32_t)(((uint32_t)(channel)) >> 1U)&0x01U)*4U))) /* DMA channel flag shift */ + +/* peripheral increasing mode */ +#define DMA_PERIPH_INCREASE_ENABLE (0x00000000) /* Next address of peripheral is increasing address mode */ +#define DMA_PERIPH_INCREASE_DISABLE (0x00000001) /* Next address of peripheral is fixed address mode */ +#define DMA_PERIPH_INCREASE_FIX (0x00000002) /* Next address of peripheral is increasing fixed */ + +/* memory increasing mode */ +#define DMA_MEMORY_INCREASE_ENABLE (0x00000000) /* Next address of memory is increasing address mode */ +#define DMA_MEMORY_INCREASE_DISABLE (0x00000001) /* Next address of memory is fixed address mode */ + +/* DMA circular mode */ +#define DMA_CIRCULAR_MODE_ENABLE (0x00000000) /* Circular mode enable */ +#define DMA_CIRCULAR_MODE_DISABLE (0x00000001) /* Circular mode disable */ + +/* DMA width selection */ +#define DMA_WIDTH_8BITS_SELECT (0x00000000) /* Select 8 bits width */ +#define DMA_WIDTH_16BITS_SELECT (0x00000001) /* Select 16 bits width */ +#define DMA_WIDTH_32BITS_SELECT (0x00000002) /* Select 16 bits width */ + +/* DMA priority level selection */ +#define DMA_PRIO_LOW_SELECT (0x00000000) /* Select low priority level */ +#define DMA_PRIO_MEDIUM_SELECT (0x00000001) /* Select medium priority level */ +#define DMA_PRIO_HIGH_SELECT (0x00000002) /* Select high priority level */ +#define DMA_PRIO_ULTRA_HIGHSELECT (0x00000003) /* Select ultra high priority level */ + +/* DMA channel select */ + +#define GD32_DMA_CH0 (0) /* DMA Channel 0 */ +#define GD32_DMA_CH1 (1) /* DMA Channel 1 */ +#define GD32_DMA_CH2 (2) /* DMA Channel 2 */ +#define GD32_DMA_CH3 (3) /* DMA Channel 3 */ +#define GD32_DMA_CH4 (4) /* DMA Channel 4 */ +#define GD32_DMA_CH5 (5) /* DMA Channel 5 */ +#define GD32_DMA_CH6 (6) /* DMA Channel 6 */ +#define GD32_DMA_CH7 (7) /* DMA Channel 7 */ + +/* DMA peripheral select */ + +#define GD32_DMA_SUBPERI0 (0) /* DMA Peripheral 0 */ +#define GD32_DMA_SUBPERI1 (1) /* DMA Peripheral 1 */ +#define GD32_DMA_SUBPERI2 (2) /* DMA Peripheral 2 */ +#define GD32_DMA_SUBPERI3 (3) /* DMA Peripheral 3 */ +#define GD32_DMA_SUBPERI4 (4) /* DMA Peripheral 4 */ +#define GD32_DMA_SUBPERI5 (5) /* DMA Peripheral 5 */ +#define GD32_DMA_SUBPERI6 (6) /* DMA Peripheral 6 */ +#define GD32_DMA_SUBPERI7 (7) /* DMA Peripheral 7 */ + +/* DMA peripheral requests mapping */ + +#define CHANNEL_SHIFT (0) +#define CHANNEL_MASK (0xf) +#define PERIPH_SHIFT (4) +#define PERIPH_MASK (0x7) + +/* Peripheral requests to DMA0 */ + +#define DMA_REQ_SPI2_RX_1 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | (GD32_DMA_CH0 << CHANNEL_SHIFT)) +#define DMA_REQ_I2C0_RX_1 ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | (GD32_DMA_CH0 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER3_CH0 ((GD32_DMA_SUBPERI2 << PERIPH_SHIFT) | (GD32_DMA_CH0 << CHANNEL_SHIFT)) +#define DMA_REQ_I2S2_ADD_RX_1 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | (GD32_DMA_CH0 << CHANNEL_SHIFT)) +#define DMA_REQ_UART4_RX ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | (GD32_DMA_CH0 << CHANNEL_SHIFT)) +#define DMA_REQ_UART7_TX ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | (GD32_DMA_CH0 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER4_CH2 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | (GD32_DMA_CH0 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER4_UP_1 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | (GD32_DMA_CH0 << CHANNEL_SHIFT)) +#define DMA_REQ_I2S2_ADD_RX ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | (GD32_DMA_CH0 << CHANNEL_SHIFT)) + +#define DMA_REQ_TIMER1_UP_1 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | (GD32_DMA_CH1 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER1_CH2 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | (GD32_DMA_CH1 << CHANNEL_SHIFT)) +#define DMA_REQ_USART2_RX ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | (GD32_DMA_CH1 << CHANNEL_SHIFT)) +#define DMA_REQ_UART6_TX ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | (GD32_DMA_CH1 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER4_CH3_1 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | (GD32_DMA_CH1 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER4_TG ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | (GD32_DMA_CH1 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER5_UP ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | (GD32_DMA_CH1 << CHANNEL_SHIFT)) + +#define DMA_REQ_SPI2_RX_2 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | (GD32_DMA_CH2 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER6_UP_1 ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | (GD32_DMA_CH2 << CHANNEL_SHIFT)) +#define DMA_REQ_I2S2_ADD_RX_2 ((GD32_DMA_SUBPERI2 << PERIPH_SHIFT) | (GD32_DMA_CH2 << CHANNEL_SHIFT)) +#define DMA_REQ_I2C2_RX ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | (GD32_DMA_CH2 << CHANNEL_SHIFT)) +#define DMA_REQ_UART3_RX ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | (GD32_DMA_CH2 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER2_CH3 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | (GD32_DMA_CH2 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER2_UP_1 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | (GD32_DMA_CH2 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER4_CH0 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | (GD32_DMA_CH2 << CHANNEL_SHIFT)) +#define DMA_REQ_I2C1_RX_1 ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | (GD32_DMA_CH2 << CHANNEL_SHIFT)) + +#define DMA_REQ_SPI1_RX ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | (GD32_DMA_CH3 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER3_CH1 ((GD32_DMA_SUBPERI2 << PERIPH_SHIFT) | (GD32_DMA_CH3 << CHANNEL_SHIFT)) +#define DMA_REQ_I2S1_ADD_RX ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | (GD32_DMA_CH3 << CHANNEL_SHIFT)) +#define DMA_REQ_USART2_TX_1 ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | (GD32_DMA_CH3 << CHANNEL_SHIFT)) +#define DMA_REQ_UART6_RX ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | (GD32_DMA_CH3 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER4_CH3_2 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | (GD32_DMA_CH3 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER4_UP_2 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | (GD32_DMA_CH3 << CHANNEL_SHIFT)) +#define DMA_REQ_I2C1_RX_2 ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | (GD32_DMA_CH3 << CHANNEL_SHIFT)) + +#define DMA_REQ_SPI1_TX ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | (GD32_DMA_CH4 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER6_UP_2 ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | (GD32_DMA_CH4 << CHANNEL_SHIFT)) +#define DMA_REQ_I2S1_ADD_TX ((GD32_DMA_SUBPERI2 << PERIPH_SHIFT) | (GD32_DMA_CH4 << CHANNEL_SHIFT)) +#define DMA_REQ_I2C2_TX ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | (GD32_DMA_CH4 << CHANNEL_SHIFT)) +#define DMA_REQ_UART3_TX ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | (GD32_DMA_CH4 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER2_CH0 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | (GD32_DMA_CH4 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER2_UP_2 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | (GD32_DMA_CH4 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER4_CH1 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | (GD32_DMA_CH4 << CHANNEL_SHIFT)) +#define DMA_REQ_USART2_TX_2 ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | (GD32_DMA_CH4 << CHANNEL_SHIFT)) + +#define DMA_REQ_SPI2_TX_1 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | (GD32_DMA_CH5 << CHANNEL_SHIFT)) +#define DMA_REQ_I2C0_RX ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | (GD32_DMA_CH5 << CHANNEL_SHIFT)) +#define DMA_REQ_I2S2_ADD_TX ((GD32_DMA_SUBPERI2 << PERIPH_SHIFT) | (GD32_DMA_CH5 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER1_CH0 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | (GD32_DMA_CH5 << CHANNEL_SHIFT)) +#define DMA_REQ_USART1_RX ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | (GD32_DMA_CH5 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER2_CH1 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | (GD32_DMA_CH5 << CHANNEL_SHIFT)) +#define DMA_REQ_DAC0 ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | (GD32_DMA_CH5 << CHANNEL_SHIFT)) + +#define DMA_REQ_I2C0_TX_1 ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | (GD32_DMA_CH6 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER3_UP ((GD32_DMA_SUBPERI2 << PERIPH_SHIFT) | (GD32_DMA_CH6 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER1_CH1 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | (GD32_DMA_CH6 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER1_CH3_1 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | (GD32_DMA_CH6 << CHANNEL_SHIFT)) +#define DMA_REQ_USART1_TX ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | (GD32_DMA_CH6 << CHANNEL_SHIFT)) +#define DMA_REQ_UART7_RX ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | (GD32_DMA_CH6 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER4_UP ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | (GD32_DMA_CH6 << CHANNEL_SHIFT)) +#define DMA_REQ_DAC1 ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | (GD32_DMA_CH6 << CHANNEL_SHIFT)) + +#define DMA_REQ_SPI2_TX_2 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | (GD32_DMA_CH7 << CHANNEL_SHIFT)) +#define DMA_REQ_I2C0_TX_2 ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | (GD32_DMA_CH7 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER3_CH2 ((GD32_DMA_SUBPERI2 << PERIPH_SHIFT) | (GD32_DMA_CH7 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER1_UP_2 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | (GD32_DMA_CH7 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER1_CH3_2 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | (GD32_DMA_CH7 << CHANNEL_SHIFT)) +#define DMA_REQ_UART4_TX ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | (GD32_DMA_CH7 << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER2_CH2 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | (GD32_DMA_CH7 << CHANNEL_SHIFT)) +#define DMA_REQ_I2C1_TX ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | (GD32_DMA_CH7 << CHANNEL_SHIFT)) + +/* Peripheral requests to DMA1 */ + +#define DMA_REQ_ADC0_1 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | ((GD32_DMA_CH0 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_ADC2_1 ((GD32_DMA_SUBPERI2 << PERIPH_SHIFT) | ((GD32_DMA_CH0 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI0_RX_1 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | ((GD32_DMA_CH0 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI3_RX_1 ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | ((GD32_DMA_CH0 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER0_TG_1 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | ((GD32_DMA_CH0 + 8) << CHANNEL_SHIFT)) + +#define DMA_REQ_DCI_1 ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | ((GD32_DMA_CH1 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_ADC2_2 ((GD32_DMA_SUBPERI2 << PERIPH_SHIFT) | ((GD32_DMA_CH1 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI3_TX_1 ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | ((GD32_DMA_CH1 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_USART5_RX_1 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | ((GD32_DMA_CH1 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER0_CH0_1 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | ((GD32_DMA_CH1 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER7_UP ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | ((GD32_DMA_CH1 + 8) << CHANNEL_SHIFT)) + +#define DMA_REQ_TIMER7_CH0_1 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | ((GD32_DMA_CH2 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER7_CH1_1 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | ((GD32_DMA_CH2 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER7_CH2_1 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | ((GD32_DMA_CH2 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_ADC1_1 ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | ((GD32_DMA_CH2 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI0_RX_2 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | ((GD32_DMA_CH2 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_USART0_RX_1 ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | ((GD32_DMA_CH2 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_USART5_RX_2 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | ((GD32_DMA_CH2 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER0_CH1_1 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | ((GD32_DMA_CH2 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER7_CH0_2 ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | ((GD32_DMA_CH2 + 8) << CHANNEL_SHIFT)) + +#define DMA_REQ_ADC1_2 ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | ((GD32_DMA_CH3 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI4_RX_1 ((GD32_DMA_SUBPERI2 << PERIPH_SHIFT) | ((GD32_DMA_CH3 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI0_TX_1 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | ((GD32_DMA_CH3 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SDIO_1 ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | ((GD32_DMA_CH3 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI3_RX_2 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | ((GD32_DMA_CH3 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER0_CH0_2 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | ((GD32_DMA_CH3 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER7_CH1_2 ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | ((GD32_DMA_CH3 + 8) << CHANNEL_SHIFT)) + +#define DMA_REQ_ADC0_2 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | ((GD32_DMA_CH4 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI4_TX_1 ((GD32_DMA_SUBPERI2 << PERIPH_SHIFT) | ((GD32_DMA_CH4 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI3_TX_2 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | ((GD32_DMA_CH4 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER0_CH3 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | ((GD32_DMA_CH4 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER0_TG_2 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | ((GD32_DMA_CH4 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER0_CMT ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | ((GD32_DMA_CH4 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER7_CH2_2 ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | ((GD32_DMA_CH4 + 8) << CHANNEL_SHIFT)) + +#define DMA_REQ_SPI5_TX ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | ((GD32_DMA_CH5 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI0_TX_2 ((GD32_DMA_SUBPERI3 << PERIPH_SHIFT) | ((GD32_DMA_CH5 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_USART0_RX_2 ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | ((GD32_DMA_CH5 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER0_UP ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | ((GD32_DMA_CH5 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI4_RX_2 ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | ((GD32_DMA_CH5 + 8) << CHANNEL_SHIFT)) + +#define DMA_REQ_TIMER0_CH0_3 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | ((GD32_DMA_CH6 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER0_CH1_2 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | ((GD32_DMA_CH6 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER0_CH2_1 ((GD32_DMA_SUBPERI0 << PERIPH_SHIFT) | ((GD32_DMA_CH6 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI5_RX ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | ((GD32_DMA_CH6 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SDIO_2 ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | ((GD32_DMA_CH6 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_USART5_TX_1 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | ((GD32_DMA_CH6 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER0_CH2_2 ((GD32_DMA_SUBPERI6 << PERIPH_SHIFT) | ((GD32_DMA_CH6 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_SPI4_TX_2 ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | ((GD32_DMA_CH6 + 8) << CHANNEL_SHIFT)) + +#define DMA_REQ_DCI_2 ((GD32_DMA_SUBPERI1 << PERIPH_SHIFT) | ((GD32_DMA_CH7 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_USART0_TX ((GD32_DMA_SUBPERI4 << PERIPH_SHIFT) | ((GD32_DMA_CH7 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_USART5_TX_2 ((GD32_DMA_SUBPERI5 << PERIPH_SHIFT) | ((GD32_DMA_CH7 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER7_CH3 ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | ((GD32_DMA_CH7 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER7_TG ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | ((GD32_DMA_CH7 + 8) << CHANNEL_SHIFT)) +#define DMA_REQ_TIMER7_CMT ((GD32_DMA_SUBPERI7 << PERIPH_SHIFT) | ((GD32_DMA_CH7 + 8) << CHANNEL_SHIFT)) + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_DMA_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_enet.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_enet.h new file mode 100644 index 0000000000..1107daf4ef --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_enet.h @@ -0,0 +1,924 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_enet.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_ENET_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_ENET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +#if GD32_NETHERNET > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +/* MAC Registers */ + +#define GD32_ENET_MAC_CFG_OFFSET 0x0000 /* MAC configuration register offset */ +#define GD32_ENET_MAC_FRMF_OFFSET 0x0004 /* MAC frame filter register offset */ +#define GD32_ENET_MAC_HLH_OFFSET 0x0008 /* MAC hash list high register offset */ +#define GD32_ENET_MAC_HLL_OFFSET 0x000C /* MAC hash list low register offset */ +#define GD32_ENET_MAC_PHY_CTL_OFFSET 0x0010 /* MAC PHY control register offset */ +#define GD32_ENET_MAC_PHY_DATA_OFFSET 0x0014 /* MAC PHY data register offset */ +#define GD32_ENET_MAC_FCTL_OFFSET 0x0018 /* MAC flow control register offset */ +#define GD32_ENET_MAC_VLT_OFFSET 0x001C /* MAC VLAN tag register offset */ +#define GD32_ENET_MAC_RWFF_OFFSET 0x0028 /* MAC remote wakeup frame filter register offset */ +#define GD32_ENET_MAC_WUM_OFFSET 0x002C /* MAC wakeup managenment register offset */ + +#define GD32_ENET_MAC_DBG_OFFSET 0x0034 /* MAC debug register offset */ +#define GD32_ENET_MAC_INTF_OFFSET 0x0038 /* MAC interrupt flag register offset */ +#define GD32_ENET_MAC_INTMSK_OFFSET 0x003C /* MAC interrupt mask register offset */ +#define GD32_ENET_MAC_ADDR0H_OFFSET 0x0040 /* MAC address 0 high register offset */ +#define GD32_ENET_MAC_ADDR0L_OFFSET 0x0044 /* MAC address 0 low register offset */ +#define GD32_ENET_MAC_ADDR1H_OFFSET 0x0048 /* MAC address 1 high register offset */ +#define GD32_ENET_MAC_ADDR1L_OFFSET 0x004C /* MAC address 1 low register offset */ +#define GD32_ENET_MAC_ADDR2H_OFFSET 0x0050 /* MAC address 2 high register offset */ +#define GD32_ENET_MAC_ADDR2L_OFFSET 0x0054 /* MAC address 2 low register offset */ +#define GD32_ENET_MAC_ADDR3H_OFFSET 0x0058 /* MAC address 3 high register offset */ +#define GD32_ENET_MAC_ADDR3L_OFFSET 0x005C /* MAC address 3 low register offset */ + +#define GD32_ENET_MAC_FCTH_OFFSET 0x1080 /* MAC flow control threshold register offset */ + +/* MSC Registers */ + +#define GD32_ENET_MSC_CTL_OFFSET 0x0100 /* MSC control register offset */ +#define GD32_ENET_MSC_RINTF_OFFSET 0x0104 /* MSC receive interrupt flag register offset */ +#define GD32_ENET_MSC_TINTF_OFFSET 0x0108 /* MSC transmit interrupt flag register offset */ +#define GD32_ENET_MSC_RINTMSK_OFFSET 0x010C /* MSC receive interrupt mask register offset */ +#define GD32_ENET_MSC_TINTMSK_OFFSET 0x0110 /* MSC transmit interrupt mask register offset */ + +#define GD32_ENET_MSC_SCCNT_OFFSET 0x014C /* MSC transmitted good frames after a single collision counter register offset */ +#define GD32_ENET_MSC_MSCCNT_OFFSET 0x0150 /* MSC transmitted good frames after more than a signle collision counter register offset */ + +#define GD32_ENET_MSC_TGFCNT_OFFSET 0x0168 /* MSC transmitted good frames counter register offset */ + +#define GD32_ENET_MSC_RFCECNT_OFFSET 0x0194 /* MSC received frames with CRC error counter register offset */ +#define GD32_ENET_MSC_RFAECNT_OFFSET 0x0198 /* MSC received frames with alignment error counter offset */ + +#define GD32_ENET_MSC_RGUFCNT_OFFSET 0x01C4 /* MSC received good unicast frames counter register offset */ + +/* PTP Registers */ + +#define GD32_ENET_PTP_TSCTL_OFFSET 0x0700 /* PTP time stamp control register offset */ +#define GD32_ENET_PTP_SSINC_OFFSET 0x0704 /* PTP subsecond increment register offset */ +#define GD32_ENET_PTP_TSH_OFFSET 0x0708 /* PTP time stamp high register offset */ +#define GD32_ENET_PTP_TSL_OFFSET 0x070C /* PTP time stamp low register offset */ +#define GD32_ENET_PTP_TSUH_OFFSET 0x0710 /* PTP time stamp update high register offset */ +#define GD32_ENET_PTP_TSUL_OFFSET 0x0714 /* PTP time stamp update low register offset */ +#define GD32_ENET_PTP_TSADDEND_OFFSET 0x0718 /* PTP time stamp addend register offset */ +#define GD32_ENET_PTP_ETH_OFFSET 0x071C /* PTP expected time high register offset */ +#define GD32_ENET_PTP_ETL_OFFSET 0x0720 /* PTP expected time low register offset */ +#define GD32_ENET_PTP_TSF_OFFSET 0x0728 /* PTP time stamp flag register offset */ +#define GD32_ENET_PTP_PPSCTL_OFFSET 0x072C /* PTP PPS control register offset */ + +/* DMA Registers */ + +#define GD32_ENET_DMA_BCTL_OFFSET 0x1000 /* DMA bus control register offset */ +#define GD32_ENET_DMA_TPEN_OFFSET 0x1004 /* DMA transmit poll enable register offset */ +#define GD32_ENET_DMA_RPEN_OFFSET 0x1008 /* DMA receive poll enable register offset */ +#define GD32_ENET_DMA_RDTADDR_OFFSET 0x100C /* DMA receive descriptor table address register offset */ +#define GD32_ENET_DMA_TDTADDR_OFFSET 0x1010 /* DMA transmit descriptor table address register offset */ +#define GD32_ENET_DMA_STAT_OFFSET 0x1014 /* DMA status register offset */ +#define GD32_ENET_DMA_CTL_OFFSET 0x1018 /* DMA control register offset */ +#define GD32_ENET_DMA_INTEN_OFFSET 0x101C /* DMA interrupt enable register offset */ +#define GD32_ENET_DMA_MFBOCNT_OFFSET 0x1020 /* DMA missed frame and buffer overflow counter register offset */ +#define GD32_ENET_DMA_RSWDC_OFFSET 0x1024 /* DMA receive state watchdog counter register offset */ + +#define GD32_ENET_DMA_CTDADDR_OFFSET 0x1048 /* DMA current transmit descriptor address register offset */ +#define GD32_ENET_DMA_CRDADDR_OFFSET 0x104C /* DMA current receive descriptor address register offset */ +#define GD32_ENET_DMA_CTBADDR_OFFSET 0x1050 /* DMA current transmit buffer address register offset */ +#define GD32_ENET_DMA_CRBADDR_OFFSET 0x1054 /* DMA current receive buffer address register offset */ + +/* Register Base Addresses **************************************************/ + +/* MAC Registers */ + +#define GD32_ENET_MAC_CFG (GD32_ENET_BASE + GD32_ENET_MAC_CFG_OFFSET) +#define GD32_ENET_MAC_FRMF (GD32_ENET_BASE + GD32_ENET_MAC_FRMF_OFFSET) +#define GD32_ENET_MAC_HLH (GD32_ENET_BASE + GD32_ENET_MAC_HLH_OFFSET) +#define GD32_ENET_MAC_HLL (GD32_ENET_BASE + GD32_ENET_MAC_HLL_OFFSET) +#define GD32_ENET_MAC_PHY_CTL (GD32_ENET_BASE + GD32_ENET_MAC_PHY_CTL_OFFSET) +#define GD32_ENET_MAC_PHY_DATA (GD32_ENET_BASE + GD32_ENET_MAC_PHY_DATA_OFFSET) +#define GD32_ENET_MAC_FCTL (GD32_ENET_BASE + GD32_ENET_MAC_FCTL_OFFSET) +#define GD32_ENET_MAC_VLT (GD32_ENET_BASE + GD32_ENET_MAC_VLT_OFFSET) +#define GD32_ENET_MAC_RWFF (GD32_ENET_BASE + GD32_ENET_MAC_RWFF_OFFSET) +#define GD32_ENET_MAC_WUM (GD32_ENET_BASE + GD32_ENET_MAC_WUM_OFFSET) +#define GD32_ENET_MAC_DBG (GD32_ENET_BASE + GD32_ENET_MAC_DBG_OFFSET) +#define GD32_ENET_MAC_INTF (GD32_ENET_BASE + GD32_ENET_MAC_INTF_OFFSET) +#define GD32_ENET_MAC_INTMSK (GD32_ENET_BASE + GD32_ENET_MAC_INTMSK_OFFSET) +#define GD32_ENET_MAC_ADDR0H (GD32_ENET_BASE + GD32_ENET_MAC_ADDR0H_OFFSET) +#define GD32_ENET_MAC_ADDR0L (GD32_ENET_BASE + GD32_ENET_MAC_ADDR0L_OFFSET) +#define GD32_ENET_MAC_ADDR1H (GD32_ENET_BASE + GD32_ENET_MAC_ADDR1H_OFFSET) +#define GD32_ENET_MAC_ADDR1L (GD32_ENET_BASE + GD32_ENET_MAC_ADDR1L_OFFSET) +#define GD32_ENET_MAC_ADDT2H (GD32_ENET_BASE + GD32_ENET_MAC_ADDT2H_OFFSET) +#define GD32_ENET_MAC_ADDR2L (GD32_ENET_BASE + GD32_ENET_MAC_ADDR2L_OFFSET) +#define GD32_ENET_MAC_ADDR3H (GD32_ENET_BASE + GD32_ENET_MAC_ADDR3H_OFFSET) +#define GD32_ENET_MAC_ADDR3L (GD32_ENET_BASE + GD32_ENET_MAC_ADDR3L_OFFSET) +#define GD32_ENET_MAC_FCTH (GD32_ENET_BASE + GD32_ENET_MAC_FCTH_OFFSET) + +/* MSC Registers */ + +#define GD32_ENET_MSC_CTL (GD32_ENET_BASE + GD32_ENET_MSC_CTL_OFFSET) +#define GD32_ENET_MSC_RINTF (GD32_ENET_BASE + GD32_ENET_MSC_RINTF_OFFSET) +#define GD32_ENET_MSC_TINTF (GD32_ENET_BASE + GD32_ENET_MSC_TINTF_OFFSET) +#define GD32_ENET_MSC_RINTMSK (GD32_ENET_BASE + GD32_ENET_MSC_RINTMSK_OFFSET) +#define GD32_ENET_MSC_TINTMSK (GD32_ENET_BASE + GD32_ENET_MSC_TINTMSK_OFFSET) +#define GD32_ENET_MSC_SCCNT (GD32_ENET_BASE + GD32_ENET_MSC_SCCNT_OFFSET) +#define GD32_ENET_MSC_MSCCNT (GD32_ENET_BASE + GD32_ENET_MSC_MSCCNT_OFFSET) +#define GD32_ENET_MSC_TGFCNT (GD32_ENET_BASE + GD32_ENET_MSC_TGFCNT_OFFSET) +#define GD32_ENET_MSC_RFCECNT (GD32_ENET_BASE + GD32_ENET_MSC_RFCECNT_OFFSET) +#define GD32_ENET_MSC_RFAECNT (GD32_ENET_BASE + GD32_ENET_MSC_RFAECNT_OFFSET) +#define GD32_ENET_MSC_RGUFCNT (GD32_ENET_BASE + GD32_ENET_MSC_RGUFCNT_OFFSET) + +/* PTP Registers */ + +#define GD32_ENET_PTP_TSCTL (GD32_ENET_BASE + GD32_ENET_PTP_TSCTL_OFFSET) +#define GD32_ENET_PTP_SSINC (GD32_ENET_BASE + GD32_ENET_PTP_SSINC_OFFSET) +#define GD32_ENET_PTP_TSH (GD32_ENET_BASE + GD32_ENET_PTP_TSH_OFFSET) +#define GD32_ENET_PTP_TSL (GD32_ENET_BASE + GD32_ENET_PTP_TSL_OFFSET) +#define GD32_ENET_PTP_TSUH (GD32_ENET_BASE + GD32_ENET_PTP_TSUH_OFFSET) +#define GD32_ENET_PTP_TSUL (GD32_ENET_BASE + GD32_ENET_PTP_TSUL_OFFSET) +#define GD32_ENET_PTP_TSADDEND (GD32_ENET_BASE + GD32_ENET_PTP_TSADDEND_OFFSET) +#define GD32_ENET_PTP_ETH (GD32_ENET_BASE + GD32_ENET_PTP_ETH_OFFSET) +#define GD32_ENET_PTP_ETL (GD32_ENET_BASE + GD32_ENET_PTP_ETL_OFFSET) +#define GD32_ENET_PTP_TSF (GD32_ENET_BASE + GD32_ENET_PTP_TSF_OFFSET) +#define GD32_ENET_PTP_PPSCTL (GD32_ENET_BASE + GD32_ENET_PTP_PPSCTL_OFFSET) + +/* DMA Registers */ + +#define GD32_ENET_DMA_BCTL (GD32_ENET_BASE + GD32_ENET_DMA_BCTL_OFFSET) +#define GD32_ENET_DMA_TPEN (GD32_ENET_BASE + GD32_ENET_DMA_TPEN_OFFSET) +#define GD32_ENET_DMA_RPEN (GD32_ENET_BASE + GD32_ENET_DMA_RPEN_OFFSET) +#define GD32_ENET_DMA_RDTADDR (GD32_ENET_BASE + GD32_ENET_DMA_RDTADDR_OFFSET) +#define GD32_ENET_DMA_TDTADDR (GD32_ENET_BASE + GD32_ENET_DMA_TDTADDR_OFFSET) +#define GD32_ENET_DMA_STAT (GD32_ENET_BASE + GD32_ENET_DMA_STAT_OFFSET) +#define GD32_ENET_DMA_CTL (GD32_ENET_BASE + GD32_ENET_DMA_CTL_OFFSET) +#define GD32_ENET_DMA_INTEN (GD32_ENET_BASE + GD32_ENET_DMA_INTEN_OFFSET) +#define GD32_ENET_DMA_MFBOCNT (GD32_ENET_BASE + GD32_ENET_DMA_MFBOCNT_OFFSET) +#define GD32_ENET_DMA_RSWDC (GD32_ENET_BASE + GD32_ENET_DMA_RSWDC_OFFSET) +#define GD32_ENET_DMA_CTDADDR (GD32_ENET_BASE + GD32_ENET_DMA_CTDADDR_OFFSET) +#define GD32_ENET_DMA_CRDADDR (GD32_ENET_BASE + GD32_ENET_DMA_CRDADDR_OFFSET) +#define GD32_ENET_DMA_CTBADDR (GD32_ENET_BASE + GD32_ENET_DMA_CTBADDR_OFFSET) +#define GD32_ENET_DMA_CRBADDR (GD32_ENET_BASE + GD32_ENET_DMA_CRBADDR_OFFSET) + +/* Register Bit-Field Definitions */ + +/* MAC Registers */ + +/* MAC configuration register (GD32_ENET_MAC_CFG) */ + +#define ENET_MAC_CFG_REN (1 << 2) /* Bit 2: receiver enable */ +#define ENET_MAC_CFG_TEN (1 << 3) /* Bit 3: transmitter enable */ +#define ENET_MAC_CFG_DFC (1 << 4) /* Bit 4: defferal check */ + +#define ENET_MAC_CFG_BOL_SHIFT (5) /* Bits 5-6: back-off limit */ +#define ENET_MAC_CFG_BOL_MASK (3 << ENET_MAC_CFG_BOL_SHIFT) +#define ENET_BACKOFFLIMIT_10 (0 << ENET_MAC_CFG_BOL_SHIFT) /* 00: k = min (n, 10) */ +#define ENET_BACKOFFLIMIT_8 (1 << ENET_MAC_CFG_BOL_SHIFT) /* 01: k = min (n, 8) */ +#define ENET_BACKOFFLIMIT_4 (2 << ENET_MAC_CFG_BOL_SHIFT) /* 10: k = min (n, 4) */ +#define ENET_BACKOFFLIMIT_1 (3 << ENET_MAC_CFG_BOL_SHIFT) /* 11: k = min (n, 1) */ + +#define ENET_MAC_CFG_APCD (1 << 7) /* Bit 7: automatic pad/CRC drop */ +#define ENET_MAC_CFG_RTD (1 << 9) /* Bit 9: retry disable */ +#define ENET_MAC_CFG_IPFCO (1 << 10) /* Bit 10: IP frame checksum offload */ +#define ENET_MAC_CFG_DPM (1 << 11) /* Bit 11: duplex mode */ +#define ENET_MAC_CFG_LBM (1 << 12) /* Bit 12: loopback mode */ +#define ENET_MAC_CFG_ROD (1 << 13) /* Bit 13: receive own disable */ +#define ENET_MAC_CFG_SPD (1 << 14) /* Bit 14: fast ethernet speed */ +#define ENET_MAC_CFG_CSD (1 << 16) /* Bit 16: carrier sense disable */ + +#define ENET_MAC_CFG_IGBS_SHIFT (17) /* Bits 17-19: inter-frame gap bit selection */ +#define ENET_MAC_CFG_IGBS_MASK (7 << ENET_MAC_CFG_IGBS_SHIFT) +#define ENET_MAC_CFG_IGBS(n) ((12 - ((n) >> 3)) << ENET_MAC_CFG_IGBS_SHIFT) /* n bit times, n=40, 48,...96 */ + +#define ENET_MAC_CFG_JBD (1 << 22) /* Bit 22: jabber disable */ +#define ENET_MAC_CFG_WDD (1 << 23) /* Bit 23: watchdog disable */ +#define ENET_MAC_CFG_TFCD (1 << 25) /* Bit 25: type frame CRC dropping */ + +/* MAC frame filter register (GD32_ENET_MAC_FRMF) */ + +#define ENET_MAC_FRMF_PM (1 << 0) /* Bit 0: promiscuous mode */ +#define ENET_MAC_FRMF_HUF (1 << 1) /* Bit 1: hash unicast filter */ +#define ENET_MAC_FRMF_HMF (1 << 2) /* Bit 2: hash multicast filter */ +#define ENET_MAC_FRMF_DAIFLT (1 << 3) /* Bit 3: destination address inverse filtering enable */ +#define ENET_MAC_FRMF_MFD (1 << 4) /* Bit 4: multicast filter disable */ +#define ENET_MAC_FRMF_BFRMD (1 << 5) /* Bit 5: broadcast frame disable */ + +#define ENET_MAC_FRMF_PCFRM_SHIFT (6) /* Bits 6-7: pass control frames */ +#define ENET_MAC_FRMF_PCFRM_MASK (3 << ENET_MAC_FRMF_PCFRM_SHIFT) +#define ENET_PCFRM_PREVENT_ALL (0 << ENET_MAC_FRMF_PCFRM_SHIFT) /* prevents all control frames */ +#define ENET_PCFRM_PREVENT_PAUSEFRAME (1 << ENET_MAC_FRMF_PCFRM_SHIFT) /* prevents all except Pause control frames */ +#define ENET_PCFRM_FORWARD_ALL (2 << ENET_MAC_FRMF_PCFRM_SHIFT) /* forwards all control frames */ +#define ENET_PCFRM_FORWARD_FILTERED (3 << ENET_MAC_FRMF_PCFRM_SHIFT) /* forwards all that pass address filter */ + +#define ENET_MAC_FRMF_SAIFLT (1 << 8) /* Bit 8: source address inverse filtering */ +#define ENET_MAC_FRMF_SAFLT (1 << 9) /* Bit 9: source address filter */ +#define ENET_MAC_FRMF_HPFLT (1 << 10) /* Bit 10: hash or perfect filter */ +#define ENET_MAC_FRMF_FAR (1 << 31) /* Bit 31: receive all frames */ + +/* MAC hash list high registers (GD32_ENET_MAC_HLH) */ + +/* MAC hash list low registers (GD32_ENET_MAC_HLL) */ + +/* MAC PHY control register (GD32_ENET_MAC_PHY_CTL) */ + +#define ENET_MAC_PHY_CTL_PB (1 << 0) /* Bit 0: PHY busy */ +#define ENET_MAC_PHY_CTL_PW (1 << 1) /* Bit 1: PHY write */ + +#define ENET_MAC_PHY_CTL_CLR_SHIFT (2) /* Bits 2-4: clock range */ +#define ENET_MAC_PHY_CTL_CLR_MASK (7 << ENET_MAC_PHY_CTL_CLR_SHIFT) +#define ENET_MDC_HCLK_DIV42 (0 << ENET_MAC_PHY_CTL_CLR_SHIFT) /* 000 60-100 MHz HCLK/42 */ +#define ENET_MDC_HCLK_DIV62 (1 << ENET_MAC_PHY_CTL_CLR_SHIFT) /* 001 100-150 MHz HCLK/62 */ +#define ENET_MDC_HCLK_DIV16 (2 << ENET_MAC_PHY_CTL_CLR_SHIFT) /* 010 20-35 MHz HCLK/16 */ +#define ENET_MDC_HCLK_DIV26 (3 << ENET_MAC_PHY_CTL_CLR_SHIFT) /* 011 35-60 MHz HCLK/26 */ +#define ENET_MDC_HCLK_DIV102 (4 << ENET_MAC_PHY_CTL_CLR_SHIFT) /* 100 150-240 MHz HCLK/102 */ + +#define ENET_MAC_PHY_CTL_PR_SHIFT (6) /* Bits 6-10: PHY register */ +#define ENET_MAC_PHY_CTL_PR_MASK (31 << ENET_MAC_PHY_CTL_PR_SHIFT) + +#define ENET_MAC_PHY_CTL_PA_SHIFT (11) /* Bits 11-15: PHY address */ +#define ENET_MAC_PHY_CTL_PA_MASK (31 << ENET_MAC_PHY_CTL_PA_SHIFT) + +/* MAC PHY data register (GD32_ENET_MAC_PHY_DATA) */ + +#define ENET_MAC_PHY_DATA_PD_MASK (0xFFFF) + +/* MAC flow control register (GD32_ENET_MAC_FCTL) */ + +#define ENET_MAC_FCTL_FLCBBKPA (1 << 0) /* Bit 0: flow control busy(in full duplex mode)/backpressure activate(in half duplex mode) */ +#define ENET_MAC_FCTL_TFCEN (1 << 1) /* Bit 1: transmit flow control enable */ +#define ENET_MAC_FCTL_RFCEN (1 << 2) /* Bit 2: receive flow control enable */ +#define ENET_MAC_FCTL_UPFDT (1 << 3) /* Bit 3: unicast pause frame detect */ + +#define ENET_MAC_FCTL_PLTS_SHIFT (4) /* Bits 4-5: pause low threshold */ +#define ENET_MAC_FCTL_PLTS_MASK (3 << ENET_MAC_FCTL_PLTS_SHIFT) +#define ENET_PAUSETIME_MINUS4 (0 << ENET_MAC_FCTL_PLTS_SHIFT) /* 00 pause time minus 4 slot times */ +#define ENET_PAUSETIME_MINUS28 (1 << ENET_MAC_FCTL_PLTS_SHIFT) /* 01 pause time minus 28 slot times */ +#define ENET_PAUSETIME_MINUS144 (2 << ENET_MAC_FCTL_PLTS_SHIFT) /* 10 pause time minus 144 slot times */ +#define ENET_PAUSETIME_MINUS256 (3 << ENET_MAC_FCTL_PLTS_SHIFT) /* 11 pause time minus 256 slot times */ + +#define ENET_MAC_FCTL_DZQP (1 << 7) /* Bit 7: disable zero-quanta pause */ + +#define ENET_MAC_FCTL_PTM_SHIFT (16) /* Bits 16-31: pause time */ +#define ENET_MAC_FCTL_PTM_MASK (0xFFFF << ENET_MAC_FCTL_PTM_SHIFT) + +/* MAC VLAN tag register (GD32_ENET_MAC_VLT) */ + +#define ENET_MAC_VLT_VLTI_SHIFT (0) /* Bits 0-15: VLAN tag identifier(for receive frames) */ +#define ENET_MAC_VLT_VLTI_MASK (0xFFFF << ENET_MAC_VLT_VLTI_SHIFT) + +#define ENET_MAC_VLT_VLTC (1 << 16) /* Bit 16: 12-bit VLAN tag comparison */ + +/* MAC remote wakeup frame filter register (GD32_ENET_MAC_RWFF) */ + +/* MAC wakeup management register (GD32_ENET_MAC_WUM) */ + +#define ENET_MAC_WUM_PWD (1 << 0) /* Bit 0: power down */ +#define ENET_MAC_WUM_MPEN (1 << 1) /* Bit 1: magic Packet enable */ +#define ENET_MAC_WUM_WFEN (1 << 2) /* Bit 2: wakeup frame enable */ +#define ENET_MAC_WUM_MPKR (1 << 5) /* Bit 5: magic packet received */ +#define ENET_MAC_WUM_WUFR (1 << 6) /* Bit 6: wakeup frame received */ +#define ENET_MAC_WUM_GU (1 << 9) /* Bit 9: global unicast */ +#define ENET_MAC_WUM_WUFFRPR (1 << 31) /* Bit 31: wakeup frame filter register pointer reset */ + +/* MAC debug register (GD32_ENET_MAC_DBG) */ + +#define ENET_MAC_DBG_MRNI (1 << 0) /* Bit 0: MAC receive state not idle */ + +#define ENET_MAC_DBG_RXAFS_SHIFT (1) /* Bits 1-2: Rx asynchronous FIFO status */ +#define ENET_MAC_DBG_RXAFS_MASK (3 << ENET_MAC_DBG_RXAFS_SHIFT) + +#define ENET_MAC_DBG_RXFW (1 << 4) /* Bit 4: RxFIFO is writing */ + +#define ENET_MAC_DBG_RXFRS_SHIFT (5) /* Bits 5-6: RxFIFO read controller status */ +#define ENET_MAC_DBG_RXFRS_MASK (3 << ENET_MAC_DBG_RXFRS_SHIFT) +#define ENET_MAC_DBG_RXFRS_IDLE (0 << ENET_MAC_DBG_RXFRS_SHIFT) /* 00: IDLE state */ +#define ENET_MAC_DBG_RXFRS_RFRAME (1 << ENET_MAC_DBG_RXFRS_SHIFT) /* 01: reading frame data */ +#define ENET_MAC_DBG_RXFRS_RSTATUS (2 << ENET_MAC_DBG_RXFRS_SHIFT) /* 10: reading frame status (or time-stamp) */ +#define ENET_MAC_DBG_RXFRS_FLUSHING (3 << ENET_MAC_DBG_RXFRS_SHIFT) /* 11: flushing the frame data and status */ + +#define ENET_MAC_DBG_RXFS_SHIFT (8) /* Bits 8-9: rxFIFO fill level */ +#define ENET_MAC_DBG_RXFS_MASK (3 << ENET_MAC_DBG_RXFS_SHIFT) +#define ENET_MAC_DBG_RXFS_EMPTY (0 << ENET_MAC_DBG_RXFS_SHIFT) /* 00: RxFIFO empty */ +#define ENET_MAC_DBG_RXFS_DEACT (1 << ENET_MAC_DBG_RXFS_SHIFT) /* 01: RxFIFO fill-level below flow-control de-activate threshold */ +#define ENET_MAC_DBG_RXFS_ACTIV (2 << ENET_MAC_DBG_RXFS_SHIFT) /* 10: RxFIFO fill-level above flow-control activate threshold */ +#define ENET_MAC_DBG_RXFS_FULL (3 << ENET_MAC_DBG_RXFS_SHIFT) /* 11: RxFIFO full */ + +#define ENET_MAC_DBG_MTNI (1 << 16) /* Bit 16: MAC transmit state not idle */ + +#define ENET_MAC_DBG_SOMT_SHIFT (17) /* Bits 17-18: status of mac transmitter */ +#define ENET_MAC_DBG_SOMT_MASK (3 << ENET_MAC_DBG_SOMT_SHIFT) +#define ENET_MAC_DBG_SOMT_IDLE (0 << ENET_MAC_DBG_SOMT_SHIFT) /* 00: idle */ +#define ENET_MAC_DBG_SOMT_WAITING (1 << ENET_MAC_DBG_SOMT_SHIFT) /* 01: waiting for Status of previous frame or IFG/backoff period to be over */ +#define ENET_MAC_DBG_SOMT_PAUSE (2 << ENET_MAC_DBG_SOMT_SHIFT) /* 10: generating and transmitting a Pause control frame */ +#define ENET_MAC_DBG_SOMT_FRAME (3 << ENET_MAC_DBG_SOMT_SHIFT) /* 11: transferring input frame for transmission */ + +#define ENET_MAC_DBG_PCS (1 << 19) /* Bit 19: pause condition status */ + +#define ENET_MAC_DBG_TXFRS_SHIFT (20) /* Bits 20-21: TxFIFO read operation status */ +#define ENET_MAC_DBG_TXFRS_MASK (3 << ENET_MAC_DBG_TXFRS_SHIFT) +#define ENET_MAC_DBG_TXFRS_IDLE (0 << ENET_MAC_DBG_TXFRS_SHIFT) /* 00: idle state */ +#define ENET_MAC_DBG_TXFRS_READ (1 << ENET_MAC_DBG_TXFRS_SHIFT) /* 01: read state */ +#define ENET_MAC_DBG_TXFRS_WAITING (2 << ENET_MAC_DBG_TXFRS_SHIFT) /* 10: waiting for TxStatus from MAC transmitter */ +#define ENET_MAC_DBG_TXFRS_WRITING (3 << ENET_MAC_DBG_TXFRS_SHIFT) /* 11: writing the received TxStatus or flushing the TxFIFO */ + +#define ENET_MAC_DBG_TXFW (1 << 22) /* Bit 22: TxFIFO is writing */ +#define ENET_MAC_DBG_TXFNE (1 << 24) /* Bit 24: TxFIFO not empty flag */ +#define ENET_MAC_DBG_TXFF (1 << 25) /* Bit 25: TxFIFO full flag */ + +/* MAC interrupt flag register (GD32_ENET_MAC_INTF) */ + +#define ENET_MAC_INTF_WUM (1 << 3) /* Bit 3: WUM status */ +#define ENET_MAC_INTF_MSC (1 << 4) /* Bit 4: MSC status */ +#define ENET_MAC_INTF_MSCR (1 << 5) /* Bit 5: MSC receive status */ +#define ENET_MAC_INTF_MSCT (1 << 6) /* Bit 6: MSC transmit status */ +#define ENET_MAC_INTF_TMST (1 << 9) /* Bit 9: timestamp trigger status */ + +/* MAC interrupt mask register (GD32_ENET_MAC_INTMSK) */ + +#define ENET_MAC_INTMSK_WUMIM (1 << 3) /* Bit 3: PMT interrupt mask */ +#define ENET_MAC_INTMSK_TMSTIM (1 << 9) /* Bit 9: Time stamp trigger interrupt mask */ +#define ENET_MAC_INTMSK_ALLINTS (ENET_MAC_INTMSK_WUMIM | ENET_MAC_INTMSK_TMSTIM) + +/* MAC address 0 high register (GD32_ENET_MAC_ADDR0H) */ + +#define ENET_MAC_ADDR0H_ADDR0H_SHIFT (0) /* Bits 0-15: MAC address0 high [47:32] */ +#define ENET_MAC_ADDR0H_ADDR0H_MASK (0xFFFF << ENET_MAC_ADDR0H_ADDR0H_SHIFT) + +#define ENET_MAC_ADDR0H_MO (1 << 31) /* Bit 31:always read 1 and must be kept */ + +/* MAC address 0 low register (GD32_ENET_MAC_ADDR0L) */ + +/* MAC address 1 high register (GD32_ENET_MAC_ADDR1H) */ + +#define ENET_MAC_ADDR1H_ADDR1H_SHIFT (0) /* Bits 0-15: MAC address1 high [47:32] */ +#define ENET_MAC_ADDR1H_ADDR1H_MASK (0xFFFF << ENET_MAC_ADDR1H_ADDR1H_SHIFT) + +#define ENET_MAC_ADDR1H_MB_SHIFT (24) /* Bits 24-29: mask byte control */ +#define ENET_MAC_ADDR1H_MB_MASK (0x3F << ENET_MAC_ADDR1H_MB_SHIFT) +#define ENET_MAC_ADDR1H_MB_40_47 (0x20 << ENET_MAC_ADDR1H_MB_SHIFT) /* Bit 29: ENET_MAC_ADDR1H[8-15] */ +#define ENET_MAC_ADDR1H_MB_32_39 (0x10 << ENET_MAC_ADDR1H_MB_SHIFT) /* Bit 28: ENET_MAC_ADDR1H[0-7] */ +#define ENET_MAC_ADDR1H_MB_24_31 (0x08 << ENET_MAC_ADDR1H_MB_SHIFT) /* Bit 27: ENET_MAC_ADDR1L[24-31] */ +#define ENET_MAC_ADDR1H_MB_16_23 (0x04 << ENET_MAC_ADDR1H_MB_SHIFT) /* Bit 26: ENET_MAC_ADDR1L[16-23] */ +#define ENET_MAC_ADDR1H_MB_8_15 (0x02 << ENET_MAC_ADDR1H_MB_SHIFT) /* Bit 25: ENET_MAC_ADDR1L[8-15] */ +#define ENET_MAC_ADDR1H_MB_0_7 (0x01 << ENET_MAC_ADDR1H_MB_SHIFT) /* Bit 24: ENET_MAC_ADDR1L[0-7] */ + +#define ENET_MAC_ADDR1H_SAF (1 << 30) /* Bit 30: source address filter */ +#define ENET_MAC_ADDR1H_AFE (1 << 31) /* Bit 31: address filter enable */ + +/* MAC address 1 low register (GD32_ENET_MAC_ADDR1L) */ + +/* MAC address 2 high register (GD32_ENET_MAC_ADDR2H) */ + +#define ENET_MAC_ADDR2H_ADDR2H_SHIFT (0) /* Bits 0-15: MAC address2 high [47:32] */ +#define ENET_MAC_ADDR2H_ADDR2H_MASK (0xFFFF << ENET_MAC_ADDR2H_ADDR2H_SHIFT) + +#define ENET_MAC_ADDR2H_MB_SHIFT (24) /* Bits 24-29: Mask byte control */ +#define ENET_MAC_ADDR2H_MB_MASK (0x3F << ENET_MAC_ADDR2H_MB_SHIFT) +#define ENET_MAC_ADDR2H_MB_40_47 (0x20 << ENET_MAC_ADDR2H_MB_SHIFT) /* Bit 29: ENET_MAC_ADDR2H[8-15] */ +#define ENET_MAC_ADDR2H_MB_32_39 (0x10 << ENET_MAC_ADDR2H_MB_SHIFT) /* Bit 28: ENET_MAC_ADDR2H[0-7] */ +#define ENET_MAC_ADDR2H_MB_24_31 (0x08 << ENET_MAC_ADDR2H_MB_SHIFT) /* Bit 27: ENET_MAC_ADDR2L[24-31] */ +#define ENET_MAC_ADDR2H_MB_16_23 (0x04 << ENET_MAC_ADDR2H_MB_SHIFT) /* Bit 26: ENET_MAC_ADDR2L[16-23] */ +#define ENET_MAC_ADDR2H_MB_8_15 (0x02 << ENET_MAC_ADDR2H_MB_SHIFT) /* Bit 25: ENET_MAC_ADDR2L[8-15] */ +#define ENET_MAC_ADDR2H_MB_0_7 (0x01 << ENET_MAC_ADDR2H_MB_SHIFT) /* Bit 24: ENET_MAC_ADDR2L[0-7] */ + +#define ENET_MAC_ADDR2H_SAF (1 << 30) /* Bit 30: source address filter */ +#define ENET_MAC_ADDR2H_AFE (1 << 31) /* Bit 31: address filter enable */ + +/* MAC address 2 low register (GD32_ENET_MAC_ADDR2L) */ + +/* MAC address 3 high register (GD32_ENET_MAC_ADDR3H) */ + +#define ENET_MAC_ADDR3H_ADDR3H_SHIFT (0) /* Bits 0-15: MAC address3 high [47:32] */ +#define ENET_MAC_ADDR3H_ADDR3H_MASK (0xFFFF << ENET_MAC_ADDR3H_ADDR3H_SHIFT) + +#define ENET_MAC_ADDR3H_MB_SHIFT (24) /* Bits 24-29: Mask byte control */ +#define ENET_MAC_ADDR3H_MB_MASK (0x3F << ENET_MAC_ADDR3H_MB_SHIFT) +#define ENET_MAC_ADDR3H_MB_40_47 (0x20 << ENET_MAC_ADDR3H_MB_SHIFT) /* Bit 29: ENET_MAC_ADDR3H[8-15] */ +#define ENET_MAC_ADDR3H_MB_32_39 (0x10 << ENET_MAC_ADDR3H_MB_SHIFT) /* Bit 28: ENET_MAC_ADDR3H[0-7] */ +#define ENET_MAC_ADDR3H_MB_24_31 (0x08 << ENET_MAC_ADDR3H_MB_SHIFT) /* Bit 27: ENET_MAC_ADDR3L[24-31] */ +#define ENET_MAC_ADDR3H_MB_16_23 (0x04 << ENET_MAC_ADDR3H_MB_SHIFT) /* Bit 26: ENET_MAC_ADDR3L[16-23] */ +#define ENET_MAC_ADDR3H_MB_8_15 (0x02 << ENET_MAC_ADDR3H_MB_SHIFT) /* Bit 25: ENET_MAC_ADDR3L[8-15] */ +#define ENET_MAC_ADDR3H_MB_0_7 (0x01 << ENET_MAC_ADDR3H_MB_SHIFT) /* Bit 24: ENET_MAC_ADDR3L[0-7] */ + +#define ENET_MAC_ADDR3H_SAF (1 << 30) /* Bit 30: source address filter */ +#define ENET_MAC_ADDR3H_AFE (1 << 31) /* Bit 31: address filter enable */ + +/* MAC address 3 low register (GD32_ENET_MAC_ADDR3L) */ + +/* MAC flow control threshold register (GD32_ENET_MAC_FCTH) */ + +#define ENET_MAC_FCTH_RFA_SHIFT (0) /* Bits 0-2 threshold of active flow control */ +#define ENET_MAC_FCTH_RFA_MASK (7 << ENET_MAC_FCTH_RFA_SHIFT) + +#define ENET_MAC_FCTH_RFD_SHIFT (4) /* Bits 4-6 threshold of deactive flow control */ +#define ENET_MAC_FCTH_RFD_MASK (7 << ENET_MAC_FCTH_RFD_SHIFT) + +/* MSC Registers */ + +/* MSC control register (GD32_ENET_MSC_CTL) */ + +#define ENET_MSC_CTL_CTR (1 << 0) /* Bit 0: counter reset */ +#define ENET_MSC_CTL_CTSR (1 << 1) /* Bit 1: counter stop rollover */ +#define ENET_MSC_CTL_RTOR (1 << 2) /* Bit 2: reset on read */ +#define ENET_MSC_CTL_MCFZ (1 << 3) /* Bit 3: MSC counter freeze */ +#define ENET_MSC_CTL_PMC (1 << 4) /* Bit 4: preset MSC counter */ +#define ENET_MSC_CTL_AFHPM (1 << 5) /* Bit 5: almost full or half preset mode */ + +/* MSC receive interrupt flag register (GD32_ENET_MSC_RINTF) */ + +#define ENET_MSC_RINTF_RFCE (1 << 5) /* Bit 5: received frames CRC error */ +#define ENET_MSC_RINTF_RFAE (1 << 6) /* Bit 6: received frames alignment error */ +#define ENET_MSC_RINTF_RGUF (1 << 17) /* Bit 17: received good unicast frames */ + +/* MSC transmit interrupt flag register (GD32_ENET_MSC_TINTF) */ + +#define ETH_MMCTI_TGFSC (1 << 14) /* Bit 14: transmitted good frames single collision */ +#define ETH_MMCTI_TGFMSC (1 << 15) /* Bit 15: transmitted good frames more single collision */ +#define ETH_MMCTI_TGF (1 << 21) /* Bit 21: transmitted good frames */ + +/* MSC receive interrupt mask register (GD32_ENET_MSC_RINTMSK) */ + +#define ENET_MSC_RINTMSK_RFCEIM (1 << 5) /* Bit 5: received frame CRC error interrupt mask */ +#define ENET_MSC_RINTMSK_RFAEIM (1 << 6) /* Bit 6: received frames alignment error interrupt mask */ +#define ENET_MSC_RINTMSK_RGUFIM (1 << 17) /* Bit 17: received good unicast frames interrupt mask */ + +/* MSC transmit interrupt mask register (GD32_ENET_MSC_TINTMSK) */ + +#define ENET_MSC_TINTMSK_TGFSCIM (1 << 14) /* Bit 14: received frame CRC error interrupt mask */ +#define ENET_MSC_TINTMSK_TGFMSCIM (1 << 15) /* Bit 15: received frames alignment error interrupt mask */ +#define ENET_MSC_TINTMSK_TGFIM (1 << 21) /* Bit 21: received good unicast frames interrupt mask */ + +/* MSC transmitted good frames after a single collision counter register + * (GD32_ENET_MSC_SCCNT) + */ + +/* MSC transmitted good frames after more than a single collision counter + * register (GD32_ENET_MSC_MSCCNT) + */ + +/* MSC transmitted good frames counter register (GD32_ENET_MSC_TGFCNT) */ + +/* MSC received frames with CRC error counter register + * (GD32_ENET_MSC_RFCECNT) + */ + +/* MSC received frames with alignment error counter register + * (GD32_ENET_MSC_RFAECNT) + */ + +/* MSC received good unicast frames counter register + * (GD32_ENET_MSC_RGUFCNT) + */ + +/* PTP Registers */ + +/* PTP time stamp control register (GD32_ENET_PTP_TSCTL) */ + +#define ENET_PTP_TSCTL_TMSEN (1 << 0) /* Bit 0: timestamp enable */ +#define ENET_PTP_TSCTL_TMSFCU (1 << 1) /* Bit 1: timestamp fine or coarse update */ +#define ENET_PTP_TSCTL_TMSSTI (1 << 2) /* Bit 2: timestamp system time initialize */ +#define ENET_PTP_TSCTL_TMSSTU (1 << 3) /* Bit 3: timestamp system time update */ +#define ENET_PTP_TSCTL_TMSITEN (1 << 4) /* Bit 4: timestamp interrupt trigger enable */ +#define ENET_PTP_TSCTL_TMSARU (1 << 5) /* Bit 5: timestamp addend register update */ + +#define ENET_PTP_TSCTL_ARFSEN (1 << 8) /* Bit 8: all received frames snapshot enable */ +#define ENET_PTP_TSCTL_SCROM (1 << 9) /* Bit 9: subsecond counter rollover mode */ +#define ENET_PTP_TSCTL_PFSV (1 << 10) /* Bit 10: PTP frame snooping version */ +#define ENET_PTP_TSCTL_ESEN (1 << 11) /* Bit 11: received Ethernet snapshot enable */ +#define ENET_PTP_TSCTL_IP6SEN (1 << 12) /* Bit 12: received IPv6 snapshot enable */ +#define ENET_PTP_TSCTL_IP4SEN (1 << 13) /* Bit 13: received IPv4 snapshot enable */ +#define ENET_PTP_TSCTL_ETMSEN (1 << 14) /* Bit 14: received event type message snapshot enable */ +#define ENET_PTP_TSCTL_MNMSEN (1 << 15) /* Bit 15: received master node message snapshot enable */ + +#define ENET_PTP_TSCTL_CKNT_SHIFT (16) /* Bits 16-17: clock node type for time stamp */ +#define ENET_PTP_TSCTL_CKNT_MASK (3 << ENET_PTP_TSCTL_CKNT_SHIFT) +#define ENET_CKNT_ORDINARY (0 << ENET_PTP_TSCTL_CKNT_SHIFT) /* 00: ordinary clock */ +#define ENET_CKNT_BOUNDARY (1 << ENET_PTP_TSCTL_CKNT_SHIFT) /* 01: boundary clock */ +#define ENET_CKNT_END_TO_END (2 << ENET_PTP_TSCTL_CKNT_SHIFT) /* 10: end-to-end transparent clock */ +#define ENET_CKNT_PEER_TO_PEER (3 << ENET_PTP_TSCTL_CKNT_SHIFT) /* 11: peer-to-peer transparent clock */ + +#define ENET_PTP_TSCTL_MAFEN (1 << 18) /* Bit 18: MAC address filter enable for PTP frame */ + +/* PTP subsecond increment register (GD32_ENET_PTP_SSINC) */ + +#define ENET_PTP_SSINC_STMSSI_MASK (0xFF) + +/* PTP time stamp high register (GD32_ENET_PTP_TSH) */ + +/* PTP time stamp low register (GD32_ENET_PTP_TSL) */ + +#define ENET_PTP_TSL_STMSS_MASK (0x7FFFFFFF) /* Bits 0-30: system time subseconds */ + +#define ENET_PTP_TSL_STS (1 << 31) /* Bit 31: system time sign */ + +/* PTP time stamp update high register (GD32_ENET_PTP_TSUH) */ + +/* PTP time stamp update low register (GD32_ENET_PTP_TSUL) */ + +#define ENET_PTP_TSUL_TMSUSS_MASK (0x7FFFFFFF) /* Bits 0-30: timestamp update subseconds */ + +#define ENET_PTP_TSUL_TMSUPNS (1 << 31) /* Bit 31: timestamp update positive or negative sign */ + +/* PTP time stamp addend register (GD32_ENET_PTP_TSADDAND) */ + +/* PTP expected time high register (GD32_ENET_PTP_ETH) */ + +/* PTP expected time low register (GD32_ENET_PTP_ETL) */ + +/* PTP time stamp flag register (GD32_ENET_PTP_TSF) */ + +#define ENET_PTP_TSF_TSSCO (1 << 0) /* Bit 0: timestamp second counter overflow */ +#define ENET_PTP_TSF_TTM (1 << 1) /* Bit 1: target time match */ + +/* PTP PPS control register (GD32_ENET_PTP_PPSCTL) */ + +#define ENET_PTP_PPSCTL_PPSOFC_SHIFT (0) /* Bits 0-3: PPS output frequency configuration */ +#define ENET_PTP_PPSCTL_PPSOFC_MASK (15 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) +#define ENET_PPSOFC_1HZ (0 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 1Hz frequency */ +#define ENET_PPSOFC_2HZ (1 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 2Hz frequency */ +#define ENET_PPSOFC_4HZ (2 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 4Hz frequency */ +#define ENET_PPSOFC_8HZ (3 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 8Hz frequency */ +#define ENET_PPSOFC_16HZ (4 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 16Hz frequency */ +#define ENET_PPSOFC_32HZ (5 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 32Hz frequency */ +#define ENET_PPSOFC_64HZ (6 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 64Hz frequency */ +#define ENET_PPSOFC_128HZ (7 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 128Hz frequency */ +#define ENET_PPSOFC_256HZ (8 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 256Hz frequency */ +#define ENET_PPSOFC_512HZ (9 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 512Hz frequency */ +#define ENET_PPSOFC_1KHZ (10 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 1024Hz frequency */ +#define ENET_PPSOFC_2KHZ (11 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 2048Hz frequency */ +#define ENET_PPSOFC_4KHZ (12 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 4096Hz frequency */ +#define ENET_PPSOFC_8KHZ (13 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 8192Hz frequency */ +#define ENET_PPSOFC_16KHZ (14 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 16384Hz frequency */ +#define ENET_PPSOFC_32KHZ (15 << ENET_PTP_PPSCTL_PPSOFC_SHIFT) /* PPS output 32768Hz frequency */ + +/* DMA Registers */ + +/* DMA bus control register (GD32_ENET_DMA_BCTL) */ + +#define ENET_DMA_BCTL_SWR (1 << 0) /* Bit 0: software reset */ +#define ENET_DMA_BCTL_DAB (1 << 1) /* Bit 1: DMA arbitration */ + +#define ENET_DMA_BCTL_DPSL_SHIFT (2) /* Bits 2-6: descriptor skip length */ +#define ENET_DMA_BCTL_DPSL_MASK (31 << ENET_DMA_BCTL_DPSL_SHIFT) +#define ENET_DMA_BCTL_DPSL(n) ((n) << ENET_DMA_BCTL_DPSL_SHIFT) + +#define ENET_DMA_BCTL_DFM (1 << 7) /* Bit 7: descriptor format mode */ + +#define ENET_DMA_BCTL_PGBL_SHIFT (8) /* Bits 8-13: programmable burst length */ +#define ENET_DMA_BCTL_PGBL_MASK (0x3F << ENET_DMA_BCTL_PGBL_SHIFT) +#define ENET_DMA_BCTL_PGBL(n) ((n) << ENET_DMA_BCTL_PGBL_SHIFT) /* n = 1, 2, 4, 8, 16, 32 */ + +#define ENET_DMA_BCTL_RTPR_SHIFT (14) /* Bits 14-15: Rx Tx priority ratio */ +#define ENET_DMA_BCTL_RTPR_MASK (3 << ENET_DMA_BCTL_RTPR_SHIFT) +#define ENET_ARBITRATION_RXTX_1_1 (0 << ENET_DMA_BCTL_RTPR_SHIFT) /* receive and transmit priority ratio is 1:1 */ +#define ENET_ARBITRATION_RXTX_2_1 (1 << ENET_DMA_BCTL_RTPR_SHIFT) /* receive and transmit priority ratio is 2:1 */ +#define ENET_ARBITRATION_RXTX_3_1 (2 << ENET_DMA_BCTL_RTPR_SHIFT) /* receive and transmit priority ratio is 3:1 */ +#define ENET_ARBITRATION_RXTX_4_1 (3 << ENET_DMA_BCTL_RTPR_SHIFT) /* receive and transmit priority ratio is 4:1 */ + +#define ENET_DMA_BCTL_FB (1 << 16) /* Bit 16: fixed burst */ + +#define ENET_DMA_BCTL_RXDP_SHIFT (17) /* Bits 17-22: Rx DMA PGBL */ +#define ENET_DMA_BCTL_RXDP_MASK (0x3F << ENET_DMA_BCTL_RXDP_SHIFT) +#define ENET_DMA_BCTL_RXDP(n) ((n) << ENET_DMA_BCTL_RXDP_SHIFT) /* n = 1, 2, 4, 8, 16, 32 */ + +#define ENET_DMA_BCTL_UIP (1 << 23) /* Bit 23: use independent PGBL */ +#define ENET_DMA_BCTL_FPBL (1 << 24) /* Bit 24: four times PGBL mod */ +#define ENET_DMA_BCTL_AA (1 << 25) /* Bit 25: address-aligned */ +#define ENET_DMA_BCTL_MB (1 << 26) /* Bit 26: mixed burst */ + +/* DMA transmit poll enable register (GD32_ENET_DMA_TPEN) */ + +/* DMA receive poll enable register (GD32_ENET_DMA_RPEN) */ + +/* DMA receive descriptor table address register (GD32_ENET_DMA_RDTADDR) */ + +/* DMA transmit descriptor table address register (GD32_ENET_DMA_TDTADDR) */ + +/* DMA status register (GD32_ENET_DMA_STAT) */ + +#define ENET_DMA_STAT_TS (1 << 0) /* Bit 0: transmit status */ +#define ENET_DMA_STAT_TPS (1 << 1) /* Bit 1: transmit process stopped status */ +#define ENET_DMA_STAT_TBU (1 << 2) /* Bit 2: transmit buffer unavailable status */ +#define ENET_DMA_STAT_TJT (1 << 3) /* Bit 3: transmit jabber timeout status */ +#define ENET_DMA_STAT_RO (1 << 4) /* Bit 4: receive overflow status */ +#define ENET_DMA_STAT_TU (1 << 5) /* Bit 5: transmit underflow status */ +#define ENET_DMA_STAT_RS (1 << 6) /* Bit 6: receive status */ +#define ENET_DMA_STAT_RBU (1 << 7) /* Bit 7: receive buffer unavailable status */ +#define ENET_DMA_STAT_RPS (1 << 8) /* Bit 8: receive process stopped status */ +#define ENET_DMA_STAT_RWT (1 << 9) /* Bit 9: receive watchdog timeout status */ +#define ENET_DMA_STAT_ET (1 << 10) /* Bit 10: early transmit status */ +#define ENET_DMA_STAT_FBE (1 << 13) /* Bit 13: fatal bus error status */ +#define ENET_DMA_STAT_ER (1 << 14) /* Bit 14: early receive status */ +#define ENET_DMA_STAT_AI (1 << 15) /* Bit 15: abnormal interrupt summary */ +#define ENET_DMA_STAT_NI (1 << 16) /* Bit 16: normal interrupt summary */ + +#define ENET_DMA_STAT_RP_SHIFT (17) /* Bits 17-19: receive process state */ +#define ENET_DMA_STAT_RP_MASK (7 << ENET_DMA_STAT_RP_SHIFT) +#define ENET_RX_STATE_STOPPED (0 << ENET_DMA_STAT_RP_SHIFT) /* 000: reset or stop rx command issued */ +#define ENET_RX_STATE_FETCHING (1 << ENET_DMA_STAT_RP_SHIFT) /* 001: fetching the Rx descriptor */ +#define ENET_RX_STATE_WAITING (3 << ENET_DMA_STAT_RP_SHIFT) /* 011: waiting for receive packet */ +#define ENET_RX_STATE_SUSPENDED (4 << ENET_DMA_STAT_RP_SHIFT) /* 100: Rx descriptor unavailable */ +#define ENET_RX_STATE_CLOSING (5 << ENET_DMA_STAT_RP_SHIFT) /* 101: closing receive descriptor */ +#define ENET_RX_STATE_QUEUING (6 << ENET_DMA_STAT_RP_SHIFT) /* 111: transferring the receive packet data from recevie buffer to host memory */ + +#define ENET_DMA_STAT_TP_SHIFT (20) /* Bits 20-22: transmit process state */ +#define ENET_DMA_STAT_TP_MASK (7 << ENET_DMA_STAT_TP_SHIFT) +#define ENET_TX_STATE_STOPPED (0 << ENET_DMA_STAT_TP_SHIFT) /* 000: reset or stop Tx Command issued */ +#define ENET_TX_STATE_FETCHING (1 << ENET_DMA_STAT_TP_SHIFT) /* 001: fetching the Tx descriptor */ +#define ENET_TX_STATE_WAITING (2 << ENET_DMA_STAT_TP_SHIFT) /* 010: waiting for status */ +#define ENET_TX_STATE_READING (3 << ENET_DMA_STAT_TP_SHIFT) /* 011: reading the data from host memory buffer and queuing it to transmit buffer */ +#define ENET_TX_STATE_SUSPENDED (6 << ENET_DMA_STAT_TP_SHIFT) /* 110: Tx descriptor unavailabe or transmit buffer underflow */ +#define ENET_TX_STATE_CLOSING (7 << ENET_DMA_STAT_TP_SHIFT) /* 111: closing Tx descriptor */ + +#define ENET_DMA_STAT_EB_SHIFT (23) /* Bits 23-25: error bits status */ +#define ENET_DMA_STAT_EB_MASK (7 << ENET_DMA_STAT_EB_SHIFT) +#define ENET_ERROR_TXDATA_TRANSFER (1 << ENET_DMA_STAT_EB_SHIFT) /* Bit 23 1 error during data transfer by TxDMA or RxDMA */ +#define ENET_ERROR_READ_TRANSFER (2 << ENET_DMA_STAT_EB_SHIFT) /* Bit 24 1 error during write transfer or read transfer */ +#define ENET_ERROR_DESC_ACCESS (4 << ENET_DMA_STAT_EB_SHIFT) /* Bit 25 1 error during descriptor or buffer access */ + +#define ENET_DMA_STAT_MSC (1 << 27) /* Bit 27: MSC status */ +#define ENET_DMA_STAT_WUM (1 << 28) /* Bit 28: WUM status */ +#define ENET_DMA_STAT_TST (1 << 29) /* Bit 29: timestamp trigger status */ + +/* DMA control register (GD32_ENET_DMA_CTL) */ + +#define ENET_DMA_CTL_SRE (1 << 1) /* Bit 1: start/stop receive enable */ +#define ENET_DMA_CTL_OSF (1 << 2) /* Bit 2: operate on second frame */ + +#define ENET_DMA_CTL_RTHC_SHIFT (3) /* Bits 3-4: receive threshold control */ +#define ENET_DMA_CTL_RTHC_MASK (3 << ENET_DMA_CTL_RTHC_SHIFT) +#define ENET_RX_THRESHOLD_64BYTES (0 << ENET_DMA_CTL_RTHC_SHIFT) /* threshold level is 64 Bytes */ +#define ENET_RX_THRESHOLD_32BYTES (1 << ENET_DMA_CTL_RTHC_SHIFT) /* threshold level is 32 Bytes */ +#define ENET_RX_THRESHOLD_96BYTES (2 << ENET_DMA_CTL_RTHC_SHIFT) /* threshold level is 96 Bytes */ +#define ENET_RX_THRESHOLD_128BYTES (3 << ENET_DMA_CTL_RTHC_SHIFT) /* threshold level is 128 Bytes */ + +#define ENET_DMA_CTL_FUF (1 << 6) /* Bit 6: forward undersized good frames */ +#define ENET_DMA_CTL_FERF (1 << 7) /* Bit 7: forward error frames */ +#define ENET_DMA_CTL_STE (1 << 13) /* Bit 13: start/stop transmission enable */ + +#define ENET_DMA_CTL_TTHC_SHIFT (14) /* Bits 14-16: transmit threshold control */ +#define ENET_DMA_CTL_TTHC_MASK (7 << ENET_DMA_CTL_TTHC_SHIFT) +#define ENET_TX_THRESHOLD_64BYTES (0 << ENET_DMA_CTL_TTHC_SHIFT) /* threshold level is 64 Bytes */ +#define ENET_TX_THRESHOLD_128BYTES (1 << ENET_DMA_CTL_TTHC_SHIFT) /* threshold level is 128 Bytes */ +#define ENET_TX_THRESHOLD_192BYTES (2 << ENET_DMA_CTL_TTHC_SHIFT) /* threshold level is 192 Bytes */ +#define ENET_TX_THRESHOLD_256BYTES (3 << ENET_DMA_CTL_TTHC_SHIFT) /* threshold level is 256 Bytes */ +#define ENET_TX_THRESHOLD_40BYTES (4 << ENET_DMA_CTL_TTHC_SHIFT) /* threshold level is 40 Bytes */ +#define ENET_TX_THRESHOLD_32BYTES (5 << ENET_DMA_CTL_TTHC_SHIFT) /* threshold level is 32 Bytes */ +#define ENET_TX_THRESHOLD_24BYTES (6 << ENET_DMA_CTL_TTHC_SHIFT) /* threshold level is 24 Bytes */ +#define ENET_TX_THRESHOLD_16BYTES (7 << ENET_DMA_CTL_TTHC_SHIFT) /* threshold level is 16 Bytes */ + +#define ENET_DMA_CTL_FTF (1 << 20) /* Bit 20: flush transmit FIFO */ +#define ENET_DMA_CTL_TSFD (1 << 21) /* Bit 21: transmit store-and-forward */ +#define ENET_DMA_CTL_DAFRF (1 << 24) /* Bit 24: disable flushing of received frames */ +#define ENET_DMA_CTL_RSFD (1 << 25) /* Bit 25: receive store-and-forward */ +#define ENET_DMA_CTL_DTCERFD (1 << 26) /* Bit 26: dropping of TCP/IP checksum error frames disable */ + +/* DMA interrupt enable register (GD32_ENET_DMA_INTEN) */ + +#define ENET_DMA_INTEN_TIE (1 << 0) /* Bit 0: transmit interrupt enable */ +#define ENET_DMA_INTEN_TPSIE (1 << 1) /* Bit 1: transmit process stopped interrupt enable */ +#define ENET_DMA_INTEN_TBUIE (1 << 2) /* Bit 2: transmit buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_TJTIE (1 << 3) /* Bit 3: transmit jabber timeout interrupt enable */ +#define ENET_DMA_INTEN_ROIE (1 << 4) /* Bit 4: receive overflow interrupt enable */ +#define ENET_DMA_INTEN_TUIE (1 << 5) /* Bit 5: transmit underflow interrupt enable */ +#define ENET_DMA_INTEN_RIE (1 << 6) /* Bit 6: receive interrupt enable */ +#define ENET_DMA_INTEN_RBUIE (1 << 7) /* Bit 7: receive buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_RPSIE (1 << 8) /* Bit 8: receive process stopped interrupt enable */ +#define ENET_DMA_INTEN_RWTIE (1 << 9) /* Bit 9: receive watchdog timeout interrupt enable */ +#define ENET_DMA_INTEN_ETIE (1 << 10) /* Bit 10: early transmit interrupt enable */ +#define ENET_DMA_INTEN_FBEIE (1 << 13) /* Bit 13: fatal bus error interrupt enable */ +#define ENET_DMA_INTEN_ERIE (1 << 14) /* Bit 14: early receive interrupt enable */ +#define ENET_DMA_INTEN_AIE (1 << 15) /* Bit 15: abnormal interrupt summary enable */ +#define ENET_DMA_INTEN_NIE (1 << 16) /* Bit 16: normal interrupt summary enable */ + +/* DMA missed frame and buffer overflow counter register + * (GD32_ENET_DMA_MFBOCNT) + */ + +#define ENET_DMA_MFBOCNT_MSFC_SHIFT (0) /* Bits 0-15: missed frames by the controller */ +#define ENET_DMA_MFBOCNT_MSFC_MASK (0xFFFF << ENET_DMA_MFBOCNT_MSFC_SHIFT) + +#define ENET_DMA_MFBOCNT_MSFA_SHIFT (17) /* Bits 17-27: missed frames by the application */ +#define ENET_DMA_MFBOCNT_MSFA_MASK (0x7FF << ENET_DMA_MFBOCNT_MSFC_SHIFT) + +/* DMA receive state watchdog counter register (GD32_ENET_DMA_RSWDC) */ + +#define ETH_DMARSWTR_MASK (0xFF) + +/* DMA current transmit descriptor address register (GD32_ENET_DMA_CTDADDR) */ + +/* DMA current receive descriptor address register (GD32_ENET_DMA_CRDADDR) */ + +/* DMA current transmit buffer address register (GD32-ENET_DMA_CTBADDR) */ + +/* DMA current receive buffer address register (GD32_ENET_DMA_CRBADDR) */ + +/* DMA Descriptors */ + +/* ENET DMA Tx descriptor TDES0 */ + +#define ENET_TDES0_DB (1 << 0) /* Bit 0: deferred */ +#define ENET_TDES0_UFE (1 << 1) /* Bit 1: underflow error */ +#define ENET_TDES0_EXD (1 << 2) /* Bit 2: excessive deferral */ + +#define ENET_TDES0_COCNT_SHIFT (3) /* Bits 3-6: collision count */ +#define ENET_TDES0_COCNT_MASK (15 << ENET_TDES0_COCNT_SHIFT) + +#define ENET_TDES0_VFRM (1 << 7) /* Bit 7: VLAN frame */ +#define ENET_TDES0_ECO (1 << 8) /* Bit 8: excessive collision */ +#define ENET_TDES0_LCO (1 << 9) /* Bit 9: late collision */ +#define ENET_TDES0_NCA (1 << 10) /* Bit 10: no carrier */ +#define ENET_TDES0_LCA (1 << 11) /* Bit 11: loss of carrier */ +#define ENET_TDES0_IPPE (1 << 12) /* Bit 12: IP payload error */ +#define ENET_TDES0_FRMF (1 << 13) /* Bit 13: frame flushed */ +#define ENET_TDES0_JT (1 << 14) /* Bit 14: jabber timeout */ +#define ENET_TDES0_ES (1 << 15) /* Bit 15: error summaryy */ +#define ENET_TDES0_IPHE (1 << 16) /* Bit 16: IP header error */ +#define ENET_TDES0_TTMSS (1 << 17) /* Bit 17: transmit timestamp status */ +#define ENET_TDES0_TCHM (1 << 20) /* Bit 20: the second address chained mode */ +#define ENET_TDES0_TERM (1 << 21) /* Bit 21: transmit end of ring mode */ + +#define ENET_TDES0_CM_SHIFT (22) /* Bits 22-23: checksum mode */ +#define ENET_TDES0_CM_MASK (3 << ENET_TDES0_CM_SHIFT) +#define ENET_CHECKSUM_DISABLE (0 << ENET_TDES0_CM_SHIFT) /* checksum insertion disabled */ +#define ENET_CHECKSUM_IPV4HEADER (1 << ENET_TDES0_CM_SHIFT) /* only IP header checksum calculation and insertion are enabled */ +#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT (2 << ENET_TDES0_CM_SHIFT) /* TCP/UDP/ICMP checksum insertion calculated but pseudo-header */ +#define ENET_CHECKSUM_TCPUDPICMP_FULL (3 << ENET_TDES0_CM_SHIFT) /* TCP/UDP/ICMP checksum insertion fully calculated */ + +#define ENET_TDES0_TTSEN (1 << 25) /* Bit 25: transmit timestamp function enable */ +#define ENET_TDES0_DPAD (1 << 26) /* Bit 26: disable adding pad */ +#define ENET_TDES0_DCRC (1 << 27) /* Bit 27: disable CRC */ +#define ENET_TDES0_FSG (1 << 28) /* Bit 28: first segment */ +#define ENET_TDES0_LSG (1 << 29) /* Bit 29: last segment */ +#define ENET_TDES0_INTC (1 << 30) /* Bit 30: interrupt on completion */ +#define ENET_TDES0_DAV (1 << 31) /* Bit 31: DAV bit */ + +/* ENET DMA Tx descriptor TDES1 */ + +#define ENET_TDES1_TB1S_SHIFT (0) /* Bits 0-12: transmit buffer 1 size */ +#define ENET_TDES1_TB1S_MASK (0x1FFF << ENET_TDES1_TB1S_SHIFT) + +#define ENET_TDES1_TB2S_SHIFT (16) /* Bits 16-28: transmit buffer 2 size */ +#define ENET_TDES1_TB2S_MASK (0x1FFF << ENET_TDES1_TB2S_SHIFT) + +/* ENET DMA Tx descriptor TDES2 (32-bit address) */ + +/* ENET DMA Tx descriptor TDES3 (32-bit address) */ + +/* ENET DMA Tx descriptor TDES6 (32-bit time stamp) */ + +/* ENET DMA Tx descriptor TDES7 (32-bit time stamp) */ + +/* ENET DMA Rx descriptor RDES0 */ + +#define ENET_RDES0_PCERR (1 << 0) /* Bit 0: payload checksum error */ +#define ENET_RDES0_EXSV (1 << 0) /* Bit 0: extended status valid */ +#define ENET_RDES0_CERR (1 << 1) /* Bit 1: CRC error */ +#define ENET_RDES0_DBERR (1 << 2) /* Bit 2: dribble bit error */ +#define ENET_RDES0_RERR (1 << 3) /* Bit 3: receive error */ +#define ENET_RDES0_RWDT (1 << 4) /* Bit 4: receive watchdog timeout */ +#define ENET_RDES0_FRMT (1 << 5) /* Bit 5: frame type */ +#define ENET_RDES0_LCO (1 << 6) /* Bit 6: late collision */ +#define ENET_RDES0_IPHERR (1 << 7) /* Bit 7: IP frame header error */ +#define ENET_RDES0_TSV (1 << 7) /* Bit 7: timestamp valid */ +#define ENET_RDES0_LDES (1 << 8) /* Bit 8: last descriptor */ +#define ENET_RDES0_FDES (1 << 9) /* Bit 9: first descriptor */ +#define ENET_RDES0_VTAG (1 << 10) /* Bit 10: VLAN tag */ +#define ENET_RDES0_OERR (1 << 11) /* Bit 11: overflow Error */ +#define ENET_RDES0_LERR (1 << 12) /* Bit 12: length error */ +#define ENET_RDES0_SAFF (1 << 13) /* Bit 13: source address filter fail */ +#define ENET_RDES0_DERR (1 << 14) /* Bit 14: descriptor error */ +#define ENET_RDES0_ERRS (1 << 15) /* Bit 15: error summary */ + +#define ENET_RDES0_FRML_SHIFT (16) /* Bits 16-29: frame length */ +#define ENET_RDES0_FRML_MASK (0x3FFF << ENET_RDES0_FRML_SHIFT) + +#define ENET_RDES0_DAFF (1 << 30) /* Bit 30: destination address filter fail */ +#define ENET_RDES0_DAV (1 << 31) /* Bit 31: descriptor available */ + +/* ENET DMA Rx descriptor RDES1 */ + +#define ENET_RDES1_RB1S_SHIFT (0) /* Bits 0-12: receive buffer 1 size */ +#define ENET_RDES1_RB1S_MASK (0x1FFF << ENET_RDES1_RB1S_SHIFT) + +#define ENET_RDES1_RCHM (1 << 14) /* Bit 14: receive chained mode for second address */ +#define ENET_RDES1_RERM (1 << 15) /* Bit 15: receive end of ring mode */ + +#define ENET_RDES1_RB2S_SHIFT (16) /* Bits 16-28: receive buffer 2 size */ +#define ENET_RDES1_RB2S_MASK (0x1FFF << ENET_RDES1_RB2S_SHIFT) + +#define ENET_RDES1_DINTC (1 << 31) /* Bit 31: disable interrupt on completion */ + +/* ENET DMA Rx descriptor RDES2 (32-bit address) */ + +/* ENET DMA Rx descriptor RDES3 (32-bit address) */ + +/* ENET DMA Rx descriptor RDES4 */ + +#define ENET_RDES4_IPPLDT_SHIFT (0) /* Bits 0-2: IP frame payload type */ +#define ENET_RDES4_IPPLDT_MASK (7 << ENET_RDES4_IPPLDT_SHIFT) +#define ENET_RDES4_IPPLDT_UDP (1 << ENET_RDES4_IPPLDT_SHIFT) /* UDP payload in IP datagram */ +#define ENET_RDES4_IPPLDT_TCP (2 << ENET_RDES4_IPPLDT_SHIFT) /* TCP payload in IP datagram */ +#define ENET_RDES4_IPPLDT_ICMP (3 << ENET_RDES4_IPPLDT_SHIFT) /* ICMP payload in IP datagram */ + +#define ENET_RDES4_IPHERR (1 << 3) /* Bit 3: IP frame header error */ +#define ENET_RDES4_IPPLDERR (1 << 4) /* Bit 4: IP frame payload error */ +#define ENET_RDES4_IPCKSB (1 << 5) /* Bit 5: IP frame checksum bypassed */ +#define ENET_RDES4_IPF4 (1 << 6) /* Bit 6: IP frame in version 4 */ +#define ENET_RDES4_IPF6 (1 << 7) /* Bit 7: IP frame in version 6 */ + +#define ENET_RDES4_PTPMT_SHIFT (8) /* Bits 8-11: PTP message type */ +#define ENET_RDES4_PTPMT_MASK (15 << ENET_RDES4_PTPMT_SHIFT) +#define ENET_RDES4_PTPMT_NONE (0 << ENET_RDES4_PTPMT_SHIFT) /* No PTP message received */ +#define ENET_RDES4_PTPMT_SYNC (1 << ENET_RDES4_PTPMT_SHIFT) /* SYNC (all clock types) */ +#define ENET_RDES4_PTPMT_FOLLOWUP (2 << ENET_RDES4_PTPMT_SHIFT) /* Follow_Up (all clock types) */ +#define ENET_RDES4_PTPMT_DELAYREQ (3 << ENET_RDES4_PTPMT_SHIFT) /* Delay_Req (all clock types) */ +#define ENET_RDES4_PTPMT_DELAYRESP (4 << ENET_RDES4_PTPMT_SHIFT) /* Delay_Resp (all clock types) */ +#define ENET_RDES4_PTPMT_PDELREQAM (5 << ENET_RDES4_PTPMT_SHIFT) /* Pdelay_Req (in peer-to-peer transparent clock) or Announce (in ordinary or boundary clock) */ +#define ENET_RDES4_PTPMT_PDELREQMM (6 << ETH_RDES4_PMT_SHIFT) /* Pdelay_Resp (in peer-to-peer transparent clock) or Management (in ordinary or boundary clock) */ +#define ENET_RDES4_PTPMT_PDELREQFUS (7 << ETH_RDES4_PMT_SHIFT) /* Pdelay_Resp_Follow_Up (in peer-to-peer transparent clock) or Signaling (for ordinary or boundary clock) */ + +#define ENET_RDES4_PTPOEF (1 << 12) /* Bit 12: ENET_RDES4_PTPMT */ +#define ENET_RDES4_PTPVF (1 << 13) /* Bit 13: PTP version format */ + +/* ENET DMA Rx descriptor RDES5 (Reserved) */ + +/* ENET DMA Rx descriptor RDES6 (32-bit time stamp) */ + +/* ENET DMA Rx descriptor RDES7 (32-bit time stamp) */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Ethernet TX DMA Descriptor */ + +struct enet_txdesc_s +{ + /* Normal DMA descriptor words */ + + volatile uint32_t tdes0; /* Status */ + volatile uint32_t tdes1; /* Control and buffer1/2 lengths */ + volatile uint32_t tdes2; /* Buffer1 address pointer */ + volatile uint32_t tdes3; /* Buffer2 or next descriptor address pointer */ + + /* Enhanced DMA descriptor words with time stamp */ + +#ifdef CONFIG_GD32F4_ENET_ENHANCEDDESC + volatile uint32_t tdes4; /* Reserved */ + volatile uint32_t tdes5; /* Reserved */ + volatile uint32_t tdes6; /* Time Stamp Low value for transmit and receive */ + volatile uint32_t tdes7; /* Time Stamp High value for transmit and receive */ +#endif +}; + +/* Ethernet RX DMA Descriptor */ + +struct enet_rxdesc_s +{ + volatile uint32_t rdes0; /* Status */ + volatile uint32_t rdes1; /* Control and buffer1/2 lengths */ + volatile uint32_t rdes2; /* Buffer1 address pointer */ + volatile uint32_t rdes3; /* Buffer2 or next descriptor address pointer */ + + /* Enhanced DMA descriptor words with time stamp and PTP support */ + +#ifdef CONFIG_GD32F4_ENET_ENHANCEDDESC + volatile uint32_t rdes4; /* Extended status for PTP receive descriptor */ + volatile uint32_t rdes5; /* Reserved */ + volatile uint32_t rdes6; /* Time Stamp Low value for transmit and receive */ + volatile uint32_t rdes7; /* Time Stamp High value for transmit and receive */ +#endif +}; + +#endif /* __ASSEMBLY__ */ +#endif /* GD32_NETHERNET > 0 */ +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_ENET_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_exti.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_exti.h new file mode 100644 index 0000000000..15510ee18d --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_exti.h @@ -0,0 +1,143 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_exti.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_EXTI_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_EXTI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define GD32_NEXTI 23 +#define GD32_EXTI_MASK 0x007fffff + +#define GD32_EXTI_BIT(n) (1 << (n)) + +/* Register Offsets *********************************************************/ + +#define GD32_EXTI_INTEN_OFFSET 0x0000 /* interrupt enable register offset */ +#define GD32_EXTI_EVEN_OFFSET 0x0004 /* event enable register offset */ +#define GD32_EXTI_RTEN_OFFSET 0x0008 /* rising edge trigger enable register offset */ +#define GD32_EXTI_FTEN_OFFSET 0x000c /* falling trigger enable register offset */ +#define GD32_EXTI_SWIEV_OFFSET 0x0010 /* software interrupt event register offset */ +#define GD32_EXTI_PD_OFFSET 0x0014 /* pending register offset */ + +/* Register Addresses *******************************************************/ + +#define GD32_EXTI_INTEN (GD32_EXTI_BASE+GD32_EXTI_INTEN_OFFSET) /* interrupt enable register */ +#define GD32_EXTI_EVEN (GD32_EXTI_BASE+GD32_EXTI_EVEN_OFFSET) /* event enable register */ +#define GD32_EXTI_RTEN (GD32_EXTI_BASE+GD32_EXTI_RTEN_OFFSET) /* rising edge trigger enable register */ +#define GD32_EXTI_FTEN (GD32_EXTI_BASE+GD32_EXTI_FTEN_OFFSET) /* falling trigger enable register */ +#define GD32_EXTI_SWIEV (GD32_EXTI_BASE+GD32_EXTI_SWIEV_OFFSET) /* software interrupt event register */ +#define GD32_EXTI_PD (GD32_EXTI_BASE+GD32_EXTI_PD_OFFSET) /* pending register */ + +/* Register Bitfield Definitions ********************************************/ + +/* EXTI lines > 15 are associated with internal devices: */ + +# define EXTI_PVD_LINE (1 << 16) /* EXTI line 16 is connected to the PVD output */ +# define EXTI_RTC_ALARM (1 << 17) /* EXTI line 17 is connected to the RTC Alarm event */ +# define EXTI_OTGFS_WAKEUP (1 << 18) /* EXTI line 18 is connected to the USB OTG FS Wakeup event */ +# define EXTI_ETH_WAKEUP (1 << 19) /* EXTI line 19 is connected to the Ethernet Wakeup event */ +# define EXTI_OTGHS_WAKEUP (1 << 20) /* EXTI line 20 is connected to the USB OTG HS Wakeup event */ +# define EXTI_RTC_TAMPER (1 << 21) /* EXTI line 21 is connected to the RTC Tamper and TimeStamp events */ +# define EXTI_RTC_TIMESTAMP (1 << 21) /* EXTI line 21 is connected to the RTC Tamper and TimeStamp events */ +# define EXTI_RTC_WAKEUP (1 << 22) /* EXTI line 22 is connected to the RTC Wakeup event */ + +/* Interrupt mask register */ + +#define EXTI_INTEN_BIT(n) GD32_EXTI_BIT(n) /* 1=Interrupt request from line x is not masked */ +#define EXTI_INTEN_SHIFT (0) /* Bits 0-X: Interrupt Mask for all lines */ +#define EXTI_INTEN_MASK GD32_EXTI_MASK + +/* Event mask register */ + +#define EXTI_EVEN_BIT(n) GD32_EXTI_BIT(n) /* 1=Event request from line x is not mask */ +#define EXTI_EVEN_SHIFT (0) /* Bits Bits 0-X: Event Mask for all lines */ +#define EXTI_EVEN_MASK GD32_EXTI_MASK + +/* Rising Trigger selection register */ + +#define EXTI_RTEN_BIT(n) GD32_EXTI_BIT(n) /* 1=Rising trigger enabled (for Event and Interrupt) for input line */ +#define EXTI_RTEN_SHIFT (0) /* Bits 0-X: Rising trigger event configuration bit for all lines */ +#define EXTI_RTEN_MASK GD32_EXTI_MASK + +/* Falling Trigger selection register */ + +#define EXTI_FTEN_BIT(n) GD32_EXTI_BIT(n) /* 1=Falling trigger enabled (for Event and Interrupt) for input line */ +#define EXTI_FTEN_SHIFT (0) /* Bits 0-X: Falling trigger event configuration bitfor all lines */ +#define EXTI_FTEN_MASK GD32_EXTI_MASK + +/* Software interrupt event register */ + +#define EXTI_SWIEV_BIT(n) GD32_EXTI_BIT(n) /* 1=Sets the corresponding pending bit in EXTI_PR */ +#define EXTI_SWIEV_SHIFT (0) /* Bits 0-X: Software Interrupt for all lines */ +#define EXTI_SWIEV_MASK GD32_EXTI_MASK + +/* Pending register */ + +#define EXTI_PD_BIT(n) GD32_EXTI_BIT(n) /* 1=Selected trigger request occurred */ +#define EXTI_PD_SHIFT (0) /* Bits 0-X: Pending bit for all lines */ +#define EXTI_PD_MASK GD32_EXTI_MASK + +/* EXTI line number */ +#define EXTI_0 GD32_EXTI_BIT(0) /* EXTI line 0 */ +#define EXTI_1 GD32_EXTI_BIT(1) /* EXTI line 1 */ +#define EXTI_2 GD32_EXTI_BIT(2) /* EXTI line 2 */ +#define EXTI_3 GD32_EXTI_BIT(3) /* EXTI line 3 */ +#define EXTI_4 GD32_EXTI_BIT(4) /* EXTI line 4 */ +#define EXTI_5 GD32_EXTI_BIT(5) /* EXTI line 5 */ +#define EXTI_6 GD32_EXTI_BIT(6) /* EXTI line 6 */ +#define EXTI_7 GD32_EXTI_BIT(7) /* EXTI line 7 */ +#define EXTI_8 GD32_EXTI_BIT(8) /* EXTI line 8 */ +#define EXTI_9 GD32_EXTI_BIT(9) /* EXTI line 9 */ +#define EXTI_10 GD32_EXTI_BIT(10) /* EXTI line 10 */ +#define EXTI_11 GD32_EXTI_BIT(11) /* EXTI line 11 */ +#define EXTI_12 GD32_EXTI_BIT(12) /* EXTI line 12 */ +#define EXTI_13 GD32_EXTI_BIT(13) /* EXTI line 13 */ +#define EXTI_14 GD32_EXTI_BIT(14) /* EXTI line 14 */ +#define EXTI_15 GD32_EXTI_BIT(15) /* EXTI line 15 */ +#define EXTI_16 GD32_EXTI_BIT(16) /* EXTI line 16 */ +#define EXTI_17 GD32_EXTI_BIT(17) /* EXTI line 17 */ +#define EXTI_18 GD32_EXTI_BIT(18) /* EXTI line 18 */ +#define EXTI_19 GD32_EXTI_BIT(19) /* EXTI line 19 */ +#define EXTI_20 GD32_EXTI_BIT(20) /* EXTI line 20 */ +#define EXTI_21 GD32_EXTI_BIT(21) /* EXTI line 21 */ +#define EXTI_22 GD32_EXTI_BIT(22) /* EXTI line 22 */ + +/* External interrupt and event */ + +#define EXTI_INTERRUPT 0 /* EXTI interrupt mode */ +#define EXTI_EVENT 1 /* EXTI event mode */ + +/* Interrupt trigger mode */ +#define EXTI_TRIG_RISING 0 /* EXTI rising edge trigger */ +#define EXTI_TRIG_FALLING 1 /* EXTI falling edge trigger */ +#define EXTI_TRIG_BOTH 2 /* EXTI rising and falling edge trigger */ +#define EXTI_TRIG_NONE 3 /* None EXTI edge trigger */ + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_EXTI_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_fmc.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_fmc.h new file mode 100644 index 0000000000..4ae58a1bbf --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_fmc.h @@ -0,0 +1,297 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_fmc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_FMC_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_FMC_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define _K(x) ((x)*1024) + +#if !defined(CONFIG_GD32F4_FLASH_CONFIG_DEFAULT) && \ + !defined(CONFIG_GD32F4_FLASH_CONFIG_E) && \ + !defined(CONFIG_GD32F4_FLASH_CONFIG_F) && \ + !defined(CONFIG_GD32F4_FLASH_CONFIG_I) && \ + !defined(CONFIG_GD32F4_FLASH_CONFIG_K) +# define CONFIG_GD32F4_FLASH_CONFIG_DEFAULT +#endif + +/* Flash default size is 512K */ +#if defined(CONFIG_GD32F4_FLASH_CONFIG_DEFAULT) + +# define GD32_FMC_NSECTORS 8 +# define GD32_FMC_SIZE _K((4 * 16) + (1 * 64) + (3 * 128)) +# define GD32_FMC_SIZES {_K(16), _K(16), _K(16), _K(16), \ + _K(64),_K(128), _K(128), _K(128)} + +/* Override of the FLASH Has been Chosen */ + +#elif !defined(CONFIG_GD32F4_FLASH_CONFIG_DEFAULT) + +# if defined(CONFIG_GD32F4_FLASH_CONFIG_E) +# define GD32_FMC_NSECTORS 8 +# define GD32_FMC_SIZE _K((4 * 16) + (1 * 64) + (3 * 128)) +# define GD32_FMC_SIZES {_K(16), _K(16), _K(16), _K(16), \ + _K(64), _K(128), _K(128), _K(128)} + +# elif defined(CONFIG_GD32F4_FLASH_CONFIG_G) +# define GD32_FMC_NSECTORS 12 +# define GD32_FMC_SIZE _K((4 * 16) + (1 * 64) + (7 * 128)) +# define GD32_FMC_SIZES {_K(16), _K(16), _K(16), _K(16), \ + _K(64), _K(128), _K(128), _K(128), \ + _K(128), _K(128), _K(128), _K(128)} + +# elif defined(CONFIG_GD32F4_FLASH_CONFIG_I) +# define GD32_FMC_NSECTORS 24 +# define GD32_FMC_SIZE _K((4 * 16) + (1 * 64) + (7 * 128)) + \ + _K((4 * 16) + (1 * 64) + (7 * 128)) +# define GD32_FMC_SIZES {_K(16), _K(16), _K(16), _K(16), \ + _K(64), _K(128), _K(128), _K(128), \ + _K(128), _K(128), _K(128), _K(128), \ + _K(16), _K(16), _K(16), _K(16), \ + _K(64), _K(128), _K(128), _K(128), \ + _K(128), _K(128), _K(128), _K(128)} + +# elif defined(CONFIG_GD32F4_FLASH_CONFIG_K) +# define GD32_FMC_NSECTORS 28 +# define GD32_FMC_SIZE _K((4 * 16) + (1 * 64) + (7 * 128)) + \ + _K((4 * 16) + (1 * 64) + (7 * 128)) +# define GD32_FMC_SIZES {_K(16), _K(16), _K(16), _K(16), \ + _K(64), _K(128), _K(128), _K(128), \ + _K(128), _K(128), _K(128), _K(128), \ + _K(16), _K(16), _K(16), _K(16), \ + _K(64), _K(128), _K(128), _K(128), \ + _K(128), _K(128), _K(128), _K(128)}, \ + _K(256), _K(256), _K(256), _K(256)} + +# endif + +#endif /* !defined(CONFIG_GD32F4_FLASH_CONFIG_DEFAULT) */ + +/* Register Offsets *********************************************************/ + +#define GD32_FMC_WS_OFFSET 0x0000 /* FMC wait state register offset */ +#define GD32_FMC_KEY_OFFSET 0x0004 /* FMC unlock key register offset */ +#define GD32_FMC_OBKEY_OFFSET 0x0008 /* FMC option byte register offset */ +#define GD32_FMC_STAT_OFFSET 0x000C /* FMC status register offset */ +#define GD32_FMC_CTL_OFFSET 0x0010 /* FMC control register offset */ +#define GD32_FMC_OBCTL0_OFFSET 0x0014 /* FMC option byte control register 0 offset */ +#define GD32_FMC_OBCTL1_OFFSET 0x0018 /* FMC option byte control register 1 offset */ +#define GD32_FMC_WSEN_OFFSET 0x00FC /* FMC wait state enable register offset */ +#define GD32_FMC_PID_OFFSET 0x0100 /* FMC product ID register offset */ + +/* Register Addresses *******************************************************/ + +#define GD32_FMC_WS (GD32_FMC_BASE+GD32_FMC_WS_OFFSET) /* FMC wait state register */ +#define GD32_FMC_KEY (GD32_FMC_BASE+GD32_FMC_KEY_OFFSET) /* FMC unlock key register */ +#define GD32_FMC_OBKEY (GD32_FMC_BASE+GD32_FMC_OBKEY_OFFSET) /* FMC option byte register */ +#define GD32_FMC_STAT (GD32_FMC_BASE+GD32_FMC_STAT_OFFSET) /* FMC status register */ +#define GD32_FMC_CTL (GD32_FMC_BASE+GD32_FMC_CTL_OFFSET) /* FMC control register */ +#define GD32_FMC_OBCTL0 (GD32_FMC_BASE+GD32_FMC_OBCTL0_OFFSET) /* FMC option byte control register 0 */ +#define GD32_FMC_OBCTL1 (GD32_FMC_BASE+GD32_FMC_OBCTL1_OFFSET) /* FMC option byte control register 1 */ +#define GD32_FMC_WSEN (GD32_FMC_BASE+GD32_FMC_WSEN_OFFSET) /* FMC wait state enable register */ +#define GD32_FMC_PID (GD32_FMC_BASE+GD32_FMC_PID_OFFSET) /* FMC product ID register */ + +/* Register Bitfield Definitions ********************************************/ + +/* FMC wait state register */ + +#define FMC_WS_WSCNT_SHIFT (0) +#define FMC_WS_WSCNT_MASK (15 << FMC_WS_WSCNT_SHIFT) +#define FMC_WC_WSCNT(n) ((n) << FMC_WS_WSCNT_SHIFT) +#define FMC_WS_WSCNT_0 WC_WSCNT(0) /* FMC 0 wait */ +#define FMC_WS_WSCNT_1 WC_WSCNT(1) /* FMC 1 wait */ +#define FMC_WS_WSCNT_2 WC_WSCNT(2) /* FMC 2 wait */ +#define FMC_WS_WSCNT_3 WC_WSCNT(3) /* FMC 3 wait */ +#define FMC_WS_WSCNT_4 WC_WSCNT(4) /* FMC 4 wait */ +#define FMC_WS_WSCNT_5 WC_WSCNT(5) /* FMC 5 wait */ +#define FMC_WS_WSCNT_6 WC_WSCNT(6) /* FMC 6 wait */ +#define FMC_WS_WSCNT_7 WC_WSCNT(7) /* FMC 7 wait */ +#define FMC_WS_WSCNT_8 WC_WSCNT(8) /* FMC 8 wait */ +#define FMC_WS_WSCNT_9 WC_WSCNT(9) /* FMC 9 wait */ +#define FMC_WS_WSCNT_10 WC_WSCNT(10) /* FMC 10 wait */ +#define FMC_WS_WSCNT_11 WC_WSCNT(11) /* FMC 11 wait */ +#define FMC_WS_WSCNT_12 WC_WSCNT(12) /* FMC 12 wait */ +#define FMC_WS_WSCNT_13 WC_WSCNT(13) /* FMC 13 wait */ +#define FMC_WS_WSCNT_14 WC_WSCNT(14) /* FMC 14 wait */ +#define FMC_WS_WSCNT_15 WC_WSCNT(15) /* FMC 15 wait */ + +/* FMC status register */ + +#define FMC_STAT_END (1 << 0) /* Bit 0: end of operation flag bit */ +#define FMC_STAT_OPERR (1 << 1) /* Bit 1: flash operation error flag bit */ +#define FMC_STAT_WPERR (1 << 4) /* Bit 4: erase/Program protection error flag bit */ +#define FMC_STAT_PGMERR (1 << 5) /* Bit 5: program size not match error flag bit */ +#define FMC_STAT_PGSERR (1 << 6) /* Bit 6: program sequence error flag bit */ +#define FMC_STAT_RDDERR (1 << 7) /* Bit 7: read D-bus protection error flag bit */ +#define FMC_STAT_BUSY (1 << 16) /* Bit 16: flash busy flag bit */ + +/* FMC control register */ + +#define FMC_CTL_PG (1 << 0) /* Bit 0: main flash program command bit */ +#define FMC_CTL_SER (1 << 1) /* Bit 1: main flash sector erase command bit */ +#define FMC_CTL_MER0 (1 << 2) /* Bit 2: main flash mass erase for bank0 command bit */ + +#define FMC_CTL_SN_SHIFT (3) /* Bits 3-7: select which sector number to be erased */ +#define FMC_CTL_SN_MASK (31 << FMC_CTL_SN_SHIFT) +#define FMC_CTL_SN(n) ((n) << FMC_CTL_SN_SHIFT) /* Sector n, n=0..11 */ +#define FMC_CTL_SN_0_11(n) ((n) << FMC_CTL_SN_SHIFT) /* Sector n, n=0..11 */ +#define FMC_CTL_SN_12_23(n) ((n+4) << FMC_CTL_SN_SHIFT)) /* Sector n, n=12..23 */ +#define FMC_CTL_SN_24_27(n) ((n-12) << FMC_CTL_SN_SHIFT)) /* Sector n, n=24..27 */ +#define FMC_CTL_SN_0 (0 << FMC_CTL_SN_SHIFT) /* sector 0 */ +#define FMC_CTL_SN_1 (1 << FMC_CTL_SN_SHIFT) /* sector 1 */ +#define FMC_CTL_SN_2 (2 << FMC_CTL_SN_SHIFT) /* sector 2 */ +#define FMC_CTL_SN_3 (3 << FMC_CTL_SN_SHIFT) /* sector 3 */ +#define FMC_CTL_SN_4 (4 << FMC_CTL_SN_SHIFT) /* sector 4 */ +#define FMC_CTL_SN_5 (5 << FMC_CTL_SN_SHIFT) /* sector 5 */ +#define FMC_CTL_SN_6 (6 << FMC_CTL_SN_SHIFT) /* sector 6 */ +#define FMC_CTL_SN_7 (7 << FMC_CTL_SN_SHIFT) /* sector 7 */ +#define FMC_CTL_SN_8 (8 << FMC_CTL_SN_SHIFT) /* sector 8 */ +#define FMC_CTL_SN_9 (9 << FMC_CTL_SN_SHIFT) /* sector 9 */ +#define FMC_CTL_SN_10 (10 << FMC_CTL_SN_SHIFT) /* sector 10 */ +#define FMC_CTL_SN_11 (11 << FMC_CTL_SN_SHIFT) /* sector 11 */ +#define FMC_CTL_SN_12 (16 << FMC_CTL_SN_SHIFT) /* sector 12 */ +#define FMC_CTL_SN_13 (17 << FMC_CTL_SN_SHIFT) /* sector 13 */ +#define FMC_CTL_SN_14 (18 << FMC_CTL_SN_SHIFT) /* sector 14 */ +#define FMC_CTL_SN_15 (19 << FMC_CTL_SN_SHIFT) /* sector 15 */ +#define FMC_CTL_SN_16 (20 << FMC_CTL_SN_SHIFT) /* sector 16 */ +#define FMC_CTL_SN_17 (21 << FMC_CTL_SN_SHIFT) /* sector 17 */ +#define FMC_CTL_SN_18 (22 << FMC_CTL_SN_SHIFT) /* sector 18 */ +#define FMC_CTL_SN_19 (23 << FMC_CTL_SN_SHIFT) /* sector 19 */ +#define FMC_CTL_SN_20 (24 << FMC_CTL_SN_SHIFT) /* sector 20 */ +#define FMC_CTL_SN_21 (25 << FMC_CTL_SN_SHIFT) /* sector 21 */ +#define FMC_CTL_SN_22 (26 << FMC_CTL_SN_SHIFT) /* sector 22 */ +#define FMC_CTL_SN_23 (27 << FMC_CTL_SN_SHIFT) /* sector 23 */ +#define FMC_CTL_SN_24 (12 << FMC_CTL_SN_SHIFT) /* sector 24 */ +#define FMC_CTL_SN_25 (13 << FMC_CTL_SN_SHIFT) /* sector 25 */ +#define FMC_CTL_SN_26 (14 << FMC_CTL_SN_SHIFT) /* sector 26 */ +#define FMC_CTL_SN_27 (15 << FMC_CTL_SN_SHIFT) /* sector 27 */ + +#define FMC_CTL_PSZ_SHIFT (8) /* Bits 8-9: Program size */ +#define FMC_CTL_PSZ_MASK (3 << FMC_CTL_PSZ_SHIFT) +#define FMC_CTL_PSZ_BYTE (0 << FMC_CTL_PSZ_SHIFT) /* FMC program by byte access */ +#define FMC_CTL_PSZ_HALF_WORD (1 << FMC_CTL_PSZ_SHIFT) /* FMC program by half-word access */ +#define FMC_CTL_PSZ_WORD (2 << FMC_CTL_PSZ_SHIFT) /* FMC program by word access */ + +#define FMC_CTL_MER1 (1 << 15) /* Bit 15: main flash mass erase for bank1 command bit */ +#define FMC_CTL_START (1 << 16) /* Bit 16: send erase command to FMC bit */ +#define FMC_CTL_ENDIE (1 << 24) /* Bit 24: end of operation interrupt enable bit */ +#define FMC_CTL_ERRIE (1 << 25) /* Bit 25: error interrupt enable bit */ +#define FMC_CTL_LK (1 << 31) /* Bit 31: FMC_CTL lock bit */ + +/* FMC option byte control register 0 */ + +#define FMC_OBCTL0_OB_LK (1 << 0) /* Bit 0: FMC_OBCTL0 lock bit */ +#define FMC_OBCTL0_OB_START (1 << 1) /* Bit 1: send option byte change command to FMC bit */ + +#define FMC_OBCTL0_BOR_TH_SHIFT (2) /* Bits 2-3: Boption byte BOR threshold value */ +#define FMC_OBCTL0_BOR_TH_MASK (3 << FLASH_OPTCR_BORLEV_SHIFT) +#define FMC_OB_BOR_TH_VALUE3 (0 << FLASH_OPTCR_BORLEV_SHIFT) /* BOR threshold value 3 */ +#define FMC_OB_BOR_TH_VALUE2 (1 << FLASH_OPTCR_BORLEV_SHIFT) /* BOR threshold value 2 */ +#define FMC_OB_BOR_TH_VALUE1 (2 << FLASH_OPTCR_BORLEV_SHIFT) /* BOR threshold value 1 */ +#define FMC_OB_BOR_TH_VALUE0 (3 << FLASH_OPTCR_BORLEV_SHIFT) /* no BOR function */ + +#define FMC_OBCTL0_BB (1 << 4) /* Bit 4: option byte boot bank value */ +#define FMC_OBCTL0_NWDG_HW (1 << 5) /* Bit 5: option byte watchdog value */ +#define FMC_OBCTL0_NRST_DPSLP (1 << 5) /* Bit 6: option byte deepsleep value */ +#define FMC_OBCTL0_NRST_STDBY (1 << 7) /* Bit 7: option byte standby value */ + +#define FMC_OBCTL0_SPC_SHIFT (8) /* Bits 8-15: option byte Security Protection code */ +#define FMC_OBCTL0_SPC_MASK (0xff << FMC_OBCTL0_SPC_SHIFT) +#define FMC_OBCTL0_WP0_SHIFT (16) /* Bits 16-27: erase/program protection of each sector when DRP is 0 */ +#define FMC_OBCTL0_WP0_MASK (0xfff << FMC_OBCTL0_WP0_SHIFT) + +#define FMC_OBCTL0_DBS (1 << 30) /* Bit 30: double banks or single bank selection when flash size is 1M bytes */ +#define FMC_OBCTL0_DRP (1 << 31) /* Bit 31: D-bus read protection bit */ + +/* FMC option byte control register 1 */ + +#define FMC_OBCTL1_WP1_SHIFT (16) /* Bits 16-27: erase/program protection of each sector when DRP is 0 */ +#define FMC_OBCTL1_WP1_MASK (0xfff << FMC_OBCTL1_WP1_SHIFT) + +/* FMC wait state enable register */ +#define FMC_WSEN_WSEN (1 << 0) /* FMC wait state enable bit */ + +/* FMC unlock key */ +#define FMC_UNLOCK_KEY0 (0x45670123) /* Unlock key 0 */ +#define FMC_UNLOCK_KEY1 (0xCDEF89AB) /* Unlock key 1 */ +#define FMC_OB_UNLOCK_KEY0 (0x08192A3B) /* ob unlock key 0 */ +#define FMC_OB_UNLOCK_KEY1 (0x4C5D6E7F) /* ob unlock key 1 */ + +/* option bytes write protection */ +#define FMC_OB_WP_0 (0x00000001) /* erase/program protection of sector 0 */ +#define FMC_OB_WP_1 (0x00000002) /* erase/program protection of sector 1 */ +#define FMC_OB_WP_2 (0x00000004) /* erase/program protection of sector 2 */ +#define FMC_OB_WP_3 (0x00000008) /* erase/program protection of sector 3 */ +#define FMC_OB_WP_4 (0x00000010) /* erase/program protection of sector 4 */ +#define FMC_OB_WP_5 (0x00000020) /* erase/program protection of sector 5 */ +#define FMC_OB_WP_6 (0x00000040) /* erase/program protection of sector 6 */ +#define FMC_OB_WP_7 (0x00000080) /* erase/program protection of sector 7 */ +#define FMC_OB_WP_8 (0x00000100) /* erase/program protection of sector 8 */ +#define FMC_OB_WP_9 (0x00000200) /* erase/program protection of sector 9 */ +#define FMC_OB_WP_10 (0x00000400) /* erase/program protection of sector 10 */ +#define FMC_OB_WP_11 (0x00000800) /* erase/program protection of sector 11 */ +#define FMC_OB_WP_12 (0x00010000) /* erase/program protection of sector 12 */ +#define FMC_OB_WP_13 (0x00020000) /* erase/program protection of sector 13 */ +#define FMC_OB_WP_14 (0x00040000) /* erase/program protection of sector 14 */ +#define FMC_OB_WP_15 (0x00080000) /* erase/program protection of sector 15 */ +#define FMC_OB_WP_16 (0x00100000) /* erase/program protection of sector 16 */ +#define FMC_OB_WP_17 (0x00200000) /* erase/program protection of sector 17 */ +#define FMC_OB_WP_18 (0x00400000) /* erase/program protection of sector 18 */ +#define FMC_OB_WP_19 (0x00800000) /* erase/program protection of sector 19 */ +#define FMC_OB_WP_20 (0x01000000) /* erase/program protection of sector 20 */ +#define FMC_OB_WP_21 (0x02000000) /* erase/program protection of sector 21 */ +#define FMC_OB_WP_22 (0x04000000) /* erase/program protection of sector 22 */ +#define FMC_OB_WP_23_27 (0x08000000) /* erase/program protection of sector 23~27 */ +#define FMC_OB_WP_ALL (0x0FFF0FFF) /* erase/program protection of all sectors */ + +/* option bytes D-bus read protection */ +#define FMC_OB_DRP_0 (0x00000001) /* D-bus read protection protection of sector 0 */ +#define FMC_OB_DRP_1 (0x00000002) /* D-bus read protection protection of sector 1 */ +#define FMC_OB_DRP_2 (0x00000004) /* D-bus read protection protection of sector 2 */ +#define FMC_OB_DRP_3 (0x00000008) /* D-bus read protection protection of sector 3 */ +#define FMC_OB_DRP_4 (0x00000010) /* D-bus read protection protection of sector 4 */ +#define FMC_OB_DRP_5 (0x00000020) /* D-bus read protection protection of sector 5 */ +#define FMC_OB_DRP_6 (0x00000040) /* D-bus read protection protection of sector 6 */ +#define FMC_OB_DRP_7 (0x00000080) /* D-bus read protection protection of sector 7 */ +#define FMC_OB_DRP_8 (0x00000100) /* D-bus read protection protection of sector 8 */ +#define FMC_OB_DRP_9 (0x00000200) /* D-bus read protection protection of sector 9 */ +#define FMC_OB_DRP_10 (0x00000400) /* D-bus read protection protection of sector 10 */ +#define FMC_OB_DRP_11 (0x00000800) /* D-bus read protection protection of sector 11 */ +#define FMC_OB_DRP_12 (0x00010000) /* D-bus read protection protection of sector 12 */ +#define FMC_OB_DRP_13 (0x00020000) /* D-bus read protection protection of sector 13 */ +#define FMC_OB_DRP_14 (0x00040000) /* D-bus read protection protection of sector 14 */ +#define FMC_OB_DRP_15 (0x00080000) /* D-bus read protection protection of sector 15 */ +#define FMC_OB_DRP_16 (0x00100000) /* D-bus read protection protection of sector 16 */ +#define FMC_OB_DRP_17 (0x00200000) /* D-bus read protection protection of sector 17 */ +#define FMC_OB_DRP_18 (0x00400000) /* D-bus read protection protection of sector 18 */ +#define FMC_OB_DRP_19 (0x00800000) /* D-bus read protection protection of sector 19 */ +#define FMC_OB_DRP_20 (0x01000000) /* D-bus read protection protection of sector 20 */ +#define FMC_OB_DRP_21 (0x02000000) /* D-bus read protection protection of sector 21 */ +#define FMC_OB_DRP_22 (0x04000000) /* D-bus read protection protection of sector 22 */ +#define FMC_OB_DRP_23_27 (0x08000000) /* D-bus read protection protection of sector 23~27 */ +#define FMC_OB_DRP_ALL (0x0FFF0FFF) /* D-bus read protection protection of all sectors */ + +/* FMC time out */ +#define FMC_TIMEOUT_COUNT (0x4FFFFFFF) /* count to judge of FMC timeout */ + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_FMC_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_gpio.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_gpio.h new file mode 100644 index 0000000000..ef7ca4d53d --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_gpio.h @@ -0,0 +1,217 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_gpio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32_HARDWARE_GD32F4XX_GPIO_H +#define __ARCH_ARM_SRC_GD32_HARDWARE_GD32F4XX_GPIO_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* GPIOx(x=A,B,C,D,E,F,G,H,I) definitions ***********************************/ +#define GD32_GPIOA_BASE (GD32_GPIO_BASE + 0x00000000) +#define GD32_GPIOB_BASE (GD32_GPIO_BASE + 0x00000400) +#define GD32_GPIOC_BASE (GD32_GPIO_BASE + 0x00000800) +#define GD32_GPIOD_BASE (GD32_GPIO_BASE + 0x00000c00) +#define GD32_GPIOE_BASE (GD32_GPIO_BASE + 0x00001000) +#define GD32_GPIOF_BASE (GD32_GPIO_BASE + 0x00001400) +#define GD32_GPIOG_BASE (GD32_GPIO_BASE + 0x00001800) +#define GD32_GPIOH_BASE (GD32_GPIO_BASE + 0x00001c00) +#define GD32_GPIOI_BASE (GD32_GPIO_BASE + 0x00002000) + +/* Register Offsets *********************************************************/ + +#define GD32_GPIO_CTL_OFFSET 0x0000 /* GPIO port control register offfset */ +#define GD32_GPIO_OMODE_OFFSET 0x0004 /* GPIO port output mode register offfset */ +#define GD32_GGPIO_OSPD_OFFSET 0x0008 /* GPIO port output speed register offfset */ +#define GD32_GPIO_PUD_OFFSET 0x000c /* GPIO port pull-up/pull-down register offfset */ +#define GD32_GPIO_ISTAT_OFFSET 0x0010 /* GPIO port input status register offfset */ +#define GD32_GPIO_OCTL_OFFSET 0x0014 /* GPIO port output control register offfset */ +#define GD32_GPIO_BOP_OFFSET 0x0018 /* GPIO port bit operation register offfset */ +#define GD32_GPIO_LOCK_OFFSET 0x001c /* GPIO port configuration lock register offfset */ +#define GD32_GPIO_AFSEL0_OFFSET 0x0020 /* GPIO alternate function selected register 0 offfset */ +#define GD32_GPIO_AFSEL1_OFFSET 0x0024 /* GPIO alternate function selected register 1 offfset */ +#define GD32_GPIO_BC_OFFSET 0x0028 /* GPIO bit clear register offfset */ +#define GD32_GPIO_TG_OFFSET 0x002c /* GPIO port bit toggle register offfset */ + +/* Register Addresses *******************************************************/ + +#define GD32_GPIOA GD32_GPIOA_BASE +#define GD32_GPIOB GD32_GPIOB_BASE +#define GD32_GPIOC GD32_GPIOC_BASE +#define GD32_GPIOD GD32_GPIOD_BASE +#define GD32_GPIOE GD32_GPIOE_BASE +#define GD32_GPIOF GD32_GPIOF_BASE +#define GD32_GPIOG GD32_GPIOG_BASE +#define GD32_GPIOH GD32_GPIOH_BASE +#define GD32_GPIOI GD32_GPIOI_BASE + +#define GD32_GPIO_CTL(gpiox) ((gpiox)+GD32_GPIO_CTL_OFFSET) /* GPIO port control register */ +#define GD32_GPIO_OMODE(gpiox) ((gpiox)+GD32_GPIO_OMODE_OFFSET) /* GPIO port output mode register */ +#define GD32_GPIO_OSPD(gpiox) ((gpiox)+GD32_GGPIO_OSPD_OFFSET) /* GPIO port output speed register */ +#define GD32_GPIO_PUD(gpiox) ((gpiox)+GD32_GPIO_PUD_OFFSET) /* GPIO port pull-up/pull-down register */ +#define GD32_GPIO_ISTAT(gpiox) ((gpiox)+GD32_GPIO_ISTAT_OFFSET) /* GPIO port input status register */ +#define GD32_GPIO_OCTL(gpiox) ((gpiox)+GD32_GPIO_OCTL_OFFSET) /* GPIO port output control register */ +#define GD32_GPIO_BOP(gpiox) ((gpiox)+GD32_GPIO_BOP_OFFSET) /* GPIO port bit operation register */ +#define GD32_GPIO_LOCK(gpiox) ((gpiox)+GD32_GPIO_LOCK_OFFSET) /* GPIO port configuration lock register */ +#define GD32_GPIO_AFSEL0(gpiox) ((gpiox)+GD32_GPIO_AFSEL0_OFFSET) /* GPIO alternate function selected register 0 */ +#define GD32_GPIO_AFSEL1(gpiox) ((gpiox)+GD32_GPIO_AFSEL1_OFFSET) /* GPIO alternate function selected register 1 */ +#define GD32_GPIO_BC(gpiox) ((gpiox)+GD32_GPIO_BC_OFFSET) /* GPIO bit clear register */ +#define GD32_GPIO_TG(gpiox) ((gpiox)+GD32_GPIO_TG_OFFSET) /* GPIO port bit toggle register */ + +/* Register Bitfield Definitions ********************************************/ + +/* GPIO port control register */ + +#define GPIO_MODE_INPUT (0) /* Input mode */ +#define GPIO_MODE_OUTPUT (1) /* Output mode */ +#define GPIO_MODE_AF (2) /* Alternate function mode */ +#define GPIO_MODE_ANALOG (3) /* Analog mode */ + +#define GPIO_MODE_SHIFT(n) ((n) << 1) +#define GPIO_MODE_MASK(n) (3 << GPIO_MODE_SHIFT(n)) + +#define GPIO_MODE0_MASK (3 << GPIO_MODE_SHIFT(0)) +#define GPIO_MODE1_MASK (3 << GPIO_MODE_SHIFT(1)) +#define GPIO_MODE2_MASK (3 << GPIO_MODE_SHIFT(2)) +#define GPIO_MODE3_MASK (3 << GPIO_MODE_SHIFT(3)) +#define GPIO_MODE4_MASK (3 << GPIO_MODE_SHIFT(4)) +#define GPIO_MODE5_MASK (3 << GPIO_MODE_SHIFT(5)) +#define GPIO_MODE6_MASK (3 << GPIO_MODE_SHIFT(6)) +#define GPIO_MODE7_MASK (3 << GPIO_MODE_SHIFT(7)) +#define GPIO_MODE8_MASK (3 << GPIO_MODE_SHIFT(8)) +#define GPIO_MODE9_MASK (3 << GPIO_MODE_SHIFT(9)) +#define GPIO_MODE10_MASK (3 << GPIO_MODE_SHIFT(10)) +#define GPIO_MODE11_MASK (3 << GPIO_MODE_SHIFT(11)) +#define GPIO_MODE12_MASK (3 << GPIO_MODE_SHIFT(12)) +#define GPIO_MODE13_MASK (3 << GPIO_MODE_SHIFT(13)) +#define GPIO_MODE14_MASK (3 << GPIO_MODE_SHIFT(14)) +#define GPIO_MODE15_MASK (3 << GPIO_MODE_SHIFT(15)) + +/* GPIO port output mode register */ + +#define GPIO_OTYPE_OD(n) (1 << (n)) /* 1=Output open drain mode */ +#define GPIO_OTYPE_PP(n) (0) /* 0=Output push pull mode */ + +/* GPIO port output speed register */ + +#define GPIO_OSPEED_2MHZ (0) /* Output max speed 2MHz */ +#define GPIO_OSPEED_25MHZ (1) /* Output max speed 25MHz */ +#define GPIO_OSPEED_50MHZ (2) /* Output max speed 50MHz */ +#define GPIO_OSPEED_200MHZ (3) /* Output max speed 200MHz */ + +#define GPIO_OSPEED_SHIFT(n) ((n) << 1) +#define GPIO_OSPEED_MASK(n) (3 << GPIO_OSPEED_SHIFT(n)) + +#define GPIO_OSPEED0_MASK (3 << GPIO_OSPEED_SHIFT(0)) +#define GPIO_OSPEED1_MASK (3 << GPIO_OSPEED_SHIFT(1)) +#define GPIO_OSPEED2_MASK (3 << GPIO_OSPEED_SHIFT(2)) +#define GPIO_OSPEED3_MASK (3 << GPIO_OSPEED_SHIFT(3)) +#define GPIO_OSPEED4_MASK (3 << GPIO_OSPEED_SHIFT(4)) +#define GPIO_OSPEED5_MASK (3 << GPIO_OSPEED_SHIFT(5)) +#define GPIO_OSPEED6_MASK (3 << GPIO_OSPEED_SHIFT(6)) +#define GPIO_OSPEED7_MASK (3 << GPIO_OSPEED_SHIFT(7)) +#define GPIO_OSPEED8_MASK (3 << GPIO_OSPEED_SHIFT(8)) +#define GPIO_OSPEED9_MASK (3 << GPIO_OSPEED_SHIFT(9)) +#define GPIO_OSPEED10_MASK (3 << GPIO_OSPEED_SHIFT(10)) +#define GPIO_OSPEED11_MASK (3 << GPIO_OSPEED_SHIFT(11)) +#define GPIO_OSPEED12_MASK (3 << GPIO_OSPEED_SHIFT(12)) +#define GPIO_OSPEED13_MASK (3 << GPIO_OSPEED_SHIFT(13)) +#define GPIO_OSPEED14_MASK (3 << GPIO_OSPEED_SHIFT(14)) +#define GPIO_OSPEED15_MASK (3 << GPIO_OSPEED_SHIFT(15)) + +/* GPIO port pull-up/pull-down register */ + +#define GPIO_PUPD_NONE (0) /* Floating mode, no pull-up and pull-down resistors */ +#define GPIO_PUPD_PULLUP (1) /* With pull-up resistor */ +#define GPIO_PUPD_PULLDOWN (2) /* With pull-up resistor */ + +#define GPIO_PUPD_SHIFT(n) ((n) << 1) +#define GPIO_PUPD_MASK(n) (3 << GPIO_PUPD_SHIFT(n)) + +#define GPIO_PUPD0_MASK (3 << GPIO_PUPD_SHIFT(0)) +#define GPIO_PUPD1_MASK (3 << GPIO_PUPD_SHIFT(1)) +#define GPIO_PUPD2_MASK (3 << GPIO_PUPD_SHIFT(2)) +#define GPIO_PUPD3_MASK (3 << GPIO_PUPD_SHIFT(3)) +#define GPIO_PUPD4_MASK (3 << GPIO_PUPD_SHIFT(4)) +#define GPIO_PUPD5_MASK (3 << GPIO_PUPD_SHIFT(5)) +#define GPIO_PUPD6_MASK (3 << GPIO_PUPD_SHIFT(6)) +#define GPIO_PUPD7_MASK (3 << GPIO_PUPD_SHIFT(7)) +#define GPIO_PUPD8_MASK (3 << GPIO_PUPD_SHIFT(8)) +#define GPIO_PUPD9_MASK (3 << GPIO_PUPD_SHIFT(9)) +#define GPIO_PUPD10_MASK (3 << GPIO_PUPD_SHIFT(10)) +#define GPIO_PUPD11_MASK (3 << GPIO_PUPD_SHIFT(11)) +#define GPIO_PUPD12_MASK (3 << GPIO_PUPD_SHIFT(12)) +#define GPIO_PUPD13_MASK (3 << GPIO_PUPD_SHIFT(13)) +#define GPIO_PUPD14_MASK (3 << GPIO_PUPD_SHIFT(14)) +#define GPIO_PUPD15_MASK (3 << GPIO_PUPD_SHIFT(15)) + +/* GPIO port input status register */ + +#define GPIO_ISTAT(n) (1 << (n)) + +/* GPIO port output control register */ + +#define GPIO_OCTL(n) (1 << (n)) + +/* GPIO port bit operation register */ + +#define GPIO_BOP_SET(n) (1 << (n)) +#define GPIO_BOP_CLEAR(n) (1 << ((n)+16)) + +/* GPIO port configuration lock register */ + +#define GPIO_LOCK(n) (1 << (n)) +#define GPIO_LOCK_LKK (1 << 16) /* Lock key */ + +/* GPIO alternate function selected register 0/1 */ + +#define GPIO_AF_SHIFT(n) ((n) << 2) +#define GPIO_AF_MASK(n) (15 << GPIO_AF_SHIFT(n)) + +#define GPIO_AFSEL0_SEL0_MASK (15 << GPIO_AF_SHIFT(0)) +#define GPIO_AFSEL0_SEL1_MASK (15 << GPIO_AF_SHIFT(1)) +#define GPIO_AFSEL0_SEL2_MASK (15 << GPIO_AF_SHIFT(2)) +#define GPIO_AFSEL0_SEL3_MASK (15 << GPIO_AF_SHIFT(3)) +#define GPIO_AFSEL0_SEL4_MASK (15 << GPIO_AF_SHIFT(4)) +#define GPIO_AFSEL0_SEL5_MASK (15 << GPIO_AF_SHIFT(5)) +#define GPIO_AFSEL0_SEL6_MASK (15 << GPIO_AF_SHIFT(6)) +#define GPIO_AFSEL0_SEL7_MASK (15 << GPIO_AF_SHIFT(7)) + +#define GPIO_AFSEL1_SEL8_MASK (15 << GPIO_AF_SHIFT(0)) +#define GPIO_AFSEL1_SEL9_MASK (15 << GPIO_AF_SHIFT(1)) +#define GPIO_AFSEL1_SEL10_MASK (15 << GPIO_AF_SHIFT(2)) +#define GPIO_AFSEL1_SEL11_MASK (15 << GPIO_AF_SHIFT(3)) +#define GPIO_AFSEL1_SEL12_MASK (15 << GPIO_AF_SHIFT(4)) +#define GPIO_AFSEL1_SEL13_MASK (15 << GPIO_AF_SHIFT(5)) +#define GPIO_AFSEL1_SEL14_MASK (15 << GPIO_AF_SHIFT(6)) +#define GPIO_AFSEL1_SEL15_MASK (15 << GPIO_AF_SHIFT(7)) + +/* GPIO bit clear register */ + +#define GPIO_BC_SET(n) (1 << (n)) + +/* GPIO port bit toggle register */ +#define GPIO_TG_SET(n) (1 << (n)) + +/* GPIO pin definitions */ +#define GPIO_PIN(n) (1 << (n)) /* Bit n: Pin n, n=0-15 */ + +#endif /* __ARCH_ARM_SRC_GD32_HARDWARE_GD32F4XX_GPIO_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_memorymap.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_memorymap.h new file mode 100644 index 0000000000..aa5f4cb1f3 --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_memorymap.h @@ -0,0 +1,38 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_memorymap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_MEMORYMAP_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip.h" + +#if defined(CONFIG_GD32F4_GD32F450) +# include "hardware/gd32f450_memorymap.h" + +#else +# error "Unsupported GD32F4 memory map" +#endif + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_MEMORYMAP_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_pinmap.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_pinmap.h new file mode 100644 index 0000000000..0d0943d784 --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_pinmap.h @@ -0,0 +1,39 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_pinmap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_PINMAP_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_PINMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* GD32 F4 Family ***********************************************************/ + +#if defined(CONFIG_GD32F4_GD32F450) +# include "hardware/gd32f450_pinmap.h" + +#else +# error "No pinmap file for this GD32 chip" +#endif + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_PINMAP_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_pmu.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_pmu.h new file mode 100644 index 0000000000..e66dcf388e --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_pmu.h @@ -0,0 +1,133 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_pmu.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_PMU_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_PMU_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define GD32_PMU_CTL_OFFSET 0x0000 /* Power control register offset */ +#define GD32_PMU_CS_OFFSET 0x0004 /* Power control and status register offset */ + +/* Register Addresses *******************************************************/ + +#define GD32_PMU_CTL (GD32_PMU_BASE+GD32_PMU_CTL_OFFSET) /* Power control register */ +#define GD32_PMU_CS (GD32_PMU_BASE+GD32_PMU_CS_OFFSET) /* Power control and status register */ + +/* Register Bitfield Definitions ********************************************/ + +/* Power control register */ + +#define PMU_CTL_LDOLP (1 << 0) /* Bit 0: LDO low power mode */ +#define PMU_CTL_STBMOD (1 << 1) /* Bit 1: Standby mode */ +#define PMU_CTL_WURST (1 << 2) /* Bit 2: wakeup flag reset */ +#define PMU_CTL_STBRST (1 << 3) /* Bit 3: Standby flag reset */ +#define PMU_CTL_LVDEN (1 << 4) /* Bit 4: Low voltage detector enable */ + +#define PMU_CTL_LVDT_SHIFT (5) /* Bits 5-7: Low voltage detector threshold */ +#define PMU_CTL_LVDT_MASK (7 << PMU_CTL_LVDT_SHIFT) +# define PMU_CTL_LVDT(n) ((n) << PMU_CTL_LVDT_SHIFT) +# define PMU_LVDT_0 PMU_CTL_LVDT(0) /* Voltage threshold is 2.1V */ +# define PMU_LVDT_1 PMU_CTL_LVDT(1) /* Voltage threshold is 2.3V */ +# define PMU_LVDT_2 PMU_CTL_LVDT(2) /* Voltage threshold is 2.4V */ +# define PMU_LVDT_3 PMU_CTL_LVDT(3) /* Voltage threshold is 2.6V */ +# define PMU_LVDT_4 PMU_CTL_LVDT(4) /* Voltage threshold is 2.7V */ +# define PMU_LVDT_5 PMU_CTL_LVDT(5) /* Voltage threshold is 2.9V */ +# define PMU_LVDT_6 PMU_CTL_LVDT(6) /* Voltage threshold is 3.0V */ +# define PMU_LVDT_7 PMU_CTL_LVDT(7) /* Voltage threshold is 3.1V */ + +#define PMU_CTL_BKPWEN (1 << 8) /* Bit 8: Backup domain write enable */ +#define PMU_CTL_LDLP (1 << 10) /* Bit 10: Low-driver mode when use low power LDO */ +#define PMU_CTL_LDNP (1 << 11) /* Bit 11: Low-driver mode when use normal power LDO */ + +#define PMU_CTL_LDOVS_SHIFT (14) /* Bit 14-15: LDO output voltage select */ +#define PMU_CTL_LDOVS_MASK (3 << PMU_CTL_LDOVS_SHIFT) +# define PMU_CTL_LDOVS(n) ((n) << PMU_CTL_LDOVS_SHIFT) +# define PMU_LDOVS_LOW PMU_CTL_LDOVS(1) /* LDO output voltage low mode */ +# define PMU_LDOVS_MID PMU_CTL_LDOVS(2) /* LDO output voltage mid mode */ +# define PMU_LDOVS_HIGH PMU_CTL_LDOVS(3) /* LDO output voltage high mode */ + +#define PMU_CTL_HDEN (1 << 16) /* Bit 16: High-driver mode enable */ +#define PMU_CTL_HDS (1 << 17) /* Bit 17: High-driver mode switch */ + +#define PMU_CTL_LDEN_SHIFT (18) /* Bit 18-19: LDO output voltage select */ +#define PMU_CTL_LDEN_MASK (3 << PMU_CTL_LDEN_SHIFT) +# define PMU_CTL_LDEN(n) ((n) << PMU_CTL_LDEN_SHIFT) +# define PMU_LOWDRIVER_DISABLE PMU_CTL_LDEN(0) /* Low-driver mode disable in deep-sleep mode */ +# define PMU_LOWDRIVER_ENABLE PMU_CTL_LDEN(3) /* Low-driver mode enable in deep-sleep mode */ + +/* Power control and status register */ + +#define PMU_CS_WUF (1 << 0) /* Bit 0: Wakeup Flag */ +#define PMU_CS_STBF (1 << 1) /* Bit 1: Standby Flag */ +#define PMU_CS_LVDF (1 << 2) /* Bit 2: Low voltage detector status flag */ +#define PMU_CS_BLDORF (1 << 3) /* Bit 3: Backup SRAM LDO ready flag */ +#define PMU_CS_WUPEN (1 << 8) /* Bit 8: Wakeup pin enable */ +#define PMU_CS_BLDOON (1 << 9) /* Bit 9: Backup SRAM LDO on */ +#define PMU_CS_LDOVSRF (1 << 14) /* Bit 14: LDO voltage select ready flag */ +#define PMU_CS_HDRF (1 << 16) /* Bit 16: High-driver ready flag */ +#define PMU_CS_HDSRF (1 << 17) /* Bit 17: High-driver switch ready flag */ + +#define PMU_CS_LDRF_SHIFT (18) /* Bit 18-19: Low-driver mode ready flag */ +#define PMU_CS_LDRF_MASK (3 << PMU_CS_LDRF_SHIFT) +# define PMU_CS_LDRF(n) ((n) << PMU_CS_LDRF_SHIFT) +# define PMU_LDRF_NORMAL PMU_CS_LDRF(0) /* Normal driver in deep-sleep mode */ +# define PMU_LDRF_LOWDRIVER PMU_CS_LDRF(3) /* Low-driver mode in deep-sleep mode */ + +/* PMU low-driver mode when use low power LDO */ +#define PMU_NORMALDR_LOWPWR (0) /* Normal driver when use low power LDO */ +#define PMU_LOWDR_LOWPWR PMU_CTL_LDLP /* Low-driver mode enabled when LDEN is 11 and use low power LDO */ + +/* PMU low-driver mode when use normal power LDO */ +#define PMU_NORMALDR_NORMALPWR (0) /* Normal driver when use normal power LDO */ +#define PMU_LOWDR_NORMALPWR PMU_CTL_LDNP /* Low-driver mode enabled when LDEN is 11 and use normal power LDO */ + +/* PMU ldo definitions */ +#define PMU_LDO_NORMAL (0) /* LDO normal work when PMU enter deep-sleep mode */ +#define PMU_LDO_LOWPOWER PMU_CTL_LDOLP /* LDO work at low power status when PMU enter deep-sleep mode */ + +/* PMU flag reset definitions */ +#define PMU_FLAG_RESET_WAKEUP (0x00) /* Wakeup flag reset */ +#define PMU_FLAG_RESET_STANDBY (0x01) /* Standby flag reset */ + +/* PMU high-driver mode switch */ +#define PMU_HIGHDR_SWITCH_NONE (0) /* No high-driver mode switch */ +#define PMU_HIGHDR_SWITCH_EN PMU_CTL_HDS /* High-driver mode switch */ + +/* PMU command constants definitions */ +#define WFI_CMD (0x00) /* Use WFI command */ +#define WFE_CMD (0x01) /* Use WFE command */ + +/* PMU backup SRAM LDO on or off */ +#define PMU_BLDOON_OFF (0) /* Backup SRAM LDO off */ +#define PMU_BLDOON_ON PMU_CS_BLDOON /* The backup SRAM LDO on */ + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_PMU_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_rcu.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_rcu.h new file mode 100644 index 0000000000..fc3866c3ac --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_rcu.h @@ -0,0 +1,668 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_rcu.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_RCU_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_RCU_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define GD32_RCU_CTL_OFFSET 0x0000 /* Control register offset */ +#define GD32_RCU_PLL_OFFSET 0x0004 /* PLL register offset */ +#define GD32_RCU_CFG0_OFFSET 0x0008 /* Clock configuration register offset */ +#define GD32_RCU_INT_OFFSET 0x000c /* Clock interrupt register offset */ +#define GD32_RCU_AHB1RST_OFFSET 0x0010 /* AHB1 reset register offset */ +#define GD32_RCU_AHB2RST_OFFSET 0x0014 /* AHB2 reset register offset */ +#define GD32_RCU_AHB3RST_OFFSET 0x0018 /* AHB3 reset register offset */ +#define GD32_RCU_APB1RST_OFFSET 0x0020 /* APB1 reset register offset */ +#define GD32_RCU_APB2RST_OFFSET 0x0024 /* APB2 reset register offset */ +#define GD32_RCU_AHB1EN_OFFSET 0x0030 /* AHB1 enable register offset */ +#define GD32_RCU_AHB2EN_OFFSET 0x0034 /* AHB2 enable register offset */ +#define GD32_RCU_AHB3EN_OFFSET 0x0038 /* AHB3 enable register offset */ +#define GD32_RCU_APB1EN_OFFSET 0x0040 /* APB1 enable register offset */ +#define GD32_RCU_APB2EN_OFFSET 0x0044 /* APB2 enable register offset */ +#define GD32_RCU_AHB1SPEN_OFFSET 0x0050 /* AHB1 sleep mode enable register offset */ +#define GD32_RCU_AHB2SPEN_OFFSET 0x0054 /* AHB2 sleep mode enable register offset */ +#define GD32_RCU_AHB3SPEN_OFFSET 0x0058 /* AHB3 sleep mode enable register offset */ +#define GD32_RCU_APB1SPEN_OFFSET 0x0060 /* APB1 sleep mode enable register offset */ +#define GD32_RCU_APB2SPEN_OFFSET 0x0064 /* APB2 sleep mode enable register offset */ +#define GD32_RCU_BDCTL_OFFSET 0x0070 /* Backup domain control register offset */ +#define GD32_RCU_RSTSCK_OFFSET 0x0074 /* Reset source / clock register offset */ +#define GD32_RCU_PLLSSCTL_OFFSET 0x0080 /* PLL clock spread spectrum control register offset*/ +#define GD32_RCU_PLLI2S_OFFSET 0x0084 /* PLLI2S register offset */ +#define GD32_RCU_PLLSAI_OFFSET 0x0088 /* PLLSAI register offset */ +#define GD32_RCU_CFG1_OFFSET 0x008c /* Clock configuration register 1 */ +#define GD32_RCU_ADDCTL_OFFSET 0x00c0 /* Additional clock control register */ +#define GD32_RCU_ADDINT_OFFSET 0x00cc /* Additional clock interrupt register offset */ +#define GD32_RCU_ADDAPB1RST_OFFSET 0x00e0 /* APB1 additional reset register offset */ +#define GD32_RCU_ADDAPB1EN_OFFSET 0x00e4 /* APB1 additional enable register offset */ +#define GD32_RCU_ADDAPB1SPEN_OFFSET 0x00e8 /* APB1 additional sleep mode enable register offset */ +#define GD32_RCU_VKEY_OFFSET 0x0100 /* Voltage key register offset */ +#define GD32_RCU_DSV_OFFSET 0x0134 /* Deep-sleep mode voltage register offset */ + +/* Register Addresses *******************************************************/ + +#define GD32_RCU_CTL (GD32_RCU_BASE+GD32_RCU_CTL_OFFSET) /* Control register */ +#define GD32_RCU_PLL (GD32_RCU_BASE+GD32_RCU_PLL_OFFSET) /* PLL register */ +#define GD32_RCU_CFG0 (GD32_RCU_BASE+GD32_RCU_CFG0_OFFSET) /* Clock configuration register */ +#define GD32_RCU_INT (GD32_RCU_BASE+GD32_RCU_INT_OFFSET) /* Clock interrupt register */ +#define GD32_RCU_AHB1RST (GD32_RCU_BASE+GD32_RCU_AHB1RST_OFFSET) /* AHB1 reset register */ +#define GD32_RCU_AHB2RST (GD32_RCU_BASE+GD32_RCU_AHB2RST_OFFSET) /* AHB2 reset register */ +#define GD32_RCU_AHB3RST (GD32_RCU_BASE+GD32_RCU_AHB3RST_OFFSET) /* AHB3 reset register */ +#define GD32_RCU_APB1RST (GD32_RCU_BASE+GD32_RCU_APB1RST_OFFSET) /* APB1 reset register */ +#define GD32_RCU_APB2RST (GD32_RCU_BASE+GD32_RCU_APB2RST_OFFSET) /* APB2 reset register */ +#define GD32_RCU_AHB1EN (GD32_RCU_BASE+GD32_RCU_AHB1EN_OFFSET) /* AHB1 enable register */ +#define GD32_RCU_AHB2EN (GD32_RCU_BASE+GD32_RCU_AHB2EN_OFFSET) /* AHB2 enable register */ +#define GD32_RCU_AHB3EN (GD32_RCU_BASE+GD32_RCU_AHB3EN_OFFSET) /* AHB3 enable register */ +#define GD32_RCU_APB1EN (GD32_RCU_BASE+GD32_RCU_APB1EN_OFFSET) /* APB1 enable register */ +#define GD32_RCU_APB2EN (GD32_RCU_BASE+GD32_RCU_APB2EN_OFFSET) /* APB2 enable register */ +#define GD32_RCU_AHB1SPEN (GD32_RCU_BASE+GD32_RCU_AHB1SPEN_OFFSET) /* AHB1 sleep mode enable register */ +#define GD32_RCU_AHB2SPEN (GD32_RCU_BASE+GD32_RCU_AHB2SPEN_OFFSET) /* AHB2 sleep mode enable register */ +#define GD32_RCU_AHB3SPEN (GD32_RCU_BASE+GD32_RCU_AHB3SPEN_OFFSET) /* AHB3 sleep mode enable register */ +#define GD32_RCU_APB1SPEN (GD32_RCU_BASE+GD32_RCU_APB1SPEN_OFFSET) /* APB1 sleep mode enable register */ +#define GD32_RCU_APB2SPEN (GD32_RCU_BASE+GD32_RCU_APB2SPEN_OFFSET) /* APB2 sleep mode enable register */ +#define GD32_RCU_BDCTL (GD32_RCU_BASE+GD32_RCU_BDCTL_OFFSET) /* Backup domain control register */ +#define GD32_RCU_RSTSCK (GD32_RCU_BASE+GD32_RCU_RSTSCK_OFFSET) /* Reset source / clock register */ +#define GD32_RCU_PLLSSCTL (GD32_RCU_BASE+GD32_RCU_PLLSSCTL_OFFSET) /* PLL clock spread spectrum control register*/ +#define GD32_RCU_PLLI2S (GD32_RCU_BASE+GD32_RCU_PLLI2S_OFFSET) /* PLLI2S register */ +#define GD32_RCU_PLLSAI (GD32_RCU_BASE+GD32_RCU_PLLSAI_OFFSET) /* PLLSAI register */ +#define GD32_RCU_CFG1 (GD32_RCU_BASE+GD32_RCU_CFG1_OFFSET) /* Clock configuration register 1 */ +#define GD32_RCU_ADDCTL (GD32_RCU_BASE+GD32_RCU_ADDCTL_OFFSET) /* Additional clock control register */ +#define GD32_RCU_ADDINT (GD32_RCU_BASE+GD32_RCU_ADDINT_OFFSET) /* Additional clock interrupt register */ +#define GD32_RCU_ADDAPB1RST (GD32_RCU_BASE+GD32_RCU_ADDAPB1RST_OFFSET) /* APB1 additional reset register */ +#define GD32_RCU_ADDAPB1EN (GD32_RCU_BASE+GD32_RCU_ADDAPB1EN_OFFSET) /* APB1 additional enable register */ +#define GD32_RCU_ADDAPB1SPEN (GD32_RCU_BASE+GD32_RCU_ADDAPB1SPEN_OFFSET) /* APB1 additional sleep mode enable register */ +#define GD32_RCU_VKEY (GD32_RCU_BASE+GD32_RCU_VKEY_OFFSET) /* Voltage key register */ +#define GD32_RCU_DSV (GD32_RCU_BASE+GD32_RCU_DSV_OFFSET) /* Deep-sleep mode voltage register */ + +/* Register Bitfield Definitions ********************************************/ + +/* Control register */ + +#define RCU_CTL_IRC16MEN (1 << 0) /* Bit 0: Internal high speed oscillator enable */ +#define RCU_CTL_IRC16MSTB (1 << 1) /* Bit 1: IRC16M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC16MADJ_SHIFT (3) /* Bits 7-3: High speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC16MADJ_MASK (0x1f << RCU_CTL_IRC16MADJ_SHIFT) +# define CU_CTL_IRC16MADJ(n) ((n) << RCU_CTL_IRC16MADJ_SHIFT) +#define RCU_CTL_IRC16MCALIB_SHIFT (8) /* Bits 15-8: High speed internal oscillator calibration value */ +#define RCU_CTL_IRC16MCAL_MASK (0xff << RCU_CTL_IRC16MCALIB_SHIFT) +# define RCU_CTL_IRC16MCAL(n) ((n) << RCU_CTL_IRC16MCALIB_SHIFT) +#define RCU_CTL_HXTALEN (1 << 16) /* Bit 16: External high speed oscillator enable */ +#define RCU_CTL_HXTALSTB (1 << 17) /* Bit 17: External crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS (1 << 18) /* Bit 18: External crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN (1 << 19) /* Bit 19: Clock Security System enable */ +#define RCU_CTL_PLLEN (1 << 24) /* Bit 24: PLL enable */ +#define RCU_CTL_PLLSTB (1 << 25) /* Bit 25: PLL clock Stabilization flag */ +#define RCU_CTL_PLLI2SEN (1 << 26) /* Bit 26: PLLI2S enable */ +#define RCU_CTL_PLLI2SSTB (1 << 27) /* Bit 27: PLLI2S clock Stabilization flag */ +#define RCU_CTL_PLLSAIEN (1 << 28) /* Bit 28: PLLSAI enable */ +#define RCU_CTL_PLLSAISTB (1 << 29) /* Bit 29: PLLSAI clock Stabilization flag */ + +/* PLL register */ + +#define RCU_PLL_PLLPSC_SHIFT (0) /* Bits 0-5: The PLL VCO source clock prescale */ +#define RCU_PLL_PLLPSC_MASK (0x3f << RCU_PLL_PLLPSC_SHIFT) +# define RCU_PLL_PLLPSC(n) ((n) << RCU_PLL_PLLPSC_SHIFT) /* CK_PLLSRC/n, n = 2..63 */ + +#define RCU_PLL_PLLN_SHIFT (6) /* Bits 6-14: The PLL VCO clock multi factor */ +#define RCU_PLL_PLLN_MASK (0x1ff << RCU_PLL_PLLN_SHIFT) +# define RCU_PLL_PLLN(n) ((n) << RCU_PLL_PLLN_SHIFT) /* CK_PLLVCO = CK_PLLVCOSRC*n, n = 64..500 */ + +#define RCU_PLL_PLLP_SHIFT (16) /* Bits 16-17: The PLLP output frequency division factor from PLL VCO clock */ +#define RCU_PLL_PLLP_MASK (3 << RCU_PLL_PLLP_SHIFT) +# define RCU_PLL_PLLP(n) ((((n)>>1)-1)<< RCU_PLL_PLLP_SHIFT) /* CK_PLLP = CK_PLLVCO/n, n=2,4,6,8 */ + +#define RCU_PLL_PLLSEL (1 << 22) /* PLL Clock Source Selection */ +# define RCU_PLL_PLLSEL_IRC16M (0) +# define RCU_PLL_PLLSEL_HXTAL (1 << 22) + +#define RCU_PLL_PLLQ_SHIFT (24) /* Bits 24-27: The PLL Q output frequency division factor from PLL VCO clock */ +#define RCU_PLL_PLLQ_MASK (15 << RCU_PLL_PLLQ_SHIFT) +# define RCU_PLL_PLLQ(n) ((n) << RCU_PLL_PLLQ_SHIFT) /* CK_PLLQ = CK_PLLVCO/n, n=2..15 */ + +/* Clock configuration register 0 */ + +#define RCU_CFG0_SCS_SHIFT (0) /* Bits 0-1: System clock source select */ +#define RCU_CFG0_SCS_MASK (3 << RCU_CFG0_SCS_SHIFT) +# define RCU_CFG0_SCS(n) ((n) << RCU_CFG0_SCS_SHIFT) +# define RCU_CFG0_SCS_IRC16M RCU_CFG0_SCS(0) /* System clock source select IRC16M */ +# define RCU_CFG0_SCS_HXTAL RCU_CFG0_SCS(1) /* System clock source select HXTAL */ +# define RCU_CFG0_SCS_PLLP RCU_CFG0_SCS(2) /* System clock source select PLLP */ + +#define RCU_CFG0_SCSS_SHIFT (2) /* Bits 2-3: System clock source select status */ +#define RCU_CFG0_SCSS_MASK (3 << RCU_CFG0_SCSS_SHIFT) +# define RCU_CFG0_SCSS(n) ((n) << RCU_CFG0_SCSS_SHIFT) +# define RCU_CFG0_SCSS_IRC16M RCU_CFG0_SCSS(0) /* System clock source select IRC16M */ +# define RCU_CFG0_SCSS_HXTAL RCU_CFG0_SCSS(1) /* System clock source select HXTAL */ +# define RCU_CFG0_SCSS_PLLP RCU_CFG0_SCSS(2) /* System clock source select PLLP */ + +#define RCU_CFG0_AHBPSC_SHIFT (4) /* Bits 4-7: AHB prescaler selection */ +#define RCU_CFG0_AHBPSC_MASK (0x0f << RCU_CFG0_AHBPSC_SHIFT) +# define RCU_CFG0_AHBPSC(n) ((n) << RCU_CFG0_AHBPSC_SHIFT) +# define RCU_CFG0_AHBPSC_CKSYS_DIV1 RCU_CFG0_AHBPSC(0) /* AHB prescaler select CK_SYS, n=0..7 */ +# define RCU_CFG0_AHBPSC_CKSYS_DIV2 RCU_CFG0_AHBPSC(8) /* AHB prescaler select CK_SYS/2 */ +# define RCU_CFG0_AHBPSC_CKSYS_DIV4 RCU_CFG0_AHBPSC(9) /* AHB prescaler select CK_SYS/4 */ +# define RCU_CFG0_AHBPSC_CKSYS_DIV8 RCU_CFG0_AHBPSC(10) /* AHB prescaler select CK_SYS/8 */ +# define RCU_CFG0_AHBPSC_CKSYS_DIV16 RCU_CFG0_AHBPSC(11) /* AHB prescaler select CK_SYS/16 */ +# define RCU_CFG0_AHBPSC_CKSYS_DIV64 RCU_CFG0_AHBPSC(12) /* AHB prescaler select CK_SYS/64 */ +# define RCU_CFG0_AHBPSC_CKSYS_DIV128 RCU_CFG0_AHBPSC(13) /* AHB prescaler select CK_SYS/128 */ +# define RCU_CFG0_AHBPSC_CKSYS_DIV256 RCU_CFG0_AHBPSC(14) /* AHB prescaler select CK_SYS/256 */ +# define RCU_CFG0_AHBPSC_CKSYS_DIV512 RCU_CFG0_AHBPSC(15) /* AHB prescaler select CK_SYS/512 */ + +#define RCU_CFG0_APB1PSC_SHIFT (10) /* Bits 10-12: APB1 prescaler selection */ +#define RCU_CFG0_APB1PSC_MASK (7 << RCU_CFG0_APB1PSC_SHIFT) +# define RCU_CFG0_APB1PSC(n) ((n) << RCU_CFG0_APB1PSC_SHIFT) +# define RCU_CFG0_APB1PSC_CKAHB_DIV1 RCU_CFG0_APB1PSC(0) /* APB1 prescaler select CK_AHB, n=0..3 */ +# define RCU_CFG0_APB1PSC_CKAHB_DIV2 RCU_CFG0_APB1PSC(4) /* APB1 prescaler select CK_AHB/2 */ +# define RCU_CFG0_APB1PSC_CKAHB_DIV4 RCU_CFG0_APB1PSC(5) /* APB1 prescaler select CK_AHB/4 */ +# define RCU_CFG0_APB1PSC_CKAHB_DIV8 RCU_CFG0_APB1PSC(6) /* APB1 prescaler select CK_AHB/8 */ +# define RCU_CFG0_APB1PSC_CKAHB_DIV16 RCU_CFG0_APB1PSC(7) /* APB1 prescaler select CK_AHB/16 */ + +#define RCU_CFG0_APB2PSC_SHIFT (13) /* Bits 13-15: APB2 prescaler selection */ +#define RCU_CFG0_APB2PSC_MASK (7 << RCU_CFG0_APB2PSC_SHIFT) +# define RCU_CFG0_APB2PSC(n) ((n) << RCU_CFG0_APB2PSC_SHIFT) +# define RCU_CFG0_APB2PSC_CKAHB_DIV1 RCU_CFG0_APB2PSC(0) /* APB2 prescaler select CK_AHB, n=0..3 */ +# define RCU_CFG0_APB2PSC_CKAHB_DIV2 RCU_CFG0_APB2PSC(4) /* APB2 prescaler select CK_AHB/2 */ +# define RCU_CFG0_APB2PSC_CKAHB_DIV4 RCU_CFG0_APB2PSC(5) /* APB2 prescaler select CK_AHB/4 */ +# define RCU_CFG0_APB2PSC_CKAHB_DIV8 RCU_CFG0_APB2PSC(6) /* APB2 prescaler select CK_AHB/8 */ +# define RCU_CFG0_APB2PSC_CKAHB_DIV16 RCU_CFG0_APB2PSC(7) /* APB2 prescaler select CK_AHB/16 */ + +#define RCU_CFG0_RTCDIV_SHIFT (16) /* Bits 16-20: RTC clock divider factor */ +#define RCU_CFG0_RTCDIV_MASK (31 << RCU_CFG0_RTCDIV_SHIFT) +# define RCU_CFG0_RTCDIV(n) ((n) << RCU_CFG0_RTCDIV_SHIFT) +# define RCU_CFG0_RTC_HXTAL_NONE RCU_CFG0_RTCDIV(0) /* No clock for RTC, n=0,1 */ +# define RCU_CFG0_RTC_HXTAL_DIV2 RCU_CFG0_RTCDIV(2) /* RTCDIV clock select CK_HXTAL/2 */ +# define RCU_CFG0_RTC_HXTAL_DIV3 RCU_CFG0_RTCDIV(3) /* RTCDIV clock select CK_HXTAL/3 */ +# define RCU_CFG0_RTC_HXTAL_DIV4 RCU_CFG0_RTCDIV(4) /* RTCDIV clock select CK_HXTAL/4 */ +# define RCU_CFG0_RTC_HXTAL_DIV5 RCU_CFG0_RTCDIV(5) /* RTCDIV clock select CK_HXTAL/5 */ +# define RCU_CFG0_RTC_HXTAL_DIV6 RCU_CFG0_RTCDIV(6) /* RTCDIV clock select CK_HXTAL/6 */ +# define RCU_CFG0_RTC_HXTAL_DIV7 RCU_CFG0_RTCDIV(7) /* RTCDIV clock select CK_HXTAL/7 */ +# define RCU_CFG0_RTC_HXTAL_DIV8 RCU_CFG0_RTCDIV(8) /* RTCDIV clock select CK_HXTAL/8 */ +# define RCU_CFG0_RTC_HXTAL_DIV9 RCU_CFG0_RTCDIV(9) /* RTCDIV clock select CK_HXTAL/9 */ +# define RCU_CFG0_RTC_HXTAL_DIV10 RCU_CFG0_RTCDIV(10) /* RTCDIV clock select CK_HXTAL/10 */ +# define RCU_CFG0_RTC_HXTAL_DIV11 RCU_CFG0_RTCDIV(11) /* RTCDIV clock select CK_HXTAL/11 */ +# define RCU_CFG0_RTC_HXTAL_DIV12 RCU_CFG0_RTCDIV(12) /* RTCDIV clock select CK_HXTAL/12 */ +# define RCU_CFG0_RTC_HXTAL_DIV13 RCU_CFG0_RTCDIV(13) /* RTCDIV clock select CK_HXTAL/13 */ +# define RCU_CFG0_RTC_HXTAL_DIV14 RCU_CFG0_RTCDIV(14) /* RTCDIV clock select CK_HXTAL/14 */ +# define RCU_CFG0_RTC_HXTAL_DIV15 RCU_CFG0_RTCDIV(15) /* RTCDIV clock select CK_HXTAL/15 */ +# define RCU_CFG0_RTC_HXTAL_DIV16 RCU_CFG0_RTCDIV(16) /* RTCDIV clock select CK_HXTAL/16 */ +# define RCU_CFG0_RTC_HXTAL_DIV17 RCU_CFG0_RTCDIV(17) /* RTCDIV clock select CK_HXTAL/17 */ +# define RCU_CFG0_RTC_HXTAL_DIV18 RCU_CFG0_RTCDIV(18) /* RTCDIV clock select CK_HXTAL/18 */ +# define RCU_CFG0_RTC_HXTAL_DIV19 RCU_CFG0_RTCDIV(19) /* RTCDIV clock select CK_HXTAL/19 */ +# define RCU_CFG0_RTC_HXTAL_DIV20 RCU_CFG0_RTCDIV(20) /* RTCDIV clock select CK_HXTAL/20 */ +# define RCU_CFG0_RTC_HXTAL_DIV21 RCU_CFG0_RTCDIV(21) /* RTCDIV clock select CK_HXTAL/21 */ +# define RCU_CFG0_RTC_HXTAL_DIV22 RCU_CFG0_RTCDIV(22) /* RTCDIV clock select CK_HXTAL/22 */ +# define RCU_CFG0_RTC_HXTAL_DIV23 RCU_CFG0_RTCDIV(23) /* RTCDIV clock select CK_HXTAL/23 */ +# define RCU_CFG0_RTC_HXTAL_DIV24 RCU_CFG0_RTCDIV(24) /* RTCDIV clock select CK_HXTAL/24 */ +# define RCU_CFG0_RTC_HXTAL_DIV25 RCU_CFG0_RTCDIV(25) /* RTCDIV clock select CK_HXTAL/25 */ +# define RCU_CFG0_RTC_HXTAL_DIV26 RCU_CFG0_RTCDIV(26) /* RTCDIV clock select CK_HXTAL/26 */ +# define RCU_CFG0_RTC_HXTAL_DIV27 RCU_CFG0_RTCDIV(27) /* RTCDIV clock select CK_HXTAL/27 */ +# define RCU_CFG0_RTC_HXTAL_DIV28 RCU_CFG0_RTCDIV(28) /* RTCDIV clock select CK_HXTAL/28 */ +# define RCU_CFG0_RTC_HXTAL_DIV29 RCU_CFG0_RTCDIV(29) /* RTCDIV clock select CK_HXTAL/29 */ +# define RCU_CFG0_RTC_HXTAL_DIV30 RCU_CFG0_RTCDIV(30) /* RTCDIV clock select CK_HXTAL/30 */ +# define RCU_CFG0_RTC_HXTAL_DIV31 RCU_CFG0_RTCDIV(31) /* RTCDIV clock select CK_HXTAL/31 */ + +#define RCU_CFG0_CKOUT0SEL_SHIFT (21) /* Bits 21-22: CKOUT0 Clock source selection */ +#define RCU_CFG0_CKOUT0SEL_MASK (3 << RCU_CFG0_CKOUT0SEL_SHIFT) +# define RCU_CFG0_CKOUT0SEL(n) ((n) << RCU_CFG0_CKOUT0SEL_SHIFT) +# define RCU_CFG0_CKOUT0SEL_IRC16M RCU_CFG0_CKOUT0SEL(0) /* Internal 16M RC oscillator clock selected */ +# define RCU_CFG0_CKOUT0SEL_LXTAL RCU_CFG0_CKOUT0SEL(1) /* Low speed crystal oscillator clock (LXTAL) selected */ +# define RCU_CFG0_CKOUT0SEL_HXTAL RCU_CFG0_CKOUT0SEL(2) /* High speed crystal oscillator clock (HXTAL) selected */ +# define RCU_CFG0_CKOUT0SEL_PLLP RCU_CFG0_CKOUT0SEL(3) /* CK_PLLP clock selected */ + +#define RCU_CFG0_I2SSEL (1 << 23) /* Bit 23: I2S Clock Source Selection */ +# define RCU_I2SSEL_PLLI2S (0 << 23) /* PLLI2S output clock selected as I2S source clock */ +# define RCU_I2SSEL_I2S_CKIN RCU_CFG0_I2SSEL /* External I2S_CKIN pin selected as I2S source clock */ + +#define RCU_CFG0_CKOUT0DIV_SHIFT (24) /* Bits 24-26: The CK_OUT0 divider */ +#define RCU_CFG0_CKOUT0DIV_MASK (7 << RCU_CFG0_CKOUT0DIV_SHIFT) +# define RCU_CFG0_CKOUT0DIV(n) ((n) << RCU_CFG0_CKOUT0DIV_SHIFT) +# define RCU_CFG0_CKOUT0_DIV1 RCU_CFG0_CKOUT0DIV(0) /* CK_OUT0 is divided by 1, n=0..3 */ +# define RCU_CFG0_CKOUT0_DIV2 RCU_CFG0_CKOUT0DIV(4) /* CK_OUT0 is divided by 2 */ +# define RCU_CFG0_CKOUT0_DIV3 RCU_CFG0_CKOUT0DIV(5) /* CK_OUT0 is divided by 3 */ +# define RCU_CFG0_CKOUT0_DIV4 RCU_CFG0_CKOUT0DIV(6) /* CK_OUT0 is divided by 4 */ +# define RCU_CFG0_CKOUT0_DIV5 RCU_CFG0_CKOUT0DIV(7) /* CK_OUT0 is divided by 5 */ + +#define RCU_CFG0_CKOUT1DIV_SHIFT (27) /* Bits 27-29: The CK_OUT1 divider */ +#define RCU_CFG0_CKOUT1DIV_MASK (7 << RCU_CFG0_CKOUT1DIV_SHIFT) +# define RCU_CFG0_CKOUT1DIV(n) ((n) << RCU_CFG0_CKOUT1DIV_SHIFT) +# define RCU_CFG0_CKOUT1_DIV1 RCU_CFG0_CKOUT1DIV(0) /* CK_OUT1 is divided by 1, n=0..3 */ +# define RCU_CFG0_CKOUT1_DIV2 RCU_CFG0_CKOUT1DIV(4) /* CK_OUT1 is divided by 2 */ +# define RCU_CFG0_CKOUT1_DIV3 RCU_CFG0_CKOUT1DIV(5) /* CK_OUT1 is divided by 3 */ +# define RCU_CFG0_CKOUT1_DIV4 RCU_CFG0_CKOUT1DIV(6) /* CK_OUT1 is divided by 4 */ +# define RCU_CFG0_CKOUT1_DIV5 RCU_CFG0_CKOUT1DIV(7) /* CK_OUT1 is divided by 5 */ + +#define RCU_CFG0_CKOUT1SEL_SHIFT (30) /* Bits 30-31: CKOUT1 Clock source selection */ +#define RCU_CFG0_CKOUT1SEL_MASK (3 << RCU_CFG0_CKOUT1SEL_SHIFT) +# define RCU_CFG0_CKOUT1SEL(n) ((n) << RCU_CFG0_CKOUT1SEL_SHIFT) +# define RCU_CFG0_CKOUT1SEL_SYSTEMCLOCK RCU_CFG0_CKOUT1SEL(0) /* System clock selected */ +# define RCU_CFG0_CKOUT1SEL_PLLI2SR RCU_CFG0_CKOUT1SEL(0) /* CK_PLLI2SR clock selected */ +# define RCU_CFG0_CKOUT1SEL_HXTAL RCU_CFG0_CKOUT1SEL(0) /* High speed crystal oscillator clock (HXTAL) selected */ +# define RCU_CFG0_CKOUT1SEL_PLLp RCU_CFG0_CKOUT1SEL(0) /* CK_PLLP clock selected */ + +/* Clock interrupt register */ + +#define RCU_INT_IRC32KSTBIF (1 << 0) /* Bit 0: IRC32K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF (1 << 1) /* Bit 1: LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC16MSTBIF (1 << 2) /* Bit 2: IRC16M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF (1 << 3) /* Bit 3: HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF (1 << 4) /* Bit 4: PLL stabilization interrupt flag */ +#define RCU_INT_PLLI2SSTBIF (1 << 5) /* Bit 5: PLLI2S stabilization interrupt flag */ +#define RCU_INT_PLLSAISTBIF (1 << 6) /* Bit 6: PLLSAI stabilization interrupt flag */ +#define RCU_INT_CKMIF (1 << 7) /* Bit 7: HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC32KSTBIE (1 << 8) /* Bit 8: IRC32K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE (1 << 9) /* Bit 9: LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC16MSTBIE (1 << 10) /* Bit 10: IRC16M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE (1 << 11) /* Bit 11: HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE (1 << 12) /* Bit 12: PLL stabilization interrupt enable */ +#define RCU_INT_PLLI2SSTBIE (1 << 13) /* Bit 13: PLLI2S Stabilization Interrupt Enable */ +#define RCU_INT_PLLSAISTBIE (1 << 14) /* Bit 14: PLLSAI Stabilization Interrupt Enable */ +#define RCU_INT_IRC32KSTBIC (1 << 16) /* Bit 16: IRC32K Stabilization Interrupt Clear */ +#define RCU_INT_LXTALSTBIC (1 << 17) /* Bit 17: LXTAL Stabilization Interrupt Clear */ +#define RCU_INT_IRC16MSTBIC (1 << 18) /* Bit 18: IRC16M Stabilization Interrupt Clear */ +#define RCU_INT_HXTALSTBIC (1 << 19) /* Bit 19: HXTAL Stabilization Interrupt Clear */ +#define RCU_INT_PLLSTBIC (1 << 20) /* Bit 20: PLL stabilization Interrupt Clear */ +#define RCU_INT_PLLI2SSTBIC (1 << 21) /* Bit 21: PLLI2S stabilization Interrupt Clear */ +#define RCU_INT_PLLSAISTBIC (1 << 22) /* Bit 22: PLLSAI stabilization Interrupt Clear */ +#define RCU_INT_CKMIC (1 << 23) /* Bit 23: HXTAL Clock Stuck Interrupt Clear */ + +/* AHB1 reset register */ + +#define RCU_AHB1RST_PARST (1 << 0) /* Bit 0: GPIO port A reset */ +#define RCU_AHB1RST_PBRST (1 << 1) /* Bit 1: GPIO port B reset */ +#define RCU_AHB1RST_PCRST (1 << 2) /* Bit 2: GPIO port C reset */ +#define RCU_AHB1RST_PDRST (1 << 3) /* Bit 3: GPIO port D reset */ +#define RCU_AHB1RST_PERST (1 << 4) /* Bit 4: GPIO port E reset */ +#define RCU_AHB1RST_PFRST (1 << 5) /* Bit 5: GPIO port F reset */ +#define RCU_AHB1RST_PGRST (1 << 6) /* Bit 6: GPIO port G reset */ +#define RCU_AHB1RST_PHRST (1 << 7) /* Bit 7: GPIO port H reset */ +#define RCU_AHB1RST_PIRST (1 << 8) /* Bit 8: GPIO port I reset */ +#define RCU_AHB1RST_CRCRST (1 << 12) /* Bit 12: CRC reset */ +#define RCU_AHB1RST_DMA0RST (1 << 21) /* Bit 21: DMA0 reset */ +#define RCU_AHB1RST_DMA1RST (1 << 22) /* Bit 22: DMA1 reset */ +#define RCU_AHB1RST_IPARST (1 << 23) /* Bit 23: IPA reset */ +#define RCU_AHB1RST_ENETRST (1 << 25) /* Bit 25: ENET reset */ +#define RCU_AHB1RST_USBHSRST (1 << 29) /* Bit 29: USBHS reset */ + +/* AHB2 reset register */ + +#define RCU_AHB2RST_DCIRST (1 << 0) /* Bit 0: DCI reset */ +#define RCU_AHB2RST_TRNGRST (1 << 6) /* Bit 6: TRNG reset */ +#define RCU_AHB2RST_USBFSRST (1 << 7) /* Bit 7: USBFS reset */ + +/* AHB3 reset register */ + +#define RCU_AHB3RST_EXMCRST (1 << 0) /* Bit 0: EXMC reset */ + +/* APB1 reset register */ + +#define RCU_APB1RST_TIMER1RST (1 << 0) /* Bit 0: TIMER1 reset */ +#define RCU_APB1RST_TIMER2RST (1 << 1) /* Bit 1: TIMER2 reset */ +#define RCU_APB1RST_TIMER3RST (1 << 2) /* Bit 2: TIMER3 reset */ +#define RCU_APB1RST_TIMER4RST (1 << 3) /* Bit 3: TIMER4 reset */ +#define RCU_APB1RST_TIMER5RST (1 << 4) /* Bit 4: TIMER5 reset */ +#define RCU_APB1RST_TIMER6RST (1 << 5) /* Bit 5: TIMER6 reset */ +#define RCU_APB1RST_TIMER11RST (1 << 6) /* Bit 6: TIMER11 reset */ +#define RCU_APB1RST_TIMER12RST (1 << 7) /* Bit 7: TIMER12 reset */ +#define RCU_APB1RST_TIMER13RST (1 << 8) /* Bit 8: TIMER13 reset */ +#define RCU_APB1RST_WWDGTRST (1 << 11) /* Bit 11: WWDGT reset */ +#define RCU_APB1RST_SPI1RST (1 << 14) /* Bit 14: SPI1 reset */ +#define RCU_APB1RST_SPI2RST (1 << 15) /* Bit 15: SPI2 reset */ +#define RCU_APB1RST_USART1RST (1 << 17) /* Bit 17: USART1 reset */ +#define RCU_APB1RST_USART2RST (1 << 18) /* Bit 18: USART2 reset */ +#define RCU_APB1RST_UART3RST (1 << 19) /* Bit 19: UART3 reset */ +#define RCU_APB1RST_UART4RST (1 << 20) /* Bit 20: UART4 reset */ +#define RCU_APB1RST_I2C0RST (1 << 21) /* Bit 21: I2C0 reset */ +#define RCU_APB1RST_I2C1RST (1 << 22) /* Bit 22: I2C1 reset */ +#define RCU_APB1RST_I2C2RST (1 << 23) /* Bit 23: I2C2 reset */ +#define RCU_APB1RST_CAN0RST (1 << 25) /* Bit 25: CAN0 reset */ +#define RCU_APB1RST_CAN1RST (1 << 26) /* Bit 26: CAN1 reset */ +#define RCU_APB1RST_PMURST (1 << 28) /* Bit 28: PMU reset */ +#define RCU_APB1RST_DACRST (1 << 29) /* Bit 29: DAC reset */ +#define RCU_APB1RST_UART6RST (1 << 30) /* Bit 30: UART6 reset */ +#define RCU_APB1RST_UART7RST (1 << 31) /* Bit 31: UART7 reset */ + +/* APB2 reset register */ + +#define RCU_APB2RST_TIMER0RST (1 << 0) /* Bit 0: TIMER0 reset */ +#define RCU_APB2RST_TIMER7RST (1 << 1) /* Bit 1: TIMER7 reset */ +#define RCU_APB2RST_USART0RST (1 << 4) /* Bit 4: USART0 reset */ +#define RCU_APB2RST_USART5RST (1 << 5) /* Bit 5: USART5 reset */ +#define RCU_APB2RST_ADCRST (1 << 8) /* Bit 8: ADC reset */ +#define RCU_APB2RST_SDIORST (1 << 11) /* Bit 11: SDIO reset */ +#define RCU_APB2RST_SPI0RST (1 << 12) /* Bit 13: SPI0 reset */ +#define RCU_APB2RST_SPI3RST (1 << 13) /* Bit 13: SPI3 reset */ +#define RCU_APB2RST_SYSCFGRST (1 << 14) /* Bit 14: SYSCFG reset */ +#define RCU_APB2RST_TIMER8RST (1 << 16) /* Bit 16: TIMER8 reset */ +#define RCU_APB2RST_TIMER9RST (1 << 17) /* Bit 17: TIMER9 reset */ +#define RCU_APB2RST_TIMER10RST (1 << 18) /* Bit 18: TIMER10 reset */ +#define RCU_APB2RST_SPI4RST (1 << 20) /* Bit 20: SPI4 reset */ +#define RCU_APB2RST_SPI5RST (1 << 21) /* Bit 21: SPI5 reset */ +#define RCU_APB2RST_TLIRST (1 << 26) /* Bit 26: TLI reset */ + +/* AHB1 enable register */ + +#define RCU_AHB1EN_PAEN (1 << 0) /* Bit 0: GPIO port A clock enable */ +#define RCU_AHB1EN_PBEN (1 << 1) /* Bit 1: GPIO port B clock enable */ +#define RCU_AHB1EN_PCEN (1 << 2) /* Bit 2: GPIO port C clock enable */ +#define RCU_AHB1EN_PDEN (1 << 3) /* Bit 3: GPIO port D clock enable */ +#define RCU_AHB1EN_PEEN (1 << 4) /* Bit 4: GPIO port E clock enable */ +#define RCU_AHB1EN_PFEN (1 << 5) /* Bit 5: GPIO port F clock enable */ +#define RCU_AHB1EN_PGEN (1 << 6) /* Bit 6: GPIO port G clock enable */ +#define RCU_AHB1EN_PHEN (1 << 7) /* Bit 7: GPIO port H clock enable */ +#define RCU_AHB1EN_PIEN (1 << 8) /* Bit 10: GPIO port I clock enable */ +#define RCU_AHB1EN_CRCEN (1 << 12) /* Bit 12: CRC clock enable */ +#define RCU_AHB1EN_BKPSRAMEN (1 << 18) /* Bit 18: BKPSRAM clock enable */ +#define RCU_AHB1EN_TCMSRAMEN (1 << 20) /* Bit 20: TCMSRAM clock enable */ +#define RCU_AHB1EN_DMA0EN (1 << 21) /* Bit 21: DMA0 clock enable */ +#define RCU_AHB1EN_DMA1EN (1 << 22) /* Bit 22: DMA1 clock enable */ +#define RCU_AHB1EN_IPAEN (1 << 23) /* Bit 23: IPA clock enable */ +#define RCU_AHB1EN_ENETEN (1 << 25) /* Bit 25: ENET clock enable */ +#define RCU_AHB1EN_ENETTXEN (1 << 26) /* Bit 26: Ethernet TX clock enable */ +#define RCU_AHB1EN_ENETRXEN (1 << 27) /* Bit 27: Ethernet RX clock enable */ +#define RCU_AHB1EN_ENETPTPEN (1 << 28) /* Bit 28: Ethernet PTP clock enable */ +#define RCU_AHB1EN_USBHSEN (1 << 29) /* Bit 29: USBHS clock enable */ +#define RCU_AHB1EN_USBHSULPIEN (1 << 30) /* Bit 30: USBHS ULPI clock enable */ + +/* AHB2 enable register */ + +#define RCU_AHB2EN_DCIEN (1 << 0) /* Bit 0: DCI clock enable */ +#define RCU_AHB2EN_TRNGEN (1 << 6) /* Bit 6: TRNG clock enable */ +#define RCU_AHB2EN_USBFSEN (1 << 7) /* Bit 7: USBFS clock enable */ + +/* AHB3 enable register */ + +#define RCU_AHB3EN_EXMCEN (1 << 0) /* Bit 0: EXMC clock enable */ + +/* APB1 enable register */ + +#define RCU_APB1EN_TIMER1EN (1 << 0) /* Bit 0: TIMER1 clock enable */ +#define RCU_APB1EN_TIMER2EN (1 << 1) /* Bit 1: TIMER2 clock enable */ +#define RCU_APB1EN_TIMER3EN (1 << 2) /* Bit 2: TIMER3 clock enable */ +#define RCU_APB1EN_TIMER4EN (1 << 3) /* Bit 3: TIMER4 clock enable */ +#define RCU_APB1EN_TIMER5EN (1 << 4) /* Bit 4: TIMER5 clock enable */ +#define RCU_APB1EN_TIMER6EN (1 << 5) /* Bit 5: TIMER6 clock enable */ +#define RCU_APB1EN_TIMER11EN (1 << 6) /* Bit 6: TIMER11 clock enable */ +#define RCU_APB1EN_TIMER12EN (1 << 7) /* Bit 7: TIMER12 clock enable */ +#define RCU_APB1EN_TIMER13EN (1 << 8) /* Bit 8: TIMER13 clock enable */ +#define RCU_APB1EN_WWDGTEN (1 << 11) /* Bit 11: WWDGT clock enable */ +#define RCU_APB1EN_SPI1EN (1 << 14) /* Bit 14: SPI1 clock enable */ +#define RCU_APB1EN_SPI2EN (1 << 15) /* Bit 15: SPI2 clock enable */ +#define RCU_APB1EN_USART1EN (1 << 17) /* Bit 17: USART1 clock enable */ +#define RCU_APB1EN_USART2EN (1 << 18) /* Bit 18: USART2 clock enable */ +#define RCU_APB1EN_UART3EN (1 << 19) /* Bit 19: UART3 clock enable */ +#define RCU_APB1EN_UART4EN (1 << 20) /* Bit 20: UART4 clock enable */ +#define RCU_APB1EN_I2C0EN (1 << 21) /* Bit 21: I2C0 clock enable */ +#define RCU_APB1EN_I2C1EN (1 << 22) /* Bit 22: I2C1 clock enable */ +#define RCU_APB1EN_I2C2EN (1 << 23) /* Bit 23: I2C2 clock enable */ +#define RCU_APB1EN_CAN0EN (1 << 25) /* Bit 25: CAN0 clock enable */ +#define RCU_APB1EN_CAN1EN (1 << 26) /* Bit 26: CAN1 clock enable */ +#define RCU_APB1EN_PMUEN (1 << 28) /* Bit 28: PMU clock enable */ +#define RCU_APB1EN_DACEN (1 << 29) /* Bit 29: DAC clock enable */ +#define RCU_APB1EN_UART6EN (1 << 30) /* Bit 30: UART6 clock enable */ +#define RCU_APB1EN_UART7EN (1 << 31) /* Bit 31: UART7 clock enable */ + +/* APB2 enable register */ + +#define RCU_APB2EN_TIMER0EN (1 << 0) /* Bit 1: TIMER0 clock enable */ +#define RCU_APB2EN_TIMER7EN (1 << 1) /* Bit 1: TIMER7 clock enable */ +#define RCU_APB2EN_USART0EN (1 << 4) /* Bit 4: USART0 clock enable */ +#define RCU_APB2EN_USART5EN (1 << 5) /* Bit 5: USART5 clock enable */ +#define RCU_APB2EN_ADC0EN (1 << 8) /* Bit 8: ADC0 clock enable */ +#define RCU_APB2EN_ADC1EN (1 << 9) /* Bit 9: ADC1 clock enable */ +#define RCU_APB2EN_ADC2EN (1 << 10) /* Bit 10: ADC2 clock enable */ +#define RCU_APB2EN_SDIOEN (1 << 11) /* Bit 11: SDIO clock enable */ +#define RCU_APB2EN_SPI0EN (1 << 12) /* Bit 12: SPI0 clock enable */ +#define RCU_APB2EN_SPI3EN (1 << 13) /* Bit 13: SPI3 clock enable */ +#define RCU_APB2EN_SYSCFGEN (1 << 14) /* Bit 14: SYSCFG clock enable */ +#define RCU_APB2EN_TIMER8EN (1 << 16) /* Bit 16: TIMER8 clock enable */ +#define RCU_APB2EN_TIMER9EN (1 << 17) /* Bit 17: TIMER9 clock enable */ +#define RCU_APB2EN_TIMER10EN (1 << 18) /* Bit 18: TIMER10 clock enable */ +#define RCU_APB2EN_SPI4EN (1 << 20) /* Bit 20: SPI4 clock enable */ +#define RCU_APB2EN_SPI5EN (1 << 21) /* Bit 21: SPI5 clock enable */ +#define RCU_APB2EN_TLIEN (1 << 26) /* Bit 26: TLI clock enable */ + +/* AHB1 sleep mode enable register */ + +#define RCU_AHB1SPEN_PASPEN (1 << 0) /* Bit 0: GPIO port A clock enable when sleep mode */ +#define RCU_AHB1SPEN_PBSPEN (1 << 1) /* Bit 1: GPIO port B clock enable when sleep mode */ +#define RCU_AHB1SPEN_PCSPEN (1 << 2) /* Bit 2: GPIO port C clock enable when sleep mode */ +#define RCU_AHB1SPEN_PDSPEN (1 << 3) /* Bit 3: GPIO port D clock enable when sleep mode */ +#define RCU_AHB1SPEN_PESPEN (1 << 4) /* Bit 4: GPIO port E clock enable when sleep mode */ +#define RCU_AHB1SPEN_PFSPEN (1 << 5) /* Bit 5: GPIO port F clock enable when sleep mode */ +#define RCU_AHB1SPEN_PGSPEN (1 << 6) /* Bit 6: GPIO port G clock enable when sleep mode */ +#define RCU_AHB1SPEN_PHSPEN (1 << 7) /* Bit 7: GPIO port H clock enable when sleep mode */ +#define RCU_AHB1SPEN_PISPEN (1 << 8) /* Bit 8: GPIO port I clock enable when sleep mode */ +#define RCU_AHB1SPEN_CRCSPEN (1 << 12) /* Bit 12: CRC clock enable when sleep mode */ +#define RCU_AHB1SPEN_FMCSPEN (1 << 15) /* Bit 15: FMC clock enable when sleep mode */ +#define RCU_AHB1SPEN_SRAM0SPEN (1 << 16) /* Bit 16: SRAM0 clock enable when sleep mode */ +#define RCU_AHB1SPEN_SRAM1SPEN (1 << 17) /* Bit 17: SRAM1 clock enable when sleep mode */ +#define RCU_AHB1SPEN_BKPSRAMSPEN (1 << 18) /* Bit 18: BKPSRAM clock enable when sleep mode */ +#define RCU_AHB1SPEN_SRAM2SPEN (1 << 19) /* Bit 19: SRAM2 clock enable when sleep mode */ +#define RCU_AHB1SPEN_DMA0SPEN (1 << 21) /* Bit 21: DMA0 clock when sleep mode enable */ +#define RCU_AHB1SPEN_DMA1SPEN (1 << 22) /* Bit 22: DMA1 clock when sleep mode enable */ +#define RCU_AHB1SPEN_IPASPEN (1 << 23) /* Bit 23: IPA clock enable when sleep mode */ +#define RCU_AHB1SPEN_ENETSPEN (1 << 25) /* Bit 25: ENET clock enable when sleep mode */ +#define RCU_AHB1SPEN_ENETTXSPEN (1 << 26) /* Bit 26: Ethernet TX clock enable when sleep mode */ +#define RCU_AHB1SPEN_ENETRXSPEN (1 << 27) /* Bit 27: Ethernet RX clock enable when sleep mode */ +#define RCU_AHB1SPEN_ENETPTPSPEN (1 << 28) /* Bit 28: Ethernet PTP clock enable when sleep mode */ +#define RCU_AHB1SPEN_USBHSSPEN (1 << 29) /* Bit 29: USBHS clock enable when sleep mode */ +#define RCU_AHB1SPEN_USBHSULPISPEN (1 << 30) /* Bit 30: USBHS ULPI clock enable when sleep mode */ + +/* AHB2 sleep mode enable register */ + +#define RCU_AHB2SPEN_DCISPEN (1 << 0) /* Bit 0: DCI clock enable when sleep mode */ +#define RCU_AHB2SPEN_TRNGSPEN (1 << 6) /* Bit 6: TRNG clock enable when sleep mode */ +#define RCU_AHB2SPEN_USBFSSPEN (1 << 7) /* Bit 7: USBFS clock enable when sleep mode */ + +/* AHB1 sleep mode enable register */ + +#define RCU_AHB3SPEN_EXMCSPEN (1 << 0) /* Bit 0: EXMC clock enable when sleep mode */ + +/* APB1 sleep mode enable register */ + +#define RCU_APB1SPEN_TIMER1SPEN (1 << 0) /* Bit 0: TIMER1 clock enable when sleep mode */ +#define RCU_APB1SPEN_TIMER2SPEN (1 << 1) /* Bit 1: TIMER2 clock enable when sleep mode */ +#define RCU_APB1SPEN_TIMER3SPEN (1 << 2) /* Bit 2: TIMER3 clock enable when sleep mode */ +#define RCU_APB1SPEN_TIMER4SPEN (1 << 3) /* Bit 3: TIMER4 clock enable when sleep mode */ +#define RCU_APB1SPEN_TIMER5SPEN (1 << 4) /* Bit 4: TIMER5 clock enable when sleep mode */ +#define RCU_APB1SPEN_TIMER6SPEN (1 << 5) /* Bit 5: TIMER6 clock enable when sleep mode */ +#define RCU_APB1SPEN_TIMER11SPEN (1 << 6) /* Bit 6: TIMER11 clock enable when sleep mode */ +#define RCU_APB1SPEN_TIMER12SPEN (1 << 7) /* Bit 7: TIMER12 clock enable when sleep mode */ +#define RCU_APB1SPEN_TIMER13SPEN (1 << 8) /* Bit 8: TIMER13 clock enable when sleep mode */ +#define RCU_APB1SPEN_WWDGTSPEN (1 << 11) /* Bit 11: WWDGT clock enable when sleep mode */ +#define RCU_APB1SPEN_SPI1SPEN (1 << 14) /* Bit 15: SPI1 clock enable when sleep mode */ +#define RCU_APB1SPEN_SPI2SPEN (1 << 15) /* Bit 16: SPI2 clock enable when sleep mode */ +#define RCU_APB1SPEN_USART1SPEN (1 << 17) /* Bit 17: USART1 clock enable when sleep mode*/ +#define RCU_APB1SPEN_USART2SPEN (1 << 18) /* Bit 18: USART2 clock enable when sleep mode*/ +#define RCU_APB1SPEN_UART3SPEN (1 << 19) /* Bit 19: UART3 clock enable when sleep mode*/ +#define RCU_APB1SPEN_UART4SPEN (1 << 20) /* Bit 20: UART4 clock enable when sleep mode */ +#define RCU_APB1SPEN_I2C0SPEN (1 << 21) /* Bit 21: I2C0 clock enable when sleep mode */ +#define RCU_APB1SPEN_I2C1SPEN (1 << 22) /* Bit 22: I2C1 clock enable when sleep mode*/ +#define RCU_APB1SPEN_I2C2SPEN (1 << 23) /* Bit 23: I2C2 clock enable when sleep mode */ +#define RCU_APB1SPEN_CAN0SPEN (1 << 25) /* Bit 25: CAN0 clock enable when sleep mode*/ +#define RCU_APB1SPEN_CAN1SPEN (1 << 26) /* Bit 26: CAN1 clock enable when sleep mode */ +#define RCU_APB1SPEN_PMUSPEN (1 << 28) /* Bit 28: PMU clock enable when sleep mode */ +#define RCU_APB1SPEN_DACSPEN (1 << 29) /* Bit 29: DAC clock enable when sleep mode */ +#define RCU_APB1SPEN_UART6SPEN (1 << 30) /* Bit 0: UART6 clock enable when sleep mode */ +#define RCU_APB1SPEN_UART7SPEN (1 << 31) /* Bit 31: UART7 clock enable when sleep mode */ + +/* APB2 sleep mode enable register */ + +#define RCU_APB2SPEN_TIMER0SPEN (1 << 0) /* Bit 0: TIMER0 clock enable when sleep mode */ +#define RCU_APB2SPEN_TIMER7SPEN (1 << 1) /* Bit 1: TIMER7 clock enable when sleep mode */ +#define RCU_APB2SPEN_USART0SPEN (1 << 4) /* Bit 4: USART0 clock enable when sleep mode */ +#define RCU_APB2SPEN_USART5SPEN (1 << 5) /* Bit 5: USART5 clock enable when sleep mode */ +#define RCU_APB2SPEN_ADC0SPEN (1 << 8) /* Bit 8: ADC0 clock enable when sleep mode */ +#define RCU_APB2SPEN_ADC1SPEN (1 << 9) /* Bit 9: ADC1 clock enable when sleep mode */ +#define RCU_APB2SPEN_ADC2SPEN (1 << 10) /* Bit 10: ADC2 clock enable when sleep mode */ +#define RCU_APB2SPEN_SDIOSPEN (1 << 11) /* Bit 11: SDIO clock enable when sleep mode */ +#define RCU_APB2SPEN_SPI0SPEN (1 << 12) /* Bit 12: SPI0 clock enable when sleep mode */ +#define RCU_APB2SPEN_SPI3SPEN (1 << 13) /* Bit 13: SPI3 clock enable when sleep mode */ +#define RCU_APB2SPEN_SYSCFGSPEN (1 << 14) /* Bit 14: SYSCFG clock enable when sleep mode */ +#define RCU_APB2SPEN_TIMER8SPEN (1 << 16) /* Bit 16: TIMER8 clock enable when sleep mode */ +#define RCU_APB2SPEN_TIMER9SPEN (1 << 17) /* Bit 17: TIMER9 clock enable when sleep mode */ +#define RCU_APB2SPEN_TIMER10SPEN (1 << 18) /* Bit 18: TIMER10 clock enable when sleep mode */ +#define RCU_APB2SPEN_SPI4SPEN (1 << 20) /* Bit 20: SPI4 clock enable when sleep mode */ +#define RCU_APB2SPEN_SPI5SPEN (1 << 21) /* Bit 21: SPI5 clock enable when sleep mode */ +#define RCU_APB2SPEN_TLISPEN (1 << 26) /* Bit 26: TLI clock enable when sleep mode*/ + +/* Backup domain control register */ + +#define RCU_BDCTL_LXTALEN (1 << 0) /* Bit 0: LXTAL enable */ +#define RCU_BDCTL_LXTALSTB (1 << 1) /* Bit 1: Low speed crystal oscillator stabilization flag */ +#define RCU_BDCTL_LXTALBPS (1 << 2) /* Bit 2: LXTAL bypass mode enable */ +#define RCU_BDCTL_LXTALDRI (1 << 3) /* Bit 3: LXTAL drive capability */ +# define RCU_LXTALDRI_LOWER_DRIVE (0 << 3) /* LXTAL drive capability is selected lower */ +# define RCU_LXTALDRI_HIGHER_DRIVE RCU_BDCTL_LXTALDRI /* LXTAL drive capability is selected higher */ + +#define RCU_BDCTL_RTCSRC_SHIFT (8) /* Bits 8:9: RTC clock entry selection */ +#define RCU_BDCTL_RTCSRC_MASK (3 << RCU_BDCR_RTCSEL_SHIFT) +# define RCU_BDCTL_RTCSRC(n) ((n) << RCU_BDCR_RTCSEL_SHIFT) +# define RCU_RTCSRC_NONE RCU_BDCTL_RTCSRC(0) /* No clock selected */ +# define RCU_RTCSRC_LXTAL RCU_BDCTL_RTCSRC(1) /* RTC source clock select LXTAL */ +# define RCU_RTCSRC_IRC32K RCU_BDCTL_RTCSRC(2) /* RTC source clock select IRC32K */ +# define RCU_RTCSRC_HXTAL_DIV_RTCDIV RCU_BDCTL_RTCSRC(3) /* RTC source clock select HXTAL/RTCDIV */ + +#define RCU_BDCTL_RTCEN (1 << 15) /* Bit 15: RTC clock enable */ +#define RCU_BDCTL_BKPRST (1 << 16) /* Bit 16: Backup domain reset */ + +/* Reset source / clock register */ + +#define RCU_RSTSCK_IRC32KEN (1 << 0) /* Bit 0: IRC32K enable */ +#define RCU_RSTSCK_IRC32KSTB (1 << 1) /* Bit 1: IRC32K stabilization flag */ +#define RCU_RSTSCK_RSTFC (1 << 24) /* Bit 24: Reset flag clear */ +#define RCU_RSTSCK_BORRSTF (1 << 25) /* Bit 25: BOR reset flag */ +#define RCU_RSTSCK_EPRSTF (1 << 26) /* Bit 26: External pin reset flag */ +#define RCU_RSTSCK_PORRSTF (1 << 27) /* Bit 27: Power reset flag */ +#define RCU_RSTSCK_SWRSTF (1 << 28) /* Bit 28: Software reset flag */ +#define RCU_RSTSCK_FWDGTRSTF (1 << 29) /* Bit 29: Free watchdog timer reset flag */ +#define RCU_RSTSCK_WWDGTRSTF (1 << 30) /* Bit 30: Window watchdog timer reset flag */ +#define RCU_RSTSCK_LPRSTF (1 << 31) /* Bit 31: Low-power reset flag */ + +/* PLL clock spread spectrum control register */ + +#define RCU_PLLSSCTL_MODCNT_SHIFT (0) /* Bit 0-12: These bits configure PLL spread spectrum modulation + * profile amplitude and frequency. The following criteria + * must be met: MODSTEP*MODCNT<=2^15-1 */ +#define RCU_PLLSSCTL_MODCNT_MASK (0x1fff << RCU_PLLSSCTL_MODCNT_SHIFT) +# define RCU_PLLSSCTL_MODCNT(n) ((n) << RCU_PLLSSCTL_MODCNT_SHIFT) + +#define RCU_PLLSSCTL_MODSTEP_SHIFT (13) /* Bit 13-27: These bits configure PLL spread spectrum modulation + * profile amplitude and frequency. The following criteria + * must be met: MODSTEP*MODCNT<=2^15-1 */ +#define RCU_PLLSSCTL_MODSTEP_MASK (0x7fff << RCU_PLLSSCTL_MODSTEP_SHIFT) +# define RCU_PLLSSCTL_MODSTEP(n) ((n) << RCU_SSCGR_INCSTEP_SHIFT) + +#define RCU_PLLSSCTL_SS_TYPE (1 << 30) /* Bit 30: PLL spread spectrum modulation type select */ +#define RCU_PLLSSCTL_SSCGON (1 << 31) /* Bit 31: PLL spread spectrum modulation enable */ + +/* PLLI2S register */ + +#define RCU_PLLI2S_PLLI2SN_SHIFT (6) /* Bits 6-14: The PLLI2S VCO clock multi factor */ +#define RCU_PLLI2S_PLLI2SN_MASK (0x1ff << RCU_PLLI2S_PLLI2SN_SHIFT) +# define RCU_PLLI2S_PLLI2SN(n) ((n) << RCU_PLLI2S_PLLI2SN_SHIFT) /* CK_PLLI2SVCO = CK_PLLI2SVCOSRC*n, n=50..500 */ + +#define RCU_PLLI2S_PLLI2SR_SHIFT (28) /* Bits 28-30: The PLLI2S R output frequency division factor + * from PLLI2S VCO clock */ +#define RCU_PLLI2S_PLLI2SR_MASK (7 << RCU_PLLI2S_PLLI2SR_SHIFT) +# define RCU_PLLI2S_PLLI2SR(n) ((n) << RCU_PLLI2S_PLLI2SR_SHIFT) /* CK_PLLI2SR = CK_PLLI2SVCO/n, n=2..7 */ + +/* PLLSAI register */ + +#define RCU_PLLSAI_PLLSAIN_SHIFT (6) /* Bits 6-14: The PLLSAI VCO clock multi factor */ +#define RCU_PLLSAI_PLLSAIN_MASK (0x1ff << RCU_PLLSAI_PLLSAIN_SHIFT) +# define RCU_PLLSAI_PLLSAIN(n) ((n) << RCU_PLLSAI_PLLSAIN_SHIFT) /* n=50..500 */ + +#define RCU_PLLSAI_PLLSAIP_SHIFT (16) /* Bits 16-17: The PLLSAI P output frequency division factor + * from PLLSAI VCO clock */ +#define RCU_PLLSAI_PLLSAIP_MASK (3 << RCU_PLLSAI_PLLSAIP_SHIFT) +# define RCU_PLLSAI_PLLSAIP(n) ((((n)>>1)-1) << RCU_PLLSAI_PLLSAIP_SHIFT) /* n=2,4,6,8 */ +# define RCU_PLLSAI_PLLSAIP_DIV_2 RCU_PLLSAI_PLLSAIP(2) +# define RCU_PLLSAI_PLLSAIP_DIV_4 RCU_PLLSAI_PLLSAIP(4) +# define RCU_PLLSAI_PLLSAIP_DIV_6 RCU_PLLSAI_PLLSAIP(6) +# define RCU_PLLSAI_PLLSAIP_DIV_8 RCU_PLLSAI_PLLSAIP(8) + +#define RCU_PLLSAI_PLLSAIR_SHIFT (28) /* Bits 28-30: The PLLSAI R output frequency division factor + * from PLLSAI VCO clock */ +#define RCU_PLLSAI_PLLSAIR_MASK (7 << RCU_PLLSAI_PLLSAIR_SHIFT) +# define RCU_PLLSAI_PLLSAIR(n) ((n) << RCU_PLLSAI_PLLSAIR_SHIFT) /* n=2..7 */ + +/* Clock configuration register 1 */ + +#define RCU_CFG1_PLLSAIRDIV_SHIFT (16) /* Bits 16-17: The divider factor from PLLSAIR clock */ +#define RCU_CFG1_PLLSAIRDIV_MASK (3 << RCU_CFG1_PLLSAIRDIV_SHIFT) +# define RCU_CFG1_PLLSAIRDIV(n) ((((n)>>1)-1) << RCU_CFG1_PLLSAIRDIV_SHIFT) /* n=2,4,6,8 */ +# define RCU_CFG1_PLLSAIRDIV_DIV_2 RCU_CFG1_PLLSAIRDIV(2) +# define RCU_CFG1_PLLSAIRDIV_DIV_4 RCU_CFG1_PLLSAIRDIV(4) +# define RCU_CFG1_PLLSAIRDIV_DIV_6 RCU_CFG1_PLLSAIRDIV(6) +# define RCU_CFG1_PLLSAIRDIV_DIV_8 RCU_CFG1_PLLSAIRDIV(8) + +#define RCU_CFG1_TIMERSEL (1 << 24) /* Bit 24: TIMER clock selection */ + +/* Additional clock control register */ + +#define RCU_ADDCTL_CK48MSEL (1 << 0) /* Bit 0: 48MHz clock selection */ +#define RCU_ADDCTL_PLL48MSEL (1 << 1) /* Bit 1: PLL48M clock selection */ +#define RCU_ADDCTL_IRC48MEN (1 << 16) /* Bit 2: Internal 48MHz RC oscillator enable */ +#define RCU_ADDCTL_IRC48MSTB (1 << 17) /* Bit 3: Internal 48MHz RC oscillator clock stabilization flag */ +#define RCU_ADDCTL_IRC48MCAL_SHIFT (24) /* Bit 24-31: Internal 48MHz RC oscillator calibration value register */ +#define RCU_ADDCTL_IRC48MCAL_MASK (ff << 24) +# define RCU_ADDCTL_IRC48MCAL(n) ((n) << 24) + +/* Additional clock interrupt register */ + +#define RCU_ADDINT_IRC48MSTBIF (6) /* Bits 6: IRC48M stabilization interrupt flag */ +#define RCU_ADDINT_IRC48MSTBIE (14) /* Bit 14: Internal 48 MHz RC oscillator stabilization interrupt enable */ +#define RCU_ADDINT_IRC48MSTBIC (22) /* Bit 22: Iinternal 48 MHz RC oscillator stabilization interrupt clear */ + +/* APB1 additional reset register */ + +#define RCU_ADDAPB1RST_CTCRST (1 << 27) /* Bit 27: CTC reset */ +#define RCU_ADDAPB1RST_IREFRST (1 << 31) /* Bit 31: IREF reset */ + +/* APB1 additional enable register */ + +#define RCU_ADDAPB1EN_CTCEN (1 << 27) /* Bit 27: CTC clock enable */ +#define RCU_ADDAPB1EN_IREFEN (1 << 31) /* Bit 31: IREF interface clock enable */ + +/* APB1 additional sleep mode enable register */ + +#define RCU_ADDAPB1SPEN_CTCSPEN (1 << 27) /* Bit 27: CTC clock enable during sleep mode */ +#define RCU_ADDAPB1SPEN_IREFSPEN (1 << 31) /* Bit 31: IREF interface clock enable during sleep mode */ + +/* Voltage key register */ +#define RCU_VKEY_KEY_SHIFT (0) /* Bit 0-31: RCU_DSV key register */ +#define RCU_VKEY_KEY_MASK (ffffffff) +#define RCU_VKEY_UNLOCK (0x1A2B3C4D) /* The voltage key unlock value */ + +/* Deep-sleep mode voltage register */ +#define RCU_DSV_DSLPVS_SHIFT (0) /* Bit 0-2: Deep-sleep mode voltage select */ +#define RCU_DSV_DSLPVS_MASK ((3) << RCU_DSV_DSLPVS_SHIFT) +#define RCU_DSV_DSLPVS(n) ((n) << RCU_DSV_DSLPVS_SHIFT) +#define RCU_DEEPSLEEP_V_1_2 RCU_DSV_DSLPVS(0) /* Core voltage is 1.2V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_1 RCU_DSV_DSLPVS(1) /* Core voltage is 1.1V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_0 RCU_DSV_DSLPVS(2) /* Core voltage is 1.0V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_9 RCU_DSV_DSLPVS(3) /* Core voltage is 0.9V in deep-sleep mode */ + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_RCU_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_spi.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_spi.h new file mode 100644 index 0000000000..c21947be06 --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_spi.h @@ -0,0 +1,222 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_spi.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_SPI_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_SPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* SPIx(x=0,1,2,3,4,5) definitions */ +#define GD32_SPI0_BASE (GD32_SPI_BASE+0x0000F800) /* SPI0 base address */ +#define GD32_SPI1_BASE (GD32_SPI_BASE+0x00000000) /* SPI1 base address */ +#define GD32_SPI2_BASE (GD32_SPI_BASE+0x00000400) /* SPI2 base address */ +#define GD32_SPI3_BASE (GD32_SPI_BASE+0x0000FC00) /* SPI3 base address */ +#define GD32_SPI4_BASE (GD32_SPI_BASE+0x00011800) /* SPI4 base address */ +#define GD32_SPI5_BASE (GD32_SPI_BASE+0x00011C00) /* SPI5 base address */ + +/* I2Sx_ADD(x=1,2) definitions */ +#define GD32_I2S1_ADD_BASE (GD32_I2S_ADD_BASE+0x00000000) /* I2S1_ADD base address */ +#define GD32_I2S2_ADD_BASE (GD32_I2S_ADD_BASE+0x00000C00) /* I2S2_ADD base address */ + +/* Register Offsets *********************************************************/ +#define GD32_SPI_CTL0_OFFSET 0x0000 /* SPI control register 0 offset */ +#define GD32_SPI_CTL1_OFFSET 0x0004 /* SPI control register 1 offset */ +#define GD32_SPI_STAT_OFFSET 0x0008 /* SPI status register offset */ +#define GD32_SPI_DATA_OFFSET 0x000C /* SPI data register offset */ +#define GD32_SPI_CRCPOLY_OFFSET 0x0010 /* SPI CRC polynomial register offset */ +#define GD32_SPI_RCRC_OFFSET 0x0014 /* SPI receive CRC register offset */ +#define GD32_SPI_TCRC_OFFSET 0x0018 /* SPI transmit CRC register offset */ +#define GD32_SPI_I2SCTL_OFFSET 0x001C /* SPI I2S control register offset */ +#define GD32_SPI_I2SPSC_OFFSET 0x0020 /* SPI I2S clock prescaler register offset */ +#define GD32_SPI_QCTL_OFFSET 0x0080 /* SPI quad mode control register offset */ + +/* Register Addresses *******************************************************/ + +#define GD32_SPI0 GD32_SPI0_BASE +#define GD32_SPI1 GD32_SPI1_BASE +#define GD32_SPI2 GD32_SPI2_BASE +#define GD32_SPI3 GD32_SPI3_BASE +#define GD32_SPI4 GD32_SPI4_BASE +#define GD32_SPI5 GD32_SPI5_BASE + +#define GD32_I2S1_ADD GD32_I2S1_ADD_BASE +#define GD32_I2S2_ADD GD32_I2S2_ADD_BASE + +/* SPI registers definitions */ +#define GD32_SPI_CTL0(spix) ((spix)+GD32_SPI_CTL0_OFFSET) /* SPI control register 0 */ +#define GD32_SPI_CTL1(spix) ((spix)+GD32_SPI_CTL1_OFFSET) /* SPI control register 1*/ +#define GD32_SPI_STAT(spix) ((spix)+GD32_SPI_STAT_OFFSET) /* SPI status register */ +#define GD32_SPI_DATA(spix) ((spix)+GD32_SPI_DATA_OFFSET) /* SPI data register */ +#define GD32_SPI_CRCPOLY(spix) ((spix)+GD32_SPI_CRCPOLY_OFFSET) /* SPI CRC polynomial register */ +#define GD32_SPI_RCRC(spix) ((spix)+GD32_SPI_RCRC_OFFSET) /* SPI receive CRC register */ +#define GD32_SPI_TCRC(spix) ((spix)+GD32_SPI_TCRC_OFFSET) /* SPI transmit CRC register */ +#define GD32_SPI_I2SCTL(spix) ((spix)+GD32_SPI_I2SCTL_OFFSET) /* SPI I2S control register */ +#define GD32_SPI_I2SPSC(spix) ((spix)+GD32_SPI_I2SPSC_OFFSET) /* SPI I2S clock prescaler register */ +#define GD32_SPI_QCTL(spix) ((spix)+GD32_SPI_QCTL_OFFSET) /* SPI quad mode control register */ + +/* I2S_ADD registers definitions */ +#define I2S_ADD_CTL0(i2sx_add) ((i2sx_add)+GD32_SPI_CTL0_OFFSET) /* I2S_ADD control register 0 */ +#define I2S_ADD_CTL1(i2sx_add) ((i2sx_add)+GD32_SPI_CTL1_OFFSET) /* I2S_ADD control register 1*/ +#define I2S_ADD_STAT(i2sx_add) ((i2sx_add)+GD32_SPI_STAT_OFFSET) /* I2S_ADD status register */ +#define I2S_ADD_DATA(i2sx_add) ((i2sx_add)+GD32_SPI_DATA_OFFSET) /* I2S_ADD data register */ +#define I2S_ADD_CRCPOLY(i2sx_add) ((i2sx_add)+GD32_SPI_CRCPOLY_OFFSET) /* I2S_ADD CRC polynomial register */ +#define I2S_ADD_RCRC(i2sx_add) ((i2sx_add)+GD32_SPI_RCRC_OFFSET) /* I2S_ADD receive CRC register */ +#define I2S_ADD_TCRC(i2sx_add) ((i2sx_add)+GD32_SPI_TCRC_OFFSET) /* I2S_ADD transmit CRC register */ +#define I2S_ADD_I2SCTL(i2sx_add) ((i2sx_add)+GD32_SPI_I2SCTL_OFFSET) /* I2S_ADD I2S control register */ +#define I2S_ADD_I2SPSC(i2sx_add) ((i2sx_add)+GD32_SPI_I2SPSC_OFFSET) /* I2S_ADD I2S clock prescaler register */ + +/* Register Bitfield Definitions ********************************************/ + +/* Control register 0 */ + +#define SPI_CTL0_CKPH (1 << 0) /* Bit 0: clock phase selection*/ +#define SPI_CTL0_CKPL (1 << 1) /* Bit 1: clock polarity selection */ +#define SPI_CTL0_MSTMOD (1 << 2) /* Bit 2: master mode enable */ +#define SPI_CTL0_PSC_SHIFT (3) /* Bit 3-5: master clock prescaler selection */ +#define SPI_CTL0_PSC_MASK (7 << SPI_CTL0_PSC_SHIFT) +#define SPI_CTL0_PSC(n) ((n) << SPI_CTL0_PSC_SHIFT) +# define SPI_CTL0_PSC_2 SPI_CTL0_PSC(0) /* 000: SPI clock prescale factor is 2 */ +# define SPI_CTL0_PSC_4 SPI_CTL0_PSC(1) /* 001: SPI clock prescale factor is 4 */ +# define SPI_CTL0_PSC_8 SPI_CTL0_PSC(2) /* 010: SPI clock prescale factor is 8 */ +# define SPI_CTL0_PSC_16 SPI_CTL0_PSC(3) /* 011: SPI clock prescale factor is 16 */ +# define SPI_CTL0_PSC_32 SPI_CTL0_PSC(4) /* 100: SPI clock prescale factor is 32 */ +# define SPI_CTL0_PSC_64 SPI_CTL0_PSC(5) /* 101: SPI clock prescale factor is 64 */ +# define SPI_CTL0_PSC_128 SPI_CTL0_PSC(6) /* 110: SPI clock prescale factor is 128 */ +# define SPI_CTL0_PSC_256 SPI_CTL0_PSC(7) /* 111: SPI clock prescale factor is 256 */ + +#define SPI_CTL0_SPIEN (1 << 6) /* Bit 6: SPI enable*/ +#define SPI_CTL0_LF (1 << 7) /* Bit 7: lsb first mode */ +#define SPI_CTL0_SWNSS (1 << 8) /* Bit 8: nss pin selection in nss software mode */ +#define SPI_CTL0_SWNSSEN (1 << 9) /* Bit 9: nss software mode selection */ +#define SPI_CTL0_RO (1 << 10) /* Bit 10: receive only */ +#define SPI_CTL0_FF16 (1 << 11) /* Bit 11: data frame size */ +#define SPI_CTL0_CRCNT (1 << 12) /* Bit 12: CRC next transfer */ +#define SPI_CTL0_CRCEN (1 << 13) /* Bit 13: CRC calculation enable */ +#define SPI_CTL0_BDOEN (1 << 14) /* Bit 14: bidirectional transmit output enable*/ +#define SPI_CTL0_BDEN (1 << 15) /* Bit 15: bidirectional enable */ + +/* SPI_CTL1 */ +#define SPI_CTL1_DMAREN (1 << 0) /* Bit 0: receive buffer dma enable */ +#define SPI_CTL1_DMATEN (1 << 1) /* Bit 1: transmit buffer dma enable */ +#define SPI_CTL1_NSSDRV (1 << 2) /* Bit 2: drive nss output */ +#define SPI_CTL1_TMOD (1 << 4) /* Bit 4: SPI TI mode enable */ +#define SPI_CTL1_ERRIE (1 << 5) /* Bit 5: errors interrupt enable */ +#define SPI_CTL1_RBNEIE (1 << 6) /* Bit 6: receive buffer not empty interrupt enable */ +#define SPI_CTL1_TBEIE (1 << 7) /* Bit 7: transmit buffer empty interrupt enable */ + +/* SPI_STAT */ +#define SPI_STAT_RBNE (1 << 0) /* Bit 0: receive buffer not empty */ +#define SPI_STAT_TBE (1 << 1) /* Bit 1: transmit buffer empty */ +#define SPI_STAT_I2SCH (1 << 2) /* Bit 2: I2S channel side */ +#define SPI_STAT_TXURERR (1 << 3) /* Bit 3: I2S transmission underrun error bit */ +#define SPI_STAT_CRCERR (1 << 4) /* Bit 4: SPI CRC error bit */ +#define SPI_STAT_CONFERR (1 << 5) /* Bit 5: SPI configuration error bit */ +#define SPI_STAT_RXORERR (1 << 6) /* Bit 6: SPI reception overrun error bit */ +#define SPI_STAT_TRANS (1 << 7) /* Bit 7: transmitting on-going bit */ +#define SPI_STAT_FERR (1 << 8) /* Bit 8: format error bit */ + +/* SPI_DATA */ +#define SPI_DATA_SHIFT (0) /* Bits 0-15: data transfer register */ +#define SPI_DATA_MASK (0xffff << SPI_DATA_SHIFT) + +/* SPI_CRCPOLY */ +#define SPI_CRCPOLY_CPR_SHIFT (0) /* Bits 0-15: CRC polynomial register */ +#define SPI_CRCPOLY_CPR__MASK (0xffff << SPI_CRCPOLY_CPR_SHIFT) + +/* SPI_RCRC */ +#define SPI_RCRC_RCR_SHIFT (0) /* Bits 0-15: CRX CRC register */ +#define SPI_RCRC_RCR_MASK (0xffff << SPI_RCRC_RCR_SHIFT) + +/* SPI_TCRC */ +#define SPI_TCRC_TCR_SHIFT (0) /* Bits 0-15: TX CRC register */ +#define SPI_TCRC_TCR_MASK (0xffff << SPI_TCRC_TCR_SHIFT) + +/* SPI_I2SCTL */ +#define SPI_I2SCTL_CHLEN (1 << 0) /* Bit 0: channel length */ +#define SPI_I2SCTL_DTLEN_SHIFT (1) /* Bit 1-2: data length */ +#define SPI_I2SCTL_DTLEN_MASK (3 << SPI_I2SCTL_DTLEN_SHIFT) +#define SPI_I2SCTL_DTLEN(n) ((n) << SPI_I2SCTL_DTLEN_SHIFT) +# define SPI_I2SCTL_DTLEN_DT16B SPI_I2SCTL_DTLEN(0) /* 00: 16 bits */ +# define SPI_I2SCTL_DTLEN_DT24B SPI_I2SCTL_DTLEN(1) /* 00: 24 bits */ +# define SPI_I2SCTL_DTLEN_DT32B SPI_I2SCTL_DTLEN(2) /* 00: 32 bits */ + +#define SPI_I2SCTL_CKPL (1 << 3) /* Bit 3: idle state clock polarity */ +#define SPI_I2SCTL_I2SSTD_SHIFT (4) /* Bit 4-5: I2S standard selection */ +#define SPI_I2SCTL_I2SSTD_MASK (3 << SPI_I2SCTL_I2SSTD_SHIFT) +#define SPI_I2SCTL_I2SSTD(n) ((n) << SPI_I2SCTL_I2SSTD_SHIFT) +# define SPI_I2SSTD_PHILLIPS SPI_I2SCTL_I2SSTD(0) /* 00: I2S Phillips standard */ +# define SPI_I2SSTD_MSB SPI_I2SCTL_I2SSTD(0) /* 01: MSB justified standard */ +# define SPI_I2SSTD_LSB SPI_I2SCTL_I2SSTD(0) /* 10: LSB justified standard */ +# define SPI_I2SSTD_PCM SPI_I2SCTL_I2SSTD(0) /* 11: PCM standard*/ + +#define SPI_I2SCTL_PCMSMOD (1 << 7) /* Bit 7: PCM frame synchronization mode */ + +#define SPI_I2SCTL_I2SOPMOD_SHIIFT (8) /* Bit 8-9: I2S operation mode */ +#define SPI_I2SCTL_I2SOPMOD_MASK (3 << SPI_I2SCTL_I2SOPMOD_SHIIFT) +#define SPI_I2SCTL_I2SOPMOD(n) ((n) << SPI_I2SCTL_I2SOPMOD_SHIIFT) +# define SPI_I2SCTL_I2SOPMSTRAN SPI_I2SCTL_I2SOPMOD(0) /* 00: Slave transmission mode */ +# define SPI_I2SCTL_I2SOPMSRECV SPI_I2SCTL_I2SOPMOD(1) /* 01: Slave reception mode */ +# define SPI_I2SCTL_I2SOPMMTRAN SPI_I2SCTL_I2SOPMOD(2) /* 10: Master transmission mode */ +# define SPI_I2SCTL_I2SOPMMRECV SPI_I2SCTL_I2SOPMOD(3) /* 11: Master reception mode */ + +#define SPI_I2SCTL_I2SEN (1 << 10) /* Bit 10: I2S enable */ +#define SPI_I2SCTL_I2SSEL (1 << 11) /* Bit 11: I2S mode selection */ + +/* SPI_I2S_PSC */ + +#define SPI_I2SPSC_DIV_SHIFT (0) /* Bit0-7: dividing factor for the prescaler */ +#define SPI_I2SPSC_DIV_MASK (0xff << SPI_I2SPSC_DIV_SHIFT) +#define SPI_I2SPSC_DIV(n) ((n) << SPI_I2SPSC_DIV_SHIFT) /* Real divider value is DIV * 2 + OF. */ + +#define SPI_I2SPSC_OF (1 << 8) /* Bit8: odd factor for the prescaler */ +#define SPI_I2SPSC_MCKOEN (1 << 9) /* Bit9: I2S MCK output enable */ + +/* SPI_SPI_QCTL(only SPI5) */ +#define SPI_QCTL_QMOD (1 << 0) /* Bit0: quad-SPI mode enable */ +#define SPI_QCTL_QRD (1 << 1) /* Bit1: quad-SPI mode read select */ +#define SPI_QCTL_IO23_DRV (1 << 2) /* Bit2: drive SPI_IO2 and SPI_IO3 enable */ + +/* SPI DMA enable */ +#define SPI_CTL1_DMAEN (SPI_CTL1_DMAREN | SPI_CTL1_DMATEN) /* SPI RX/TX DMA enable */ + +/* SPI mode definitions */ +#define SPI_MASTER (SPI_CTL0_MSTMOD | SPI_CTL0_SWNSS) /* SPI as master, SWNSS=1 to prevent CONFERR */ +#define SPI_SLAVE (0x00000000) /* SPI as slave */ + +/* SPI bidirectional transfer direction */ +#define SPI_BIDIRECTIONAL_TRANSMIT SPI_CTL0_BDOEN /* SPI work in transmit-only mode */ +#define SPI_BIDIRECTIONAL_RECEIVE SPI_CTL0_BDOEN) /* SPI work in receive-only mode */ + +/* SPI transmit type */ +#define SPI_TRANSMODE_FULLDUPLEX (00000000) /* SPI receive and send data at fullduplex communication */ +#define SPI_TRANSMODE_RECEIVEONLY SPI_CTL0_RO /* SPI only receive data */ +#define SPI_TRANSMODE_BDRECEIVE SPI_CTL0_BDEN /* bidirectional receive data */ +#define SPI_TRANSMODE_BDTRANSMIT (SPI_CTL0_BDEN | SPI_CTL0_BDOEN) /* bidirectional transmit data*/ + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_SPI_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_syscfg.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_syscfg.h new file mode 100644 index 0000000000..3c208107c7 --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_syscfg.h @@ -0,0 +1,170 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_syscfg.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_SYSCFG_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_SYSCFG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define GD32_SYSCFG_CFG0_OFFSET 0x0000 /* System configuration register 0 */ +#define GD32_SYSCFG_CFG1_OFFSET 0x0004 /* System configuration register 1 */ +#define GD32_SYSCFG_EXTISS0_OFFSET 0x0008 /* EXTI sources selection register 0 */ +#define GD32_SYSCFG_EXTISS1_OFFSET 0x000c /* EXTI sources selection register 0 */ +#define GD32_SYSCFG_EXTISS2_OFFSET 0x0010 /* EXTI sources selection register 0 */ +#define GD32_SYSCFG_EXTISS3_OFFSET 0x0014 /* EXTI sources selection register 0 */ +#define GD32_SYSCFG_CPSCTLOFFSET 0x0020 /* System I/O compensation control register */ + +/* Register Addresses *******************************************************/ + +#define GD32_SYSCFG_CFG0 (GD32_SYSCFG_BASE+GD32_SYSCFG_CFG0_OFFSET) +#define GD32_SYSCFG_CFG1 (GD32_SYSCFG_BASE+GD32_SYSCFG_CFG1_OFFSET) +#define GD32_SYSCFG_EXTISS0 (GD32_SYSCFG_BASE+GD32_SYSCFG_EXTISS0_OFFSET) +#define GD32_SYSCFG_EXTISS1 (GD32_SYSCFG_BASE+GD32_SYSCFG_EXTISS1_OFFSET) +#define GD32_SYSCFG_EXTISS2 (GD32_SYSCFG_BASE+GD32_SYSCFG_EXTISS2_OFFSET) +#define GD32_SYSCFG_EXTISS3 (GD32_SYSCFG_BASE+GD32_SYSCFG_EXTISS3_OFFSET) +#define GD32_SYSCFG_CPSCTL (GD32_SYSCFG_BASE+GD32_SYSCFG_CPSCTLOFFSET) + +/* Register Bitfield Definitions ********************************************/ + +/* System configuration register 0 */ + +/* boot mode definitions */ +#define SYSCFG_CFG0_BOOT_MODE_SHIFT (0) /* Bits 2:0 BOOT_MODE: SYSCFG memory remap config */ +#define SYSCFG_CFG0_BOOT_MODE_MASK (7 << SYSCFG_CFG0_BOOT_MODE_SHIFT) +# define SYSCFG_BOOTMODE_FLASH (0 << SYSCFG_CFG0_BOOT_MODE_SHIFT) /* 000: Main flash memory remap */ +# define SYSCFG_BOOTMODE_BOOTLOADER (1 << SYSCFG_CFG0_BOOT_MODE_SHIFT) /* 001: Boot loader remap */ +# define SYSCFG_BOOTMODE_EXMC_SRAM (2 << SYSCFG_CFG0_BOOT_MODE_SHIFT) /* 010: SRAM/NOR 0 and 1 of EXMC remap */ +# define SYSCFG_BOOTMODE_SRAM (3 << SYSCFG_CFG0_BOOT_MODE_SHIFT) /* 011: SRAM0 of on-chip SRAM remap */ +# define SYSCFG_BOOTMODE_EXMC_SDRAM (4 << SYSCFG_CFG0_BOOT_MODE_SHIFT) /* 100: SDRAM bank0 of EXMC remap */ + +/* FMC swap definitions */ + +#define SYSCFG_CFG0_FMC_SWP_SHIFT (8) /* FMC memory swap config */ +#define SYSCFG_CFG0_FMC_SWP_MASK (1 << SYSCFG_CFG0_FMC_SWP_SHIFT) +# define SYSCFG_FMC_SWP_BANK0 (0 << SYSCFG_CFG0_FMC_SWP_SHIFT) /* Main flash Bank 0 is mapped at address 0x08000000 */ +# define SYSCFG_FMC_SWP_BANK1 (1 << SYSCFG_CFG0_FMC_SWP_SHIFT) /* Main flash Bank 1 is mapped at address 0x08000000 */ + +/* EXMC swap enable/disable */ + +#define SYSCFG_CFG0_EXMC_SWP_SHIFT (9) /* EXMC memory swap config */ +#define SYSCFG_CFG0_EXMC_SWP_MASK (1 << SYSCFG_CFG0_EXMC_SWP_SHIFT) +# define SYSCFG_EXMC_SWP_ENABLE (1 << SYSCFG_CFG0_EXMC_SWP_SHIFT) /* SDRAM bank 0 and bank 1 are swapped with NAND bank 1 and PC card */ +# define SYSCFG_EXMC_SWP_DISABLE (0 << SYSCFG_CFG0_EXMC_SWP_SHIFT) /* No memory mapping swap */ + +/* System configuration register 1 */ + +/* Ethernet PHY selection */ +#define SYSCFG_CFG1_ENET_PHY_SEL_SHIFT (23) /* Ethernet PHY selection config */ +#define SYSCFG_CFG1_ENET_PHY_SEL_MASK (1 << SYSCFG_CFG1_ENET_PHY_SEL_SHIFT) +# define SYSCFG_ENET_PHY_MII (0<< SYSCFG_CFG1_ENET_PHY_SEL_SHIFT) /* MII is selected for the Ethernet MAC */ +# define SYSCFG_ENET_PHY_RMII (1 << SYSCFG_CFG1_ENET_PHY_SEL_SHIFT) /* RMII is selected for the Ethernet MAC */ + +/* SYSCFG external interrupt configuration register 0-3 */ + +/* SYSCFG_EXTISS0 bits definitions */ +#define SYSCFG_EXTISS0_EXTI0_SHIFT (0) +#define SYSCFG_EXTISS0_EXTI0_MASK (15 << SYSCFG_EXTISS0_EXTI0_SHIFT) +#define SYSCFG_EXTISS0_EXTI1_SHIFT (4) +#define SYSCFG_EXTISS0_EXTI1_MASK (15 << SYSCFG_EXTISS0_EXTI1_SHIFT) +#define SYSCFG_EXTISS0_EXTI2_SHIFT (8) +#define SYSCFG_EXTISS0_EXTI2_MASK (15 << SYSCFG_EXTISS0_EXTI2_SHIFT) +#define SYSCFG_EXTISS0_EXTI3_SHIFT (12) +#define SYSCFG_EXTISS0_EXTI3_MASK (15 << SYSCFG_EXTISS0_EXTI3_MASK) + +/* SYSCFG_EXTISS1 bits definitions */ +#define SYSCFG_EXTISS1_EXTI0_SHIFT (0) +#define SYSCFG_EXTISS1_EXTI0_MASK (15 << SYSCFG_EXTISS1_EXTI0_SHIFT) +#define SYSCFG_EXTISS1_EXTI1_SHIFT (4) +#define SYSCFG_EXTISS1_EXTI1_MASK (15 << SYSCFG_EXTISS1_EXTI1_SHIFT) +#define SYSCFG_EXTISS1_EXTI2_SHIFT (8) +#define SYSCFG_EXTISS1_EXTI2_MASK (15 << SYSCFG_EXTISS1_EXTI2_SHIFT) +#define SYSCFG_EXTISS1_EXTI3_SHIFT (12) +#define SYSCFG_EXTISS1_EXTI3_MASK (15 << SYSCFG_EXTISS1_EXTI3_SHIFT) + +/* SYSCFG_EXTISS2 bits definitions */ +#define SYSCFG_EXTISS2_EXTI0_SHIFT (0) +#define SYSCFG_EXTISS2_EXTI0_MASK (15 << SYSCFG_EXTISS2_EXTI0_SHIFT) +#define SYSCFG_EXTISS2_EXTI1_SHIFT (4) +#define SYSCFG_EXTISS2_EXTI1_MASK (15 << SYSCFG_EXTISS2_EXTI1_SHIFT) +#define SYSCFG_EXTISS2_EXTI2_SHIFT (8) +#define SYSCFG_EXTISS2_EXTI2_MASK (15 << SYSCFG_EXTISS2_EXTI2_SHIFT) +#define SYSCFG_EXTISS2_EXTI3_SHIFT (12) +#define SYSCFG_EXTISS2_EXTI3_MASK (15 << SYSCFG_EXTISS2_EXTI3_SHIFT) + +/* SYSCFG_EXTISS3 bits definitions */ +#define SYSCFG_EXTISS3_EXTI0_SHIFT (0) +#define SYSCFG_EXTISS3_EXTI0_MASK (15 << SYSCFG_EXTISS3_EXTI0_SHIFT) +#define SYSCFG_EXTISS3_EXTI1_SHIFT (4) +#define SYSCFG_EXTISS3_EXTI1_MASK (15 << SYSCFG_EXTISS3_EXTI1_SHIFT) +#define SYSCFG_EXTISS3_EXTI2_SHIFT (8) +#define SYSCFG_EXTISS3_EXTI2_MASK (15 << SYSCFG_EXTISS3_EXTI2_SHIFT) +#define SYSCFG_EXTISS3_EXTI3_SHIFT (12) +#define SYSCFG_EXTISS3_EXTI3_MASK (15 << SYSCFG_EXTISS3_EXTI3_SHIFT) + +/* EXTI source select definition */ +#define SYSCFG_EXTISS0 (0x00) /* EXTI source select GPIOx pin 0~3 */ +#define SYSCFG_EXTISS1 (0x01) /* EXTI source select GPIOx pin 4~7 */ +#define SYSCFG_EXTISS2 (0x02) /* EXTI source select GPIOx pin 8~11 */ +#define SYSCFG_EXTISS3 (0x03) /* EXTI source select GPIOx pin 12~15 */ + +/* EXTI source select mask bits definition */ +#define SYSCFG_EXTI_SS_MASK (15) /* EXTI source select mask */ + +/* EXTI source select jumping step definition */ +#define SYSCFG_EXTI_SS_JSTEP (0x04) /* EXTI source select jumping step */ + +/* EXTI source select moving step definition */ +#define SYSCFG_EXTI_SS_MSTEP(pin) (SYSCFG_EXTI_SS_JSTEP*((pin)%SYSCFG_EXTI_SS_JSTEP)) /* EXTI source select moving step */ + +#define EXTI_SOURCE_GPIOA (0) /* EXTI GPIOA configuration */ +#define EXTI_SOURCE_GPIOB (1) /* EXTI GPIOA configuration */ +#define EXTI_SOURCE_GPIOC (2) /* EXTI GPIOA configuration */ +#define EXTI_SOURCE_GPIOD (3) /* EXTI GPIOA configuration */ +#define EXTI_SOURCE_GPIOE (4) /* EXTI GPIOA configuration */ +#define EXTI_SOURCE_GPIOF (5) /* EXTI GPIOA configuration */ +#define EXTI_SOURCE_GPIOG (6) /* EXTI GPIOA configuration */ +#define EXTI_SOURCE_GPIOH (7) /* EXTI GPIOA configuration */ +#define EXTI_SOURCE_GPIOI (8) /* EXTI GPIOA configuration */ + +/* System I/O compensation control register */ + +/* I/O compensation cell enable/disable */ +#define SYSCFG_CPSCTL_CPS_EN_SHILT (0) /* I/O compensation cell enable bit */ +#define SYSCFG_CPSCTL_CPS_EN_MASK (1 << SYSCFG_CPSCTL_CPS_EN_SHILT) +# define SYSCFG_COMPENSATION_ENABLE (1 << SYSCFG_CPSCTL_CPS_EN_SHILT) /* I/O compensation cell enable */ +# define SYSCFG_COMPENSATION_DISABLE (1 << SYSCFG_CPSCTL_CPS_EN_SHILT) /* I/O compensation cell disable */ + +#define SYSCFG_CPSCTL_CPS_RDY_SHIFT (8) /* I/O compensation cell is ready or not */ +#define SYSCFG_CPSCTL_CPS_RDY_MASK (1 << SYSCFG_CPSCTL_CPS_RDY_SHIFT) +#define SYSCFG_CPSCTL_CPS_RDY_SET (1 << SYSCFG_CPSCTL_CPS_RDY_SHIFT) /* Ready */ +#define SYSCFG_CPSCTL_CPS_RDY_RESET (1 << SYSCFG_CPSCTL_CPS_RDY_SHIFT) /* Not ready */ + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_SYSCFG_H */ diff --git a/arch/arm/src/gd32f4/hardware/gd32f4xx_uart.h b/arch/arm/src/gd32f4/hardware/gd32f4xx_uart.h new file mode 100644 index 0000000000..0ab4066446 --- /dev/null +++ b/arch/arm/src/gd32f4/hardware/gd32f4xx_uart.h @@ -0,0 +1,244 @@ +/**************************************************************************** + * arch/arm/src/gd32f4/hardware/gd32f4xx_uart.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_UART_H +#define __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_UART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) definitions */ +#define GD32_USART1_BASE (GD32_USART_BASE+0x00000000) /* USART1 base address */ +#define GD32_USART2_BASE (GD32_USART_BASE+0x00000400) /* USART2 base address */ +#define GD32_UART3_BASE (GD32_USART_BASE+0x00000800) /* UART3 base address */ +#define GD32_UART4_BASE (GD32_USART_BASE+0x00000C00) /* UART4 base address */ +#define GD32_UART6_BASE (GD32_USART_BASE+0x00003400) /* UART6 base address */ +#define GD32_UART7_BASE (GD32_USART_BASE+0x00003800) /* UART7 base address */ +#define GD32_USART0_BASE (GD32_USART_BASE+0x0000CC00) /* USART0 base address */ +#define GD32_USART5_BASE (GD32_USART_BASE+0x0000D000) /* USART5 base address */ + +/* Register Offsets *********************************************************/ + +#define GD32_USART_STAT0_OFFSET 0x0000 /* USART status register 0 offset */ +#define GD32_USART_DATA_OFFSET 0x0004 /* USART data register offset */ +#define GD32_USART_BAUD_OFFSET 0x0008 /* USART baud rate register offset */ +#define GD32_USART_CTL0_OFFSET 0x000c /* USART control register 0 offset */ +#define GD32_USART_CTL1_OFFSET 0x0010 /* USART control register 1 offset */ +#define GD32_USART_CTL2_OFFSET 0x0014 /* USART control register 2 offset */ +#define GD32_USART_GP_OFFSET 0x0018 /* USART guard time and prescaler registet offset */ +#define GD32_USART_CTL3_OFFSET 0x0080 /* USART control register 3 offset */ +#define GD32_USART_RT_OFFSET 0x0084 /* USART receiver timeout register offset */ +#define GD32_USART_STAT1_OFFSET 0x0088 /* USART status register 1 offset */ +#define GD32_USART_CHC_OFFSET 0x00C0 /* USART coherence control register offset */ + +/* Register Addresses *******************************************************/ + +#define GD32_USART1 GD32_USART1_BASE +#define GD32_USART2 GD32_USART2_BASE +#define GD32_UART3 GD32_UART3_BASE +#define GD32_UART4 GD32_UART4_BASE +#define GD32_UART6 GD32_UART6_BASE +#define GD32_UART7 GD32_UART7_BASE +#define GD32_USART0 GD32_USART0_BASE +#define GD32_USART5 GD32_USART5_BASE + +/* USART0,1,2,5 Register ****************************************************/ + +#define GD32_USART_STAT0(usartx) ((usartx)+GD32_USART_STAT0_OFFSET) /* USART status register 0 */ +#define GD32_USART_DATA(usartx) ((usartx)+GD32_USART_DATA_OFFSET) /* USART data register */ +#define GD32_USART_BAUD(usartx) ((usartx)+GD32_USART_BAUD_OFFSET) /* USART baud rate register */ +#define GD32_USART_CTL0(usartx) ((usartx)+GD32_USART_CTL0_OFFSET) /* USART control register 0 */ +#define GD32_USART_CTL1(usartx) ((usartx)+GD32_USART_CTL1_OFFSET) /* USART control register 1 */ +#define GD32_USART_CTL2(usartx) ((usartx)+GD32_USART_CTL2_OFFSET) /* USART control register 2 */ +#define GD32_USART_GP(usartx) ((usartx)+GD32_USART_GP_OFFSET) /* USART guard time and prescaler register */ +#define GD32_USART_CTL3(usartx) ((usartx)+GD32_USART_CTL3_OFFSET) /* USART control register 3 offset */ +#define GD32_USART_RT(usartx) ((usartx)+GD32_USART_RT_OFFSET) /* USART receiver timeout register */ +#define GD32_USART_STAT1(usartx) ((usartx)+GD32_USART_STAT1_OFFSET) /* USART status register 1 */ +#define GD32_USART_CHC(usartx) ((usartx)+GD32_USART_CHC_OFFSET) /* USART coherence control register */ + +/* UART3,4,6,7 Register *****************************************************/ + +#define GD32_UART_STAT0(uartx) ((uartx)+GD32_USART_STAT0_OFFSET) /* UART status register 0 */ +#define GD32_UART_DATA(uartx) ((uartx)+GD32_USART_DATA_OFFSET) /* UART data register */ +#define GD32_UART_BAUD(uartx) ((uartx)+GD32_USART_BAUD_OFFSET) /* UART baud rate register */ +#define GD32_UART_CTL0(uartx) ((uartx)+GD32_USART_CTL0_OFFSET) /* UART control register 0 */ +#define GD32_UART_CTL1(uartx) ((uartx)+GD32_USART_CTL1_OFFSET) /* UART control register 1 */ +#define GD32_UART_CTL2(uartx) ((uartx)+GD32_USART_CTL2_OFFSET) /* UART control register 2 */ +#define GD32_UART_GP(uartx) ((uartx)+GD32_USART_GP_OFFSET) /* UART guard time and prescaler register */ +#define GD32_UART_CHC(uartx) ((uartx)+GD32_USART_CHC_OFFSET) /* UART coherence control register */ + +/* Register Bitfield Definitions ********************************************/ + +/* Status register 0 */ + +#define USART_STAT0_PERR (1 << 0) /* Bit 0: Parity error flag */ +#define USART_STAT0_FERR (1 << 1) /* Bit 1: Frame error flag */ +#define USART_STAT0_NERR (1 << 2) /* Bit 2: Noise error flag */ +#define USART_STAT0_ORERR (1 << 3) /* Bit 3: OverRun error */ +#define USART_STAT0_IDLEF (1 << 4) /* Bit 4: IDLE frame detected flag */ +#define USART_STAT0_RBNE (1 << 5) /* Bit 5: Read data buffer not empty */ +#define USART_STAT0_TC (1 << 6) /* Bit 6: Transmission complete */ +#define USART_STAT0_TBE (1 << 7) /* Bit 7: Transmit data buffer empty */ +#define USART_STAT0_LBDF (1 << 8) /* Bit 8: LIN break detected flag */ +#define USART_STAT0_CTSF (1 << 9) /* Bit 9: CTS change flag */ + +#define USART_STAT0_MASK (0x03ff) + +/* Data register */ + +#define USART_DATA_SHIFT (0) /* Bits 0-8: Transmit or read data value */ +#define USART_DATA_MASK (0xff << USART_DATA_SHIFT) + +/* Baud Rate Register */ + +#define USART_BAUD_FRADIV_SHIFT (0) /* Bits 0-3: Fraction part of baud-rate divider */ +#define USART_BAUD_FRADIV_MASK (0x0f << USART_BAUD_FRADIV_SHIFT) +# define USART_BAUD_FRADIV(n) ((n) << USART_BAUD_FRADIV_SHIFT) +#define USART_BAUD_INTDIV_SHIFT (4) /* Bits 4-15: Integer part of baud-rate divider */ +#define USART_BAUD_INTDIV_MASK (0xfff << USART_BAUD_INTDIV_SHIFT) +# define USART_BAUD_INTDIV(n) ((n) << USART_BAUD_INTDIV_SHIFT) + +/* Control register 0 */ + +#define USART_CTL0_SBKCMD (1 << 0) /* Bit 0: Send break command */ +#define USART_CTL0_RWU (1 << 1) /* Bit 1: Receiver wakeup from mute mode */ +#define USART_CTL0_REN (1 << 2) /* Bit 2: Receiver Enable */ +#define USART_CTL0_TEN (1 << 3) /* Bit 3: Transmitter Enable */ +#define USART_CTL0_IDLEIE (1 << 4) /* Bit 4: Idle line detected interrupt enable */ +#define USART_CTL0_RBNEIE (1 << 5) /* Bit 5: Read data buffer not empty interrupt and overrun error interrupt enable */ +#define USART_CTL0_TCIE (1 << 6) /* Bit 6: Transmission complete interrupt enable */ +#define USART_CTL0_TBEIE (1 << 7) /* Bit 7: Transmitter buffer empty interrupt enable */ +#define USART_CTL0_PERRIE (1 << 8) /* Bit 8: Parity error interrupt enable */ +#define USART_CTL0_PM (1 << 9) /* Bit 9: Parity mode */ +#define USART_CTL0_PCEN (1 << 10) /* Bit 10: Parity check function enable */ +#define USART_CTL0_WM (1 << 11) /* Bit 11: Wakeup method in mute mode */ +#define USART_CTL0_WL (1 << 12) /* Bit 12: Word length */ +#define USART_CTL0_UEN (1 << 13) /* Bit 13: USART Enable */ +#define USART_CTL0_OVSMOD (1 << 15) /* Bit 15: Oversample mode */ + +#define USART_CTL0_PM_SHIFT (9) +# define USART_CTL0_PM_MASK (0x3 << USART_CTL0_PM_SHIFT) +# define USART_CTL0_PMEN(n) ((n) << USART_CTL0_PM_SHIFT) +# define USART_CTL0_PM_NONE USART_CTL0_PMEN(0) +# define USART_CTL0_PM_EVEN USART_CTL0_PMEN(2) +# define USART_CTL0_PM_ODD USART_CTL0_PMEN(3) + +#define USART_WL_9BIT USART_CTL0_WL +#define USART_WL_8BIT (0) + +#define USART_CTL0_INT_SHIFT (4) +#define USART_CTL0_INT_MASK (0x1f << USART_CTL0_INT_SHIFT) + +/* Control register 1 */ + +#define USART_CTL1_ADDR_SHIFT (0) /* Bits 0-3: Address of USART */ +#define USART_CTL1_ADDR_MASK (0x0f << USART_CTL1_ADDR_SHIFT) +#define USART_CTL1_ADDR(n) ((n) << USART_CTL1_ADDR_SHIFT) +#define USART_CTL1_LBLEN (1 << 5) /* Bit 5: LIN break frame Length */ +#define USART_CTL1_LBDIE (1 << 6) /* Bit 6: LIN break detected interrupt enable */ +#define USART_CTL1_CLEN (1 << 8) /* Bit 8: CK length */ +#define USART_CTL1_CPH (1 << 9) /* Bit 9: CK phase */ +#define USART_CTL1_CPL (1 << 10) /* Bit 10: CK polarity */ +#define USART_CTL1_CKEN (1 << 11) /* Bit 11: CK pin enable */ +#define USART_CTL1_STB_SHIFT (12) /* Bits 12-13: STOP bits length */ +#define USART_CTL1_STB_MASK (3 << USART_CTL1_STB_SHIFT) +# define USART_CTL1_STB(n) (n << USART_CTL1_STB_SHIFT) +# define USART_CTL1_STB1BIT USART_CTL1_STB(0) /* 00: 1 bit */ +# define USART_CTL1_STB0_5BIT USART_CTL1_STB(1) /* 01: 0.5 bit */ +# define USART_CTL1_STB2BIT USART_CTL1_STB(2) /* 10: 2 bits */ +# define USART_CTL1_STB1_5BIT USART_CTL1_STB(3) /* 11: 1.5 bit */ + +#define USART_CTL1_LMEN (1 << 14) /* Bit 14: LIN mode enable */ + +#define USART_CTL1_INT_MASK USART_CTL1_LBDIE + +/* Control register 2 */ + +#define USART_CTL2_ERRIE (1 << 0) /* Bit 0: Error interrupt enable */ +#define USART_CTL2_IREN (1 << 1) /* Bit 1: IrDA mode enable */ +#define USART_CTL2_IRLP (1 << 2) /* Bit 2: IrDA low-power */ +#define USART_CTL2_HDEN (1 << 3) /* Bit 3: Half-duplex enable */ +#define USART_CTL2_NKEN (1 << 4) /* Bit 4: NACK enable in smartcard mode */ +#define USART_CTL2_SCEN (1 << 5) /* Bit 5: Smartcard mode enable */ +#define USART_CTL2_DENR (1 << 6) /* Bit 6: DMA request enable for reception */ +#define USART_CTL2_DENT (1 << 7) /* Bit 7: DMA request enable for transmission */ +#define USART_CTL2_RTSEN (1 << 8) /* Bit 8: RTS enable */ +#define USART_CTL2_CTSEN (1 << 9) /* Bit 9: CTS enable */ +#define USART_CTL2_CTSIE (1 << 10) /* Bit 10: CTS interrupt enable */ +#define USART_CTL2_OSB (1 << 11) /* Bit 11: One sample bit method */ + +#define USART_CTL2_INT_MASK (USART_CTL2_ERRIE | USART_CTL2_CTSIE) + +/* USART guard time and prescaler register */ + +#define USART_GP_PSC_SHIFT (0) /* Bits 0-7: Prescaler value for dividing the system clock */ +#define USART_GP_PSC_MASK (0xff << USART_GP_PSC_SHIFT) +# define USART_GP_PSC(n) ((n) << USART_GP_PSC_SHIFT) +#define USART_GP_GUAT_SHIFT (8) /* Bits 8-15: Guard time value in smartcard mode */ +#define USART_GP_GUAT_MASK (0xff << USART_GP_GUAT_SHIFT) +# define USART_GP_GUAT(n) ((n) << USART_GP_GUAT_SHIFT) + +/* USART control register 3 offset */ + +#define USART_CTL3_RTEN (1 << 0) /* Bit 0: Receiver timeout enable */ +#define USART_CTL3_SCRTNUM_SHIFT (1) /* Bit 1-3: Smartcard auto-retry number */ +#define USART_CTL3_SCRTNUM_MASK (0x07 << USART_CTL3_SCRTNUM_SHIFT) +# define USART_CTL3_SCRTNUM(n) ((n) << USART_CTL3_SCRTNUM_SHIFT) +#define USART_CTL3_RTIE (1 << 4) /* Bit 4: Interrupt enable bit of receive timeout event */ +#define USART_CTL3_EBIE (1 << 5) /* Bit 5: Interrupt enable bit of end of block event */ +#define USART_CTL3_RINV (1 << 8) /* Bit 8: RX pin level inversion */ +#define USART_CTL3_TINV (1 << 9) /* Bit 9: TX pin level inversion */ +#define USART_CTL3_DINV (1 << 10) /* Bit 10: Data bit level inversion */ +#define USART_CTL3_MSBF (1 << 11) /* Bit 11: Most significant bit first */ + +#define USART_CTL3_INT_MASK (USART_CTL3_RTIE | USART_CTL3_EBIE) + +/* USART receiver timeout register */ + +#define USART_RT_RT_SHIFT (0) /* Bit 0-23: Receiver timeout threshold */ +#define USART_RT_RT_MASK (0xffffff << USART_RT_RT_SHIFT) +# define USART_RT_RT(n) ((n) << USART_RT_RT_SHIFT) +#define USART_RT_BL_SHIFT (24) /* Bit 24-31: Block length */ +#define USART_RT_BL_MASK (0xff << USART_RT_BL_SHIFT) +# define USART_RT_BL(n) ((n) << USART_RT_BL_SHIFT) + +/* USART status register 1 */ + +#define USART_STAT1_RTF (1 << 11) /* Bit 11: Receiver timeout flag */ +#define USART_STAT1_EBF (1 << 12) /* Bit 12: End of block flag */ +#define USART_STAT1_BSY (1 << 16) /* Bit 16: Busy flag */ + +/* USART coherence control register */ + +#define USART_CHC_HCM (1 << 0) /* Bit 0: Hardware flow control coherence mode */ +#define USART_CHC_PCM (1 << 1) /* Bit 1: Parity check coherence mode */ +#define USART_CHC_BCM (1 << 2) /* Bit 2: Break frame coherence mode */ +#define USART_CHC_EPERR (1 << 8) /* Bit 8: Early parity error flag */ + +#endif /* __ARCH_ARM_SRC_GD32F4_HARDWARE_GD32F4XX_UART_H */ diff --git a/boards/Kconfig b/boards/Kconfig index 2805aa19d6..364fd022f5 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -474,6 +474,15 @@ config ARCH_BOARD_FREEDOM_KL26Z This is the configuration for the NXP/FreeScale Freedom KL26Z board. This board has the K26Z128VLH4 chip with a built-in SDA debugger. +config ARCH_BOARD_GD32F450ZK_EVAL + bool "GD32 MCU GD32F450ZK" + depends on ARCH_CHIP_GD32F450ZK + select ARCH_HAVE_LEDS + select ARCH_HAVE_BUTTONS + select ARCH_HAVE_IRQBUTTONS + ---help--- + GD32 MCU GD32F450ZK-EVAL board based on the GD32F4 GD32F450ZKT6 MCU. + config ARCH_BOARD_HIFIVE1_REVB bool "HiFive1 Rev B board" depends on ARCH_CHIP_FE310 @@ -2631,6 +2640,7 @@ config ARCH_BOARD default "freedom-k66f" if ARCH_BOARD_FREEDOM_K66F default "freedom-kl25z" if ARCH_BOARD_FREEDOM_KL25Z default "freedom-kl26z" if ARCH_BOARD_FREEDOM_KL26Z + default "gd32f450zk-eval" if ARCH_BOARD_GD32F450ZK_EVAL default "hifive1-revb" if ARCH_BOARD_HIFIVE1_REVB default "hymini-stm32v" if ARCH_BOARD_HYMINI_STM32V default "imxrt1020-evk" if ARCH_BOARD_IMXRT1020_EVK @@ -2983,6 +2993,9 @@ endif if ARCH_BOARD_FREEDOM_KL26Z source "boards/arm/kl/freedom-kl26z/Kconfig" endif +if ARCH_BOARD_GD32F450ZK_EVAL +source "boards/arm/gd32f4/gd32f450zk-eval/Kconfig" +endif if ARCH_BOARD_TEENSY_LC source "boards/arm/kl/teensy-lc/Kconfig" endif diff --git a/boards/arm/gd32f4/gd32f450zk-eval/Kconfig b/boards/arm/gd32f4/gd32f450zk-eval/Kconfig new file mode 100644 index 0000000000..c71bdccc77 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/Kconfig @@ -0,0 +1,121 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_GD32F450ZK_EVAL + +choice + prompt "Select Console wiring." + default GD32F450ZK_EVAL_CONSOLE_BOARD + ---help--- + Select where you will connect the console. + + Virtual COM Port: + + Advantage: Use the ST-Link as a console. No Extra wiring + needed. + + Disadvantage: Not the best choice for initial bring up. + + BOARD USART Connector: + + Advantage: You have a shield so it is easy. + + Disadvantage: You loose the use of the + other functions on PA9, PA10 + + GD32F450ZK_EVAL + USART0 GPIO + -- ----- --------- ---- + RX USART0_RX PA10 + TX USART0_TX PA9 + -- ----- --------- --- + +config GD32F450ZK_EVAL_CONSOLE_BOARD + bool "Eval Com Connector" + select GD32_USART0 + select USART0_SERIALDRIVER + select USART0_SERIAL_CONSOLE + select GD32F4_FLASH_CONFIG_K + +config GD32F450ZK_EVAL_CONSOLE_VIRTUAL + bool "Virtual Comport" + select GD32_USART3 + select USART3_SERIALDRIVER + select USART3_SERIAL_CONSOLE + +config GD32F450ZK_EVAL_CONSOLE_NONE + bool "No Console" + +endchoice # "Select Console wiring" + + +choice + prompt "GD32F4 MCU Crystal Selected" + default GD32F4_BOARD_USE_HXTAL + +config GD32F4_BOARD_USE_HXTAL + bool "Use Hxtal as clock source" + # select GD32F4_BOARD_HXTAL_VALUE + +config GD32F4_BOARD_USE_IRC16 + bool "Use IRC16M as clock source" + +endchoice # CPU Frequency + +config GD32F4_BOARD_HXTAL_VALUE + int "GD32F450Z Eval Board Hxtal Value" + default 25000000 + depends on GD32F4_BOARD_USE_HXTAL + ---help--- + GD32F450Z Eval Board Hxtal Value, default is 25MHz. + +choice + prompt "GD32F4 MCU System Frequency" + default GD32F4_200MHZ + +config GD32F4_200MHZ + bool "200 MHz" + +config GD32F4_168MHZ + bool "168 MHz" + +config GD32F4_120MHZ + bool "120 MHz" + +endchoice # CPU Frequency + + +config GD32F4_GD25_BLOCKMOUNT + bool "GD25 serial FLASH auto-mount" + default n + depends on GD32F4_SPI5 && MTD_GD25 + ---help--- + Automatically initialize the GD25 SPI FLASH driver when NSH starts. + +choice + prompt "GD25 SPI FLASH configuration" + default GD32F4_GD25_NXFFS + depends on GD32F4_GD25_BLOCKMOUNT + +config GD32F4_GD25_FTL + bool "Create GD25 SPI FLASH block driver" + ---help--- + Create the MTD driver for the GD25 and "wrap" the GD25 as a standard + block driver that could then, for example, be mounted using FAT or + any other file system. Any file system may be used, but there will + be no wear-leveling. + +config GD32F4_GD25_NXFFS + bool "Create GD25 serial FLASH NXFFS file system" + depends on FS_NXFFS + ---help--- + Create the MTD driver for the GD25 and mount the GD25 device as + a wear-leveling, NuttX FLASH file system (NXFFS). The downside of + NXFFS is that it can be very slow. + +endchoice # GD25 serial FLASH configuration + + +endif # ARCH_BOARD_GD32F450ZK_EVAL diff --git a/boards/arm/gd32f4/gd32f450zk-eval/configs/btngpionsh/defconfig b/boards/arm/gd32f4/gd32f450zk-eval/configs/btngpionsh/defconfig new file mode 100644 index 0000000000..8e23e89540 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/configs/btngpionsh/defconfig @@ -0,0 +1,99 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="gd32f450zk-eval" +CONFIG_ARCH_BOARD_GD32F450ZK_EVAL=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP="gd32f4" +CONFIG_ARCH_CHIP_GD32F450ZK=y +CONFIG_ARCH_CHIP_GD32F4=y +CONFIG_ARCH_IRQBUTTONS=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEBUG_CUSTOMOPT=y +CONFIG_DEBUG_OPTLEVEL="-O0" +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_GPIO=y +CONFIG_ETH0_PHY_DP83848C=y +CONFIG_EXAMPLES_BUTTONS=y +CONFIG_EXAMPLES_GPIO=y +CONFIG_FS_NXFFS=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_FS_TMPFS=y +CONFIG_GD25_SPIFREQUENCY=4000000 +CONFIG_GD32F4_168MHZ=y +CONFIG_GD32F4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y +CONFIG_GD32F4_ENETMAC=y +CONFIG_GD32F4_FLASH_CONFIG_K=y +CONFIG_GD32F4_GD25_BLOCKMOUNT=y +CONFIG_GD32F4_PHY_SR=16 +CONFIG_GD32F4_PHY_SR_100FD=0x0004 +CONFIG_GD32F4_PHY_SR_100HD=0x0000 +CONFIG_GD32F4_PHY_SR_10FD=0x0006 +CONFIG_GD32F4_PHY_SR_10HD=0x0002 +CONFIG_GD32F4_PHY_SR_ALTCONFIG=y +CONFIG_GD32F4_PHY_SR_ALTMODE=0x006 +CONFIG_GD32F4_RMII_EXTCLK=y +CONFIG_GD32F4_SPI5=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INPUT=y +CONFIG_INPUT_BUTTONS=y +CONFIG_INPUT_BUTTONS_LOWER=y +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=2 +CONFIG_MTD=y +CONFIG_MTD_BYTE_WRITE=y +CONFIG_MTD_GD25=y +CONFIG_NET=y +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETINIT_DRIPADDR=0x0a320301 +CONFIG_NETINIT_IPADDR=0x0a320336 +CONFIG_NETINIT_MACADDR_1=0x20304050 +CONFIG_NETINIT_MACADDR_2=0x6080 +CONFIG_NETINIT_NOMAC=y +CONFIG_NETUTILS_DISCOVER=y +CONFIG_NETUTILS_WEBCLIENT=y +CONFIG_NET_ARP_IPIN=y +CONFIG_NET_ARP_SEND=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1500 +CONFIG_NET_ICMP=y +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_IGMP=y +CONFIG_NET_LOOPBACK=y +CONFIG_NET_ROUTE=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_UDP=y +CONFIG_NET_UDP_CHECKSUMS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART0_SERIAL_CONSOLE=y diff --git a/boards/arm/gd32f4/gd32f450zk-eval/configs/fmcfsnsh/defconfig b/boards/arm/gd32f4/gd32f450zk-eval/configs/fmcfsnsh/defconfig new file mode 100644 index 0000000000..cf2aaba245 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/configs/fmcfsnsh/defconfig @@ -0,0 +1,88 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="gd32f450zk-eval" +CONFIG_ARCH_BOARD_GD32F450ZK_EVAL=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP="gd32f4" +CONFIG_ARCH_CHIP_GD32F450ZK=y +CONFIG_ARCH_CHIP_GD32F4=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEBUG_CUSTOMOPT=y +CONFIG_DEBUG_OPTLEVEL="-O0" +CONFIG_DEBUG_SYMBOLS=y +CONFIG_ETH0_PHY_DP83848C=y +CONFIG_FS_NXFFS=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_FS_TMPFS=y +CONFIG_GD32F4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y +CONFIG_GD32F4_ENETMAC=y +CONFIG_GD32F4_FLASH_CONFIG_K=y +CONFIG_GD32F4_FMC=y +CONFIG_GD32F4_MTD=y +CONFIG_GD32F4_PHY_SR=16 +CONFIG_GD32F4_PHY_SR_100FD=0x0004 +CONFIG_GD32F4_PHY_SR_100HD=0x0000 +CONFIG_GD32F4_PHY_SR_10FD=0x0006 +CONFIG_GD32F4_PHY_SR_10HD=0x0002 +CONFIG_GD32F4_PHY_SR_ALTCONFIG=y +CONFIG_GD32F4_PHY_SR_ALTMODE=0x006 +CONFIG_GD32F4_PROGMEM=y +CONFIG_GD32F4_RMII_EXTCLK=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=2 +CONFIG_NET=y +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETINIT_DRIPADDR=0x0a320301 +CONFIG_NETINIT_IPADDR=0x0a320336 +CONFIG_NETINIT_MACADDR_1=0x20304050 +CONFIG_NETINIT_MACADDR_2=0x6080 +CONFIG_NETINIT_NOMAC=y +CONFIG_NETUTILS_DISCOVER=y +CONFIG_NETUTILS_WEBCLIENT=y +CONFIG_NET_ARP_IPIN=y +CONFIG_NET_ARP_SEND=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1500 +CONFIG_NET_ICMP=y +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_IGMP=y +CONFIG_NET_LOOPBACK=y +CONFIG_NET_ROUTE=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_UDP=y +CONFIG_NET_UDP_CHECKSUMS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART0_SERIAL_CONSOLE=y diff --git a/boards/arm/gd32f4/gd32f450zk-eval/configs/netnsh/defconfig b/boards/arm/gd32f4/gd32f450zk-eval/configs/netnsh/defconfig new file mode 100644 index 0000000000..9b51c8b71a --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/configs/netnsh/defconfig @@ -0,0 +1,84 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="gd32f450zk-eval" +CONFIG_ARCH_BOARD_GD32F450ZK_EVAL=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP="gd32f4" +CONFIG_ARCH_CHIP_GD32F450ZK=y +CONFIG_ARCH_CHIP_GD32F4=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEBUG_CUSTOMOPT=y +CONFIG_DEBUG_OPTLEVEL="-O0" +CONFIG_DEBUG_SYMBOLS=y +CONFIG_ETH0_PHY_DP83848C=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_FS_TMPFS=y +CONFIG_GD32F4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y +CONFIG_GD32F4_ENETMAC=y +CONFIG_GD32F4_FLASH_CONFIG_K=y +CONFIG_GD32F4_PHY_SR=16 +CONFIG_GD32F4_PHY_SR_100FD=0x0004 +CONFIG_GD32F4_PHY_SR_100HD=0x0000 +CONFIG_GD32F4_PHY_SR_10FD=0x0006 +CONFIG_GD32F4_PHY_SR_10HD=0x0002 +CONFIG_GD32F4_PHY_SR_ALTCONFIG=y +CONFIG_GD32F4_PHY_SR_ALTMODE=0x006 +CONFIG_GD32F4_RMII_EXTCLK=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=2 +CONFIG_NET=y +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETINIT_DRIPADDR=0x0a320301 +CONFIG_NETINIT_IPADDR=0x0a320336 +CONFIG_NETINIT_MACADDR_1=0x20304050 +CONFIG_NETINIT_MACADDR_2=0x6080 +CONFIG_NETINIT_NOMAC=y +CONFIG_NETUTILS_DISCOVER=y +CONFIG_NETUTILS_WEBCLIENT=y +CONFIG_NET_ARP_IPIN=y +CONFIG_NET_ARP_SEND=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1500 +CONFIG_NET_ICMP=y +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_IGMP=y +CONFIG_NET_LOOPBACK=y +CONFIG_NET_ROUTE=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_UDP=y +CONFIG_NET_UDP_CHECKSUMS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART0_SERIAL_CONSOLE=y diff --git a/boards/arm/gd32f4/gd32f450zk-eval/configs/nsh/defconfig b/boards/arm/gd32f4/gd32f450zk-eval/configs/nsh/defconfig new file mode 100644 index 0000000000..f0709b882d --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/configs/nsh/defconfig @@ -0,0 +1,49 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="gd32f450zk-eval" +CONFIG_ARCH_BOARD_GD32F450ZK_EVAL=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP="gd32f4" +CONFIG_ARCH_CHIP_GD32F450ZK=y +CONFIG_ARCH_CHIP_GD32F4=y +CONFIG_ARCH_INTERRUPTSTACK=256 +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEBUG_CUSTOMOPT=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_IRQ=y +CONFIG_DEBUG_LEDS=y +CONFIG_DEBUG_OPTLEVEL="-O0" +CONFIG_DEBUG_SCHED=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_FS_PROCFS=y +CONFIG_GD32F4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y +CONFIG_GD32F4_FLASH_CONFIG_K=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=2 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART0_SERIAL_CONSOLE=y diff --git a/boards/arm/gd32f4/gd32f450zk-eval/configs/spifsnsh/defconfig b/boards/arm/gd32f4/gd32f450zk-eval/configs/spifsnsh/defconfig new file mode 100644 index 0000000000..392141ad22 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/configs/spifsnsh/defconfig @@ -0,0 +1,92 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="gd32f450zk-eval" +CONFIG_ARCH_BOARD_GD32F450ZK_EVAL=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP="gd32f4" +CONFIG_ARCH_CHIP_GD32F450ZK=y +CONFIG_ARCH_CHIP_GD32F4=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEBUG_CUSTOMOPT=y +CONFIG_DEBUG_OPTLEVEL="-O0" +CONFIG_DEBUG_SYMBOLS=y +CONFIG_ETH0_PHY_DP83848C=y +CONFIG_FS_NXFFS=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_FS_TMPFS=y +CONFIG_GD25_SPIFREQUENCY=4000000 +CONFIG_GD32F4_168MHZ=y +CONFIG_GD32F4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y +CONFIG_GD32F4_ENETMAC=y +CONFIG_GD32F4_FLASH_CONFIG_K=y +CONFIG_GD32F4_GD25_BLOCKMOUNT=y +CONFIG_GD32F4_PHY_SR=16 +CONFIG_GD32F4_PHY_SR_100FD=0x0004 +CONFIG_GD32F4_PHY_SR_100HD=0x0000 +CONFIG_GD32F4_PHY_SR_10FD=0x0006 +CONFIG_GD32F4_PHY_SR_10HD=0x0002 +CONFIG_GD32F4_PHY_SR_ALTCONFIG=y +CONFIG_GD32F4_PHY_SR_ALTMODE=0x006 +CONFIG_GD32F4_RMII_EXTCLK=y +CONFIG_GD32F4_SPI5=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=2 +CONFIG_MTD=y +CONFIG_MTD_BYTE_WRITE=y +CONFIG_MTD_GD25=y +CONFIG_NET=y +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETINIT_DRIPADDR=0x0a320301 +CONFIG_NETINIT_IPADDR=0x0a320336 +CONFIG_NETINIT_MACADDR_1=0x20304050 +CONFIG_NETINIT_MACADDR_2=0x6080 +CONFIG_NETINIT_NOMAC=y +CONFIG_NETUTILS_DISCOVER=y +CONFIG_NETUTILS_WEBCLIENT=y +CONFIG_NET_ARP_IPIN=y +CONFIG_NET_ARP_SEND=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1500 +CONFIG_NET_ICMP=y +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_IGMP=y +CONFIG_NET_LOOPBACK=y +CONFIG_NET_ROUTE=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_UDP=y +CONFIG_NET_UDP_CHECKSUMS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART0_SERIAL_CONSOLE=y diff --git a/boards/arm/gd32f4/gd32f450zk-eval/include/board.h b/boards/arm/gd32f4/gd32f450zk-eval/include/board.h new file mode 100644 index 0000000000..b290994e26 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/include/board.h @@ -0,0 +1,351 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/include/board.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_GD32F450ZK_EVAL_INCLUDE_BOARD_H +#define __BOARDS_ARM_GD32F450ZK_EVAL_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +#define GD32_BOARD_SYSCLK_PLL_HXTAL + +/* Do not include GD32F4 header files here */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Clocking *****************************************************************/ + +/* The GD32F450ZK-EVAL board features a single 25MHz crystal. + * + * This is the default configuration: + * System clock source : PLL (HXTAL) + * SYSCLK(Hz) : 200000000 Determined by PLL config + * HCLK(Hz) : 200000000 (GD32_SYSCLK_FREQUENCY) + * AHB Prescaler : 1 (GD32_RCU_CFG0_AHB_PSC) + * APB2 Prescaler : 2 (GD32_RCU_CFG0_APB2_PSC) + * APB1 Prescaler : 4 (GD32_RCU_CFG0_APB1_PSC) + * HXTAL value(Hz) : 25000000 (GD32_BOARD_XTAL) + * PLLM : 25 (GD32_PLL_PLLM) + * PLLN : 400 (RCU_PLL_PLLN) + * PLLP : 2 (GD32_PLL_PLLP) + * PLLQ : 7 (GD32_PLL_PLLQ) + */ + +/* IRC16M - 16 MHz RC factory-trimmed + * IRC32K - 32 KHz RC + * HXTAL - On-board crystal frequency is 25MHz + * LXTAL - 32.768 kHz + */ + +#ifndef CONFIG_GD32F4_BOARD_HXTAL_VALUE +# define GD32_BOARD_HXTAL 25000000ul +#else +# define GD32_BOARD_HXTAL CONFIG_GD32F4_BOARD_HXTAL_VALUE +#endif + +#define GD32_IRC16M_VALUE 16000000ul +#define GD32_IRC32K_VALUE 32000u +#define GD32_HXTAL_VALUE GD32_BOARD_HXTAL +#define GD32_LXTAL_VALUE 32768u + +#if defined(CONFIG_GD32F4_200MHZ) + +/* Main PLL Configuration. + * + * PLL source is HXTAL + * PLL_VCO = (GD32_HXTAL_VALUE / PLLM) * PLLN + * = (25,000,000 / 25) * 400 + * = 400,000,000 + * SYSCLK = PLL_VCO / PLLP + * = 400,000,000 / 2 = 168,000,000 + * USB, SDIO and RNG Clock + * = PLL_VCO / PLLQ + * = 48,000,000 + */ + +#define GD32_PLL_PLLPSC RCU_PLL_PLLPSC(25) +#define GD32_PLL_PLLN RCU_PLL_PLLN(400) +#define GD32_PLL_PLLP RCU_PLL_PLLP(2) +#define GD32_PLL_PLLQ RCU_PLL_PLLQ(7) + +#define GD32_SYSCLK_FREQUENCY 200000000ul + +#elif defined(CONFIG_GD32F4_168MHZ) + +/* Main PLL Configuration. + * + * PLL source is HXTAL + * PLL_VCO = (GD32_HXTAL_VALUE / PLLM) * PLLN + * = (25,000,000 / 25) * 336 + * = 336,000,000 + * SYSCLK = PLL_VCO / PLLP + * = 336,000,000 / 2 = 168,000,000 + * USB, SDIO and RNG Clock + * = PLL_VCO / PLLQ + * = 48,000,000 + */ + +#define GD32_PLL_PLLPSC RCU_PLL_PLLPSC(25) +#define GD32_PLL_PLLN RCU_PLL_PLLN(336) +#define GD32_PLL_PLLP RCU_PLL_PLLP(2) +#define GD32_PLL_PLLQ RCU_PLL_PLLQ(7) + +#define GD32_SYSCLK_FREQUENCY 168000000ul + +#endif + +/* AHB clock (HCLK) is SYSCLK */ + +#define GD32_RCU_CFG0_AHB_PSC RCU_CFG0_AHBPSC_CKSYS_DIV1 /* HCLK = SYSCLK / 1 */ +#define GD32_HCLK_FREQUENCY GD32_SYSCLK_FREQUENCY + +/* APB2 clock (PCLK2) is HCLK/2 */ + +#define GD32_RCU_CFG0_APB2_PSC RCU_CFG0_APB2PSC_CKAHB_DIV2 /* PCLK2 = HCLK / 2 */ +#define GD32_PCLK2_FREQUENCY (GD32_HCLK_FREQUENCY/2) + +/* APB1 clock (PCLK1) is HCLK/4 */ + +#define GD32_RCU_CFG0_APB1_PSC RCU_CFG0_APB1PSC_CKAHB_DIV4 /* PCLK1 = HCLK / 4 */ +#define GD32_PCLK1_FREQUENCY (GD32_HCLK_FREQUENCY / 4) + +/* Timers driven from APB1 will be twice PCLK1 */ + +#define GD32_APB1_TIMER2_CLKIN (2*GD32_PCLK1_FREQUENCY) +#define GD32_APB1_TIMER3_CLKIN (2*GD32_PCLK1_FREQUENCY) +#define GD32_APB1_TIMER4_CLKIN (2*GD32_PCLK1_FREQUENCY) +#define GD32_APB1_TIMER5_CLKIN (2*GD32_PCLK1_FREQUENCY) +#define GD32_APB1_TIMER6_CLKIN (2*GD32_PCLK1_FREQUENCY) +#define GD32_APB1_TIMER7_CLKIN (2*GD32_PCLK1_FREQUENCY) +#define GD32_APB1_TIMER12_CLKIN (2*GD32_PCLK1_FREQUENCY) +#define GD32_APB1_TIMER13_CLKIN (2*GD32_PCLK1_FREQUENCY) +#define GD32_APB1_TIMER14_CLKIN (2*GD32_PCLK1_FREQUENCY) + +/* Timers driven from APB2 will be twice PCLK2 */ + +#define GD32_APB2_TIMER1_CLKIN (2*GD32_PCLK2_FREQUENCY) +#define GD32_APB2_TIMER8_CLKIN (2*GD32_PCLK2_FREQUENCY) +#define GD32_APB2_TIMER9_CLKIN (2*GD32_PCLK2_FREQUENCY) +#define GD32_APB2_TIMER10_CLKIN (2*GD32_PCLK2_FREQUENCY) +#define GD32_APB2_TIMER11_CLKIN (2*GD32_PCLK2_FREQUENCY) + +/* Timer Frequencies, if APBx is set to 1, frequency is same to APBx + * otherwise frequency is 2xAPBx. + * Note: TIMER1,8 are on APB2, others on APB1 + */ + +#define BOARD_TIMER1_FREQUENCY GD32_HCLK_FREQUENCY +#define BOARD_TIMER2_FREQUENCY (GD32_HCLK_FREQUENCY/2) +#define BOARD_TIMER3_FREQUENCY (GD32_HCLK_FREQUENCY/2) +#define BOARD_TIMER4_FREQUENCY (GD32_HCLK_FREQUENCY/2) +#define BOARD_TIMER5_FREQUENCY (GD32_HCLK_FREQUENCY/2) +#define BOARD_TIMER6_FREQUENCY (GD32_HCLK_FREQUENCY/2) +#define BOARD_TIMER7_FREQUENCY (GD32_HCLK_FREQUENCY/2) +#define BOARD_TIMER8_FREQUENCY GD32_HCLK_FREQUENCY + +/* LED definitions **********************************************************/ + +/* The GD32F450ZK_EVAL board has board has three LEDs. The LED1, LED2 and + * LED3 are controlled by GPIO. LED1 is connected to PD4, LED2 is connected + * to PD5, LED3 is connected to PG3 + * + * If CONFIG_ARCH_LEDS is not defined, then the user can control the LEDs + * in any way. + * The following definitions are used to access individual LEDs. + */ + +/* LED index values */ + +typedef enum +{ + BOARD_LED1 = 0, + BOARD_LED2 = 1, + BOARD_LED3 = 2, + BOARD_LEDS +} led_typedef_enum; + +/* LED bits */ + +#define BOARD_LED1_BIT (1 << BOARD_LED1) +#define BOARD_LED2_BIT (1 << BOARD_LED2) +#define BOARD_LED3_BIT (1 << BOARD_LED3) + +/* If CONFIG_ARCH_LEDS is defined, the usage by the board port is defined in + * include/board.h and src/gd32f4xx_autoleds.c. The LEDs are used to encode + * OS-related events as follows: + * + * + * SYMBOL Meaning LED state + * LED1 LED2 LED3 + * ---------------------- -------------------------- ------ ------ --- + */ + +#define LED_STARTED 0 /* NuttX has been started OFF OFF OFF */ +#define LED_HEAPALLOCATE 1 /* Heap has been allocated ON OFF OFF */ +#define LED_IRQSENABLED 2 /* Interrupts enabled OFF ON OFF */ +#define LED_STACKCREATED 3 /* Idle stack created OFF OFF ON */ +#define LED_INIRQ 4 /* In an interrupt ON ON OFF */ +#define LED_SIGNAL 5 /* In a signal handler ON OFF ON */ +#define LED_ASSERTION 6 /* An assertion failed OFF ON ON */ +#define LED_PANIC 7 /* The system has crashed FLASH ON ON */ +#define LED_IDLE 8 /* MCU is is sleep mode OFF FLASH OFF */ + +/* Button definitions *******************************************************/ + +/* The GD32F450Z Eval supports three user buttons: Wakeup, Tamper and + * User key, they are connected to GPIO PA0, PC13, PB14. + * A low value will be sensed when the button is depressed. + */ + +typedef enum +{ + BUTTON_WAKEUP = 0, + BUTTON_TAMPER = 1, + BUTTON_USER = 2, + NUM_BUTTONS +} key_typedef_enum; + +#define BUTTON_WAKEUP_BIT (1 << BUTTON_WAKEUP) +#define BUTTON_TAMPER_BIT (1 << BUTTON_TAMPER) +#define BUTTON_USER_BIT (1 << BUTTON_USER) + +/* Alternate function pin selections ****************************************/ + +#if defined(CONFIG_GD32F450ZK_EVAL_CONSOLE_BOARD) + +/* USART0: + * + * These configurations assume that you are using a standard RS-232 + * shield with the serial interface with RX on PA10 and TX on PA10: + * + * -------- --------------- + * GD32F450ZK-EVAL + * -- ----- --------- ----- + * RX USART0_RX PA10 + * TX USART0_TX PA9 + * -- ----- --------- ----- + */ + +# define GPIO_USART0_RX GPIO_USART0_RX_1 +# define GPIO_USART0_TX GPIO_USART0_TX_1 + +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_USART0_IFLOWCONTROL) +# define GPIO_USART0_RTS GPIO_USART0_RTS_1 +# endif +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_USART0_OFLOWCONTROL) +# define GPIO_USART0_CTS GPIO_USART0_CTS_1 +# endif +#endif + +#if CONFIG_GD32F4_USART0_TXDMA +# define DMA_CHANNEL_USART0_TX DMA_REQ_USART0_TX +#endif +#if CONFIG_GD32F4_USART0_RXDMA +# define DMA_CHANNEL_USART0_RX DMA_REQ_USART0_RX_1 +#endif + +#if defined(CONFIG_GD32F4_USART_RXDMA) || defined(CONFIG_GD32F4_USART_TXDMA) +# define USART_DMA_INTEN (DMA_CHXCTL_SDEIE | DMA_CHXCTL_TAEIE | DMA_CHXCTL_FTFIE) +#endif + +/* USART3: + * Use USART3 and the USB virtual COM port + */ + +#if defined(GD32F450ZK_EVAL_CONSOLE_VIRTUAL) +# define GPIO_USART3_RX GPIO_USART3_RX_3 +# define GPIO_USART3_TX GPIO_USART3_TX_3 +#endif + +/* SPI flash + * + * PG12 SPI5_MISO + * PG14 SPI5_MOSI + * PG13 SPI5_SCK + * + * PG9 SPI5_CS + * + */ + +#define GPIO_SPI5_CSPIN (GPIO_CFG_PORT_G | GPIO_PIN9_OUTPUT) + +#define GPIO_SPI5_MISO_PIN ((GPIO_SPI5_MISO & ~GPIO_CFG_SPEED_MASK) | GPIO_CFG_SPEED_25MHZ) +#define GPIO_SPI5_MOSI_PIN ((GPIO_SPI5_MOSI & ~GPIO_CFG_SPEED_MASK) | GPIO_CFG_SPEED_25MHZ) +#define GPIO_SPI5_SCK_PIN ((GPIO_SPI5_SCK & ~GPIO_CFG_SPEED_MASK) | GPIO_CFG_SPEED_25MHZ) + +#define GPIO_SPI5_IO2_PIN ((GPIO_SPI5_IO2 & ~GPIO_CFG_SPEED_MASK) | GPIO_CFG_SPEED_25MHZ) +#define GPIO_SPI5_IO3_PIN ((GPIO_SPI5_IO3 & ~GPIO_CFG_SPEED_MASK) | GPIO_CFG_SPEED_25MHZ) + +#ifdef CONFIG_GD32F4_SPI0 +# define GPIO_SPI0_CSPIN (GPIO_CFG_PORT_B | GPIO_PIN9_OUTPUT) +# define GPIO_SPI0_MISO_PIN ((GPIO_SPI0_MISO_1 & ~GPIO_CFG_SPEED_MASK) | GPIO_CFG_SPEED_25MHZ) +# define GPIO_SPI0_MOSI_PIN ((GPIO_SPI0_MOSI_1 & ~GPIO_CFG_SPEED_MASK) | GPIO_CFG_SPEED_25MHZ) +# define GPIO_SPI0_SCK_PIN ((GPIO_SPI0_SCK_1 & ~GPIO_CFG_SPEED_MASK) | GPIO_CFG_SPEED_25MHZ) +#endif + +#ifdef CONFIG_GD32F4_SPI0_DMA +# define DMA_CHANNEL_SPI0_TX DMA_REQ_SPI0_TX_1 +# define DMA_CHANNEL_SPI0_RX DMA_REQ_SPI0_RX_1 +#endif + +#ifdef CONFIG_GD32F4_SPI_DMA +# define SPI_DMA_INTEN (DMA_CHXCTL_SDEIE | DMA_CHXCTL_TAEIE | DMA_CHXCTL_FTFIE) +#endif + +/* The GD32 F4 connects to a DP83848 PHY using these pins: + * + * GD32F450Z Eval BOARD DP83848 + * GPIO SIGNAL PIN NAME + * -------- ------------ ------------- + * PB11 RMII_TX_EN TXEN + * PB12 RMII_TXD0 TXD0 + * PB13 RMII_TXD1 TXD1 + * PC4 RMII_RXD0 RXD_0/PHYAD1 + * PC5 RMII_RXD1 RXD_1/PHYAD2 + * PA7 RMII_CRS_DV RX_DV/MII_MODE + * PC1 RMII_MDC MDC + * PA2 RMII_MDIO MDIO + * NRST NRST RESET_N + * PA1 RMII_REF_CLK X1 + * PB15 RMII_INT PWR_DOWN/INT + * + * The PHY address is 1. + */ + +#define GPIO_ENET_RMII_TX_EN GPIO_ENET_RMII_TX_EN_1 +#define GPIO_ENET_RMII_TXD0 GPIO_ENET_RMII_TXD0_1 +#define GPIO_ENET_RMII_TXD1 GPIO_ENET_RMII_TXD1_1 + +#ifdef CONFIG_GD32F4_ENET_PTP + /* Enable pulse-per-second (PPS) output signal */ + +# define GPIO_ENET_PPS_OUT GPIO_ENET_PPS_OUT_1 +#endif + +#endif /* __BOARDS_ARM_GD32F450ZK_EVAL_INCLUDE_BOARD_H */ diff --git a/boards/arm/gd32f4/gd32f450zk-eval/scripts/Make.defs b/boards/arm/gd32f4/gd32f450zk-eval/scripts/Make.defs new file mode 100644 index 0000000000..347dcfd2d0 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/scripts/Make.defs @@ -0,0 +1,41 @@ +############################################################################ +# boards/arm/gd32f4/gd32f450zk-eval/scripts/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/.config +include $(TOPDIR)/tools/Config.mk +include $(TOPDIR)/arch/arm/src/armv7-m/Toolchain.defs + +LDSCRIPT = ld.script +ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) + +ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10 + +CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +AFLAGS := $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +EXEEXT = .elf diff --git a/boards/arm/gd32f4/gd32f450zk-eval/scripts/gnu-elf.ld b/boards/arm/gd32f4/gd32f450zk-eval/scripts/gnu-elf.ld new file mode 100644 index 0000000000..71448aa6cd --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/scripts/gnu-elf.ld @@ -0,0 +1,116 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/scripts/gnu-elf.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +SECTIONS +{ + .text 0x00000000 : + { + _stext = . ; + *(.text) + *(.text.*) + *(.gnu.warning) + *(.stub) + *(.glue_7) + *(.glue_7t) + *(.jcr) + + /* C++ support: The .init and .fini sections contain specific logic + * to manage static constructors and destructors. + */ + + *(.gnu.linkonce.t.*) + *(.init) /* Old ABI */ + *(.fini) /* Old ABI */ + _etext = . ; + } + + .rodata : + { + _srodata = . ; + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.gnu.linkonce.r*) + _erodata = . ; + } + + .data : + { + _sdata = . ; + *(.data) + *(.data1) + *(.data.*) + *(.gnu.linkonce.d*) + . = ALIGN(4); + _edata = . ; + } + + /* C++ support. For each global and static local C++ object, + * GCC creates a small subroutine to construct the object. Pointers + * to these routines (not the routines themselves) are stored as + * simple, linear arrays in the .ctors section of the object file. + * Similarly, pointers to global/static destructor routines are + * stored in .dtors. + */ + + .ctors : + { + _sctors = . ; + *(.ctors) /* Old ABI: Unallocated */ + *(.init_array) /* New ABI: Allocated */ + _edtors = . ; + } + + .dtors : + { + _sdtors = . ; + *(.dtors) /* Old ABI: Unallocated */ + *(.fini_array) /* New ABI: Allocated */ + _edtors = . ; + } + + .bss : + { + _sbss = . ; + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.b*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + } + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/gd32f4/gd32f450zk-eval/scripts/kernel-space.ld b/boards/arm/gd32f4/gd32f450zk-eval/scripts/kernel-space.ld new file mode 100644 index 0000000000..2ad4fa660e --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/scripts/kernel-space.ld @@ -0,0 +1,97 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/scripts/kernel-space.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* NOTE: This depends on the memory.ld script having been included prior to + * this script. + */ + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > kflash + + .init_section : { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > kflash + + .ARM.extab : { + *(.ARM.extab*) + } > kflash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > kflash + + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > ksram AT > kflash + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > ksram + + /* Stabs debugging sections */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/gd32f4/gd32f450zk-eval/scripts/ld.script b/boards/arm/gd32f4/gd32f450zk-eval/scripts/ld.script new file mode 100644 index 0000000000..d14ef1ec80 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/scripts/ld.script @@ -0,0 +1,130 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/scripts/ld.script + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* The GD32F450ZKT6 has 3072Kb of FLASH beginning at address 0x0800:0000 and + * 256Kb of SRAM. SRAM is split up into four blocks: + * + * 1) 112Kb of SRAM beginning at address 0x2000:0000 + * 2) 16Kb of SRAM beginning at address 0x2001:c000 + * 3) 64Kb of SRAM beginning at address 0x2002:0000 + * 4) 64Kb of TCMSRAM beginning at address 0x1000:0000 + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address + * range. + */ + +MEMORY +{ + flash (rx) : ORIGIN = 0x08000000, LENGTH = 3072K + sram (rwx) : ORIGIN = 0x20000000, LENGTH = 112K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : ALIGN(4) { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : ALIGN(4) { + *(.ARM.extab*) + } > flash + + .ARM.exidx : ALIGN(4) { + __exidx_start = ABSOLUTE(.); + *(.ARM.exidx*) + __exidx_end = ABSOLUTE(.); + } > flash + + .tdata : { + _stdata = ABSOLUTE(.); + *(.tdata .tdata.* .gnu.linkonce.td.*); + _etdata = ABSOLUTE(.); + } > flash + + .tbss : { + _stbss = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon); + _etbss = ABSOLUTE(.); + } > flash + + _eronly = ABSOLUTE(.); + + /* The RAM vector table (if present) should lie at the beginning of SRAM */ + + .ram_vectors : { + *(.ram_vectors) + } > sram + + .data : ALIGN(4) { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .bss : ALIGN(4) { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/gd32f4/gd32f450zk-eval/scripts/memory.ld b/boards/arm/gd32f4/gd32f450zk-eval/scripts/memory.ld new file mode 100644 index 0000000000..d540022dbc --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/scripts/memory.ld @@ -0,0 +1,85 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/scripts/memory.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* The GD32F450ZKT6 has 3072Kb of FLASH beginning at address 0x0800:0000 and + * 256Kb of SRAM. SRAM is split up into four blocks: + * + * 1) 112KB of SRAM beginning at address 0x2000:0000 + * 2) 16KB of SRAM beginning at address 0x2001:c000 + * 3) 64KB of SRAM beginning at address 0x2002:0000 + * 4) 64KB of TCMSRAM beginning at address 0x1000:0000 + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address range. + * + * For MPU support, the kernel-mode NuttX section is assumed to be 128Kb of + * FLASH and 4Kb of SRAM. That is an excessive amount for the kernel which + * should fit into 64KB and, of course, can be optimized as needed. Allowing the + * additional does permit addition debug instrumentation to be added to the + * kernel space without overflowing the partition. + * + * Alignment of the user space FLASH partition is also a critical factor: + * The user space FLASH partition will be spanned with a single region of + * size 2**n bytes. The alignment of the user-space region must be the same. + * As a consequence, as the user-space increases in size, the alignment + * requirement also increases. + * + * This alignment requirement means that the largest user space FLASH region + * you can have will be 512KB at it would have to be positioned at + * 0x08800000. If you change this address, don't forget to change the + * CONFIG_NUTTX_USERSPACE configuration setting to match and to modify + * the check in kernel/userspace.c. + * + * For the same reasons, the maximum size of the SRAM mapping is limited to + * 4KB. Both of these alignment limitations could be reduced by using + * multiple regions to map the FLASH/SDRAM range or perhaps with some + * clever use of subregions. + * + * A detailed memory map for the 112KB SRAM region is as follows: + * + * 0x20000 0000: Kernel .data region. Typical size: 0.1KB + * ------- ---- Kernel .bss region. Typical size: 1.8KB + * 0x20000 0800: Kernel IDLE thread stack (approximate). Size is + * determined by CONFIG_IDLETHREAD_STACKSIZE and + * adjustments for alignment. Typical is 1KB. + * ------- ---- Padded to 4KB + * 0x20000 1000: User .data region. Size is variable. + * ------- ---- User .bss region Size is variable. + * 0x20000 2000: Beginning of kernel heap. Size determined by + * CONFIG_MM_KERNEL_HEAPSIZE. + * ------- ---- Beginning of user heap. Can vary with other settings. + * 0x20001 c000: End+1 of CPU RAM + */ + +MEMORY +{ + /* 1024Kb FLASH */ + + kflash (rx) : ORIGIN = 0x08000000, LENGTH = 128K + uflash (rx) : ORIGIN = 0x08020000, LENGTH = 128K + xflash (rx) : ORIGIN = 0x08040000, LENGTH = 768K + + /* 112Kb of contiguous SRAM */ + + ksram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K + usram (rwx) : ORIGIN = 0x20001000, LENGTH = 4K + xsram (rwx) : ORIGIN = 0x20002000, LENGTH = 104K +} diff --git a/boards/arm/gd32f4/gd32f450zk-eval/scripts/user-space.ld b/boards/arm/gd32f4/gd32f450zk-eval/scripts/user-space.ld new file mode 100644 index 0000000000..06d62960e2 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/scripts/user-space.ld @@ -0,0 +1,111 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/scripts/user-space.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* NOTE: This depends on the memory.ld script having been included prior to + * this script. + */ + +/* Make sure that the critical memory management functions are in user-space. + * the user heap memory manager will reside in user-space but be usable both + * by kernel- and user-space code + */ + +EXTERN(umm_initialize) +EXTERN(umm_addregion) + +EXTERN(malloc) +EXTERN(realloc) +EXTERN(zalloc) +EXTERN(free) + +OUTPUT_ARCH(arm) +SECTIONS +{ + .userspace : { + *(.userspace) + } > uflash + + .text : { + _stext = ABSOLUTE(.); + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > uflash + + .init_section : { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > uflash + + .ARM.extab : { + *(.ARM.extab*) + } > uflash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > uflash + + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > usram AT > uflash + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > usram + + /* Stabs debugging sections */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/Makefile b/boards/arm/gd32f4/gd32f450zk-eval/src/Makefile new file mode 100644 index 0000000000..227344aa3a --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/Makefile @@ -0,0 +1,56 @@ +############################################################################ +# boards/arm/gd32f4/gd32f450zk-eval/src/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/Make.defs + +CSRCS = gd32f4xx_boot.c + +ifeq ($(CONFIG_BOARDCTL),y) +CSRCS += gd32f4xx_appinit.c +endif +# ifeq ($(CONFIG_BOARDCTL),y) +# CSRCS += gd32f4xx_appinit.c gd32f4xx_bringup.c +# else ifeq ($(CONFIG_BOARD_LATE_INITIALIZE),y) +# CSRCS += gd32f4xx_bringup.c +# endif + +ifeq ($(CONFIG_ARCH_LEDS),y) +CSRCS += gd32f4xx_autoleds.c +else +CSRCS += gd32f4xx_userleds.c +endif + +ifeq ($(CONFIG_DEV_GPIO),y) +CSRCS += gd32f4xx_gpio.c +endif + +ifeq ($(CONFIG_ARCH_BUTTONS),y) +CSRCS += gd32f4xx_buttons.c +endif + +ifeq ($(CONFIG_SPI),y) +CSRCS += gd32f4xx_spi.c +endif + +ifeq ($(CONFIG_MTD_GD25),y) +CSRCS += gd32f4xx_gd25.c +endif + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f450z_eval.h b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f450z_eval.h new file mode 100644 index 0000000000..8dc528ac51 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f450z_eval.h @@ -0,0 +1,190 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f450z_eval.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_GD32F4_GD32F450ZK_EVAL_SRC_GD32F450Z_EVAL_H +#define __BOARDS_ARM_GD32F4_GD32F450ZK_EVAL_SRC_GD32F450Z_EVAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* procfs File System */ + +#ifdef CONFIG_FS_PROCFS +# ifdef CONFIG_NSH_PROC_MOUNTPOINT +# define GD32_PROCFS_MOUNTPOINT CONFIG_NSH_PROC_MOUNTPOINT +# else +# define GD32_PROCFS_MOUNTPOINT "/proc" +# endif +#endif + +#ifdef CONFIG_FS_NXFFS +# ifndef CONFIG_GD32F4_NXFFS_MOUNTPT +# define CONFIG_GD32F4_NXFFS_MOUNTPT "/mnt/gd32nxffs" +# endif +#endif + +/* GD32F450ZK GPIO Pin Definitions ******************************************/ + +/* LED + * + * The GD32F450ZK-EVAL board has three LEDs, LED1, LED2 and LED3, that can be + * controlled by software. + * The following definitions assume the default Solder Bridges are installed. + */ + +#define GPIO_LED1 (GPIO_CFG_PORT_D | GPIO_CFG_OUTPUT_RESET | GPIO_PIN4_OUTPUT) +#define GPIO_LED2 (GPIO_CFG_PORT_D | GPIO_CFG_OUTPUT_RESET | GPIO_PIN5_OUTPUT) +#define GPIO_LED3 (GPIO_CFG_PORT_G | GPIO_CFG_OUTPUT_RESET | GPIO_PIN3_OUTPUT) + +#define LED1 GPIO_LED1 +#define LED2 GPIO_LED2 +#define LED3 GPIO_LED3 + +#define LED_DRIVER_PATH "/dev/userleds" + +/* BUTTONS + * + * The GD32F450Z Eval board has User, Tamper, and Wakeup key, the are + * connected to GPIO PB14, PC13 and PA0. + * A low value will be sensed when the button is depressed. + * + * Note: + * That the EXTI is included in the definition to enable + * an interrupt on this IO. + */ + +#define GPIO_BTN_USER (GPIO_CFG_PORT_B | GPIO_CFG_EXTI | GPIO_PIN14_INPUT) +#define GPIO_BTN_TAMPER (GPIO_CFG_PORT_C | GPIO_CFG_EXTI | GPIO_PIN13_INPUT) +#define GPIO_BTN_WAKEUP (GPIO_CFG_PORT_A | GPIO_CFG_EXTI | GPIO_PIN0_INPUT) + +/* SPI Flash ****************************************************************/ + +/* SPI FLASH (GD25Q40) + * + * PG12 SPI5_MISO + * PG14 SPI5_MOSI + * PG13 SPI5_SCK + * + * PG9 SPI5_CS + */ + +#define GPIO_SPI5_CS (GPIO_CFG_PORT_G | GPIO_PIN9_OUTPUT) +#define SPI_FLASH_CSNUM 5 + +#define HAVE_GD25 1 + +/* GPIO pins used by the GPIO Subsystem */ + +#define BOARD_NGPIOIN 1 /* Amount of GPIO Input pins */ +#define BOARD_NGPIOOUT 1 /* Amount of GPIO Output pins */ +#define BOARD_NGPIOINT 1 /* Amount of GPIO Input w/ Interruption pins */ + +#define GPIO_IN1 (GPIO_CFG_MODE_INPUT | GPIO_CFG_PUPD_NONE | GPIO_CFG_PORT_B | GPIO_CFG_PIN_0) +#define GPIO_OUT1 (GPIO_CFG_MODE_OUTPUT | GPIO_CFG_OUTPUT_SET | GPIO_CFG_SPEED_50MHZ | \ + GPIO_CFG_PORT_B | GPIO_CFG_PIN_1) +#define GPIO_INT1 (GPIO_CFG_MODE_INPUT | GPIO_CFG_PUPD_NONE | GPIO_CFG_PORT_B | GPIO_CFG_PIN_2) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Name: gd32_spidev_initialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the GD32F450Z + * Eval board. + * + ****************************************************************************/ + +#if defined(CONFIG_SPI) +void gd32_spidev_initialize(void); +#endif + +/**************************************************************************** + * Name: gd32_gd25_automount + * + * Description: + * Initialize, configure, and mount the GD25 SPI FLASH. The FLASH will + * be mounted at /dev/gd25. + * + ****************************************************************************/ + +#ifdef HAVE_GD25 +int gd32_gd25_automount(int minor); +#endif + +/**************************************************************************** + * Name: gd32_gpio_initialize + * + * Description: + * Initialize GPIO drivers for use with /apps/examples/gpio + * + ****************************************************************************/ + +#ifdef CONFIG_DEV_GPIO +int gd32_gpio_initialize(void); +#endif + +/**************************************************************************** + * Name: gd32_dma_alloc_init + * + * Description: + * Called to create a FAT DMA allocator + * + * Returned Value: + * 0 on success or -ENOMEM + * + ****************************************************************************/ + +void gd32_dma_alloc_init(void); + +#if defined (CONFIG_FAT_DMAMEMORY) +int gd32_dma_alloc_init(void); +#endif + +/**************************************************************************** + * Name: gd32_sdio_initialize + * + * Description: + * Called at application startup time to initialize the SCMMC + * functionality. + * + ****************************************************************************/ + +#ifdef CONFIG_MMCSD +int gd32_sdio_initialize(void); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_ARM_GD32F4_GD32F450ZK_EVAL_SRC_GD32F450Z_EVAL_H */ diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_appinit.c b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_appinit.c new file mode 100644 index 0000000000..0fcfda8ec2 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_appinit.c @@ -0,0 +1,200 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_appinit.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CONFIG_INPUT_BUTTONS +# include +#endif + +#ifdef CONFIG_GD32F4_ROMFS +#include "gd32f4xx_romfs.h" +#endif + +#include "gd32f450z_eval.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initialization logic and the + * matching application logic. The value could be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_app_initialize(uintptr_t arg) +{ + int ret; + static bool initialized = false; + + /* Have we already initialized? */ + + if (!initialized) + { +#ifdef CONFIG_FS_PROCFS + /* Mount the procfs file system */ + + ret = nx_mount(NULL, GD32_PROCFS_MOUNTPOINT, "procfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount procfs at %s: %d\n", + GD32_PROCFS_MOUNTPOINT, ret); + } +#endif + +#ifdef CONFIG_GD32F4_ROMFS + /* Mount the romfs partition */ + + ret = gd32_romfs_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount romfs at %s: %d\n", + CONFIG_GD32F4_ROMFS_MOUNTPOINT, ret); + } +#endif + +#ifdef CONFIG_FS_NXFFS + +# ifdef CONFIG_GD32F4_PROGMEM + + /* Create an instance of the GD32F4 FLASH program memory + * device driver + */ + + struct mtd_dev_s *mtd = progmem_initialize(); + if (!mtd) + { + syslog(LOG_ERR, "ERROR: progmem_initialize failed\n"); + } + + /* Initialize to provide NXFFS on the MTD interface */ + + ret = nxffs_initialize(mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: NXFFS initialization failed: %d\n", + ret); + } + + /* Mount the file system */ + + ret = nx_mount(NULL, CONFIG_GD32F4_NXFFS_MOUNTPT, "nxffs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the NXFFS volume: %d\n", + ret); + } + +# endif + +# ifdef CONFIG_MTD_GD25 + + ret = gd32_gd25_automount(0); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the NXFFS \ + volume on spi flash: %d\n", ret); + } + +# endif + +#endif + +#ifdef CONFIG_DEV_GPIO + /* Register the GPIO driver */ + + ret = gd32_gpio_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to initialize GPIO Driver: %d\n", ret); + return ret; + } +#endif + +#ifdef CONFIG_INPUT_BUTTONS +#ifdef CONFIG_INPUT_BUTTONS_LOWER + /* Register the BUTTON driver */ + + ret = btn_lower_initialize("/dev/buttons"); + if (ret != OK) + { + syslog(LOG_ERR, "ERROR: btn_lower_initialize() failed: %d\n", ret); + return ret; + } +#else + /* Enable BUTTON support for some other purpose */ + + board_button_initialize(); +#endif /* CONFIG_INPUT_BUTTONS_LOWER */ +#endif /* CONFIG_INPUT_BUTTONS */ + +#if !defined(CONFIG_ARCH_LEDS) && defined(CONFIG_USERLED_LOWER) + /* Register the LED driver */ + + ret = userled_lower_initialize(LED_DRIVER_PATH); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: userled_lower_initialize() failed: %d\n", + ret); + } +#endif + + /* Now we are initialized */ + + initialized = true; + } + + UNUSED(ret); + return OK; +} diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_autoleds.c b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_autoleds.c new file mode 100644 index 0000000000..da2869fd8a --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_autoleds.c @@ -0,0 +1,181 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_autoleds.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "gd32f4xx_gpio.h" +#include "gd32f450z_eval.h" +#ifdef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0])) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* LED index */ + +static const uint32_t g_led_map[BOARD_LEDS] = +{ + LED1, + LED2, + LED3 +}; + +static bool g_initialized; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Turn on selected led */ + +static void gd32_eval_led_on(led_typedef_enum led_num) +{ + gd32_gpio_write(g_led_map[led_num], true); +} + +/* Turn off selected led */ + +static void gd32_eval_led_off(led_typedef_enum led_num) +{ + gd32_gpio_write(g_led_map[led_num], false); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_autoled_initialize + ****************************************************************************/ + +void board_autoled_initialize(void) +{ + int i; + + /* Configure the LED GPIO for output. */ + + for (i = 0; i < ARRAYSIZE(g_led_map); i++) + { + gd32_gpio_config(g_led_map[i]); + } +} + +/**************************************************************************** + * Name: board_autoled_on + ****************************************************************************/ + +void board_autoled_on(int led) +{ + switch (led) + { + default: + break; + + case LED_HEAPALLOCATE: + gd32_eval_led_on(BOARD_LED1); + break; + + case LED_IRQSENABLED: + gd32_eval_led_on(BOARD_LED2); + break; + + case LED_STACKCREATED: + gd32_eval_led_on(BOARD_LED3); + g_initialized = true; + break; + + case LED_INIRQ: + gd32_eval_led_on(BOARD_LED1); + gd32_eval_led_on(BOARD_LED2); + break; + + case LED_SIGNAL: + gd32_eval_led_on(BOARD_LED1); + gd32_eval_led_on(BOARD_LED3); + break; + + case LED_ASSERTION: + gd32_eval_led_on(BOARD_LED2); + gd32_eval_led_on(BOARD_LED3); + break; + + case LED_PANIC: + gd32_eval_led_on(BOARD_LED1); + break; + + case LED_IDLE : /* IDLE */ + gd32_eval_led_on(BOARD_LED2); + break; + } +} + +/**************************************************************************** + * Name: board_autoled_off + ****************************************************************************/ + +void board_autoled_off(int led) +{ + switch (led) + { + default: + break; + + case LED_SIGNAL: + gd32_eval_led_off(BOARD_LED1); + gd32_eval_led_off(BOARD_LED3); + break; + + case LED_INIRQ: + gd32_eval_led_off(BOARD_LED1); + gd32_eval_led_off(BOARD_LED2); + break; + + case LED_ASSERTION: + gd32_eval_led_off(BOARD_LED2); + gd32_eval_led_off(BOARD_LED3); + break; + + case LED_PANIC: + gd32_eval_led_off(BOARD_LED1); + break; + + case LED_IDLE : /* IDLE */ + gd32_eval_led_off(BOARD_LED2); + break; + } +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_boot.c b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_boot.c new file mode 100644 index 0000000000..1a36b5aaa1 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_boot.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_boot.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "gd32f450z_eval.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_boardinitialize + * + * Description: + * All GD32F4xx architectures must provide the following entry point. + * This entry point is called early in the initialization + * after all memory has been configured and mapped but + * before any devices have been initialized. + * + ****************************************************************************/ + +void gd32_boardinitialize(void) +{ +#ifdef CONFIG_ARCH_LEDS + /* Configure on-board LEDs if LED support has been selected. */ + + board_autoled_initialize(); +#endif + +#if defined(CONFIG_SPI) + /* Configure SPI chip selects */ + + gd32_spidev_initialize(); +#endif +} + +/**************************************************************************** + * Name: board_late_initialize + * + * Description: + * If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional + * initialization call will be performed in the boot-up sequence to a + * function called board_late_initialize(). board_late_initialize() + * will be called immediately after up_initialize() is called and + * just before the initial application is started. This additional + * initialization phase may be used, for example, to initialize + * board-specific device drivers. + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_LATE_INITIALIZE +void board_late_initialize(void) +{ +#if defined(CONFIG_NSH_LIBRARY) && !defined(CONFIG_BOARDCTL) + /* Perform NSH initialization here instead of from the NSH. This + * alternative NSH initialization is necessary when NSH is ran in + * user-space but the initialization function must run in kernel space. + */ + + board_app_initialize(0); +#endif +} +#endif diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_bringup.c b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_bringup.c new file mode 100644 index 0000000000..22cc139852 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_bringup.c @@ -0,0 +1,184 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_bringup.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gd32f450z_eval.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_bringup + * + * Description: + * Perform architecture-specific initialization + * + * CONFIG_BOARD_LATE_INITIALIZE=y : + * Called from board_late_initialize(). + * + * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_BOARDCTL=y : + * Called from the NSH library via boardctl() + * + ****************************************************************************/ + +int gd32_bringup(void) +{ +#ifdef CONFIG_RAMMTD + uint8_t *ramstart; +#endif + + int ret = OK; + +#ifdef CONFIG_FS_PROCFS + /* Mount the procfs file system */ + + ret = nx_mount(NULL, GD32_PROCFS_MOUNTPOINT, "procfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount procfs at %s: %d\n", + GD32_PROCFS_MOUNTPOINT, ret); + } +#endif + +#ifdef CONFIG_RAMMTD + /* Create a RAM MTD device if configured */ + + ramstart = (uint8_t *)kmm_malloc(64 * 1024); + if (ramstart == NULL) + { + syslog(LOG_ERR, "ERROR: Allocation for RAM MTD failed\n"); + } + else + { + /* Initialized the RAM MTD */ + + struct mtd_dev_s *mtd = rammtd_initialize(ramstart, 64 * 1024); + if (mtd == NULL) + { + syslog(LOG_ERR, "ERROR: rammtd_initialize failed\n"); + kmm_free(ramstart); + } + else + { + /* Erase the RAM MTD */ + + ret = mtd->ioctl(mtd, MTDIOC_BULKERASE, 0); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: IOCTL MTDIOC_BULKERASE failed\n"); + } + +#if defined(CONFIG_MTD_SMART) && defined(CONFIG_FS_SMARTFS) + /* Initialize a SMART Flash block device and bind it to the MTD + * device. + */ + + smart_initialize(0, mtd, NULL); + +#elif defined(CONFIG_FS_SPIFFS) + /* Register the MTD driver so that it can be accessed from the + * VFS. + */ + + ret = register_mtddriver("/dev/rammtd", mtd, 0755, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD driver: %d\n", + ret); + } + + /* Mount the SPIFFS file system */ + + ret = nx_mount("/dev/rammtd", "/mnt/spiffs", "spiffs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to mount SPIFFS at /mnt/spiffs: %d\n", + ret); + } + +#elif defined(CONFIG_FS_LITTLEFS) + /* Register the MTD driver so that it can be accessed from the + * VFS. + */ + + ret = register_mtddriver("/dev/rammtd", mtd, 0755, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD driver: %d\n", + ret); + } + + /* Mount the LittleFS file system */ + + ret = nx_mount("/dev/rammtd", "/mnt/lfs", "littlefs", 0, + "forceformat"); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to mount LittleFS at /mnt/lfs: %d\n", + ret); + } + +#elif defined(CONFIG_FS_NXFFS) + /* Initialize to provide NXFFS on the MTD interface */ + + ret = nxffs_initialize(mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: NXFFS initialization failed: %d\n", + ret); + } +#endif + } + } +#endif + +#if defined(CONFIG_INPUT_BUTTONS_LOWER) + ret = btn_lower_initialize("/dev/buttons"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: btn_lower_initialize() failed: %d\n", ret); + } +#endif + + return ret; +} diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_buttons.c b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_buttons.c new file mode 100644 index 0000000000..1e53ed311b --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_buttons.c @@ -0,0 +1,188 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_buttons.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include + +#include "gd32f4xx.h" +#include "gd32f450z_eval.h" + +#ifdef CONFIG_ARCH_BUTTONS + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint32_t g_button_boards[NUM_BUTTONS] = +{ + GPIO_BTN_USER, GPIO_BTN_TAMPER, GPIO_BTN_WAKEUP +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_button_initialize + * + * Description: + * board_button_initialize() must be called to initialize button resources. + * After that, board_buttons() may be called to collect the current state + * of all buttons or board_button_irq() may be called to register button + * interrupt handlers. + * + ****************************************************************************/ + +uint32_t board_button_initialize(void) +{ + int i; + + /* Configure each button */ + + for (i = 0; i < NUM_BUTTONS; i++) + { + gd32_gpio_config(g_button_boards[i]); + } + + return NUM_BUTTONS; +} + +/**************************************************************************** + * Name: board_buttons + * After board_button_initialize() has been called, board_buttons() may be + * called to collect the state of all buttons. board_buttons() returns an + * 32-bit bit set with each bit associated with a button. See the BUTTON* + * definitions above for the meaning of each bit in the returned value. + * + ****************************************************************************/ + +uint32_t board_buttons(void) +{ + uint32_t ret; + int i; + + /* Check each button */ + + for (i = 0, ret = 0; i < NUM_BUTTONS; i++) + { + /* The low value is sensed when the button is pressed */ + + if (!gd32_gpio_read(g_button_boards[i])) + { + ret |= (1 << i); + } + } + + return ret; +} + +/**************************************************************************** + * Button support. + * + * Description: + * board_button_initialize() must be called to initialize button resources. + * After that, board_buttons() may be called to collect the current + * state of all buttons or board_button_irq() may be called to register + * button interrupt handlers. + * + * After board_button_initialize() has been called, board_buttons() + * may be called to collect the state of all buttons. board_buttons() + * returns an 32-bit bit set with each bit associated with a button. + * See the BUTTON_*_BIT definitions in board.h for the meaning of each + * bit. + * + * board_button_irq() may be called to register an interrupt handler that + * will be called when a button is depressed or released. The ID value + * is a button enumeration value that uniquely identifies a button + * resource. See the BUTTON_* definitions in board.h for the meaning of + * enumeration value. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQBUTTONS +int board_button_irq(int id, xcpt_t irqhandler, void *arg) +{ + if (id >= 0 && id < NUM_BUTTONS) + { + uint8_t gpio_irq; + uint8_t gpio_irqnum; + irqstate_t flags; + int ret; + + /* Disable interrupts until we are done. This guarantees that the + * following operations are atomic. + */ + + flags = enter_critical_section(); + + /* Get gpio irq numbers */ + + ret = gd32_gpio_exti_irqnum_get(g_button_boards[id], &gpio_irqnum); + + if (ret < 0) + { + return ret; + } + + /* Are we attaching or detaching? */ + + if (irqhandler != NULL) + { + ret = gd32_exti_gpioirq_init(g_button_boards[id], EXTI_INTERRUPT, + EXTI_TRIG_RISING, &gpio_irq); + + if (ret < 0) + { + return ret; + } + + /* Attach and enable the interrupt */ + + gd32_exti_gpio_irq_attach(gpio_irq, irqhandler, arg); + up_enable_irq(gpio_irqnum); + } + else + { + /* Disable and detach the interrupt */ + + up_disable_irq(gpio_irqnum); + irq_detach(gpio_irqnum); + } + + leave_critical_section(flags); + } + + /* Return the old button handler (so that it can be restored) */ + + return OK; +} +#endif +#endif /* CONFIG_ARCH_BUTTONS */ diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_gd25.c b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_gd25.c new file mode 100644 index 0000000000..a27ce6dcf2 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_gd25.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_gd25.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "gd32f4xx.h" +#include "gd32f450z_eval.h" + +#ifdef HAVE_GD25 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_gd25_automount + * + * Description: + * Initialize, configure, and mount the GD25 SPI FLASH. The FLASH will + * be mounted at /dev/gd25. + * + ****************************************************************************/ + +int gd32_gd25_automount(int minor) +{ + struct spi_dev_s *spi; + struct mtd_dev_s *mtd; + static bool initialized = false; + int ret; + + /* Have we already initialized? */ + + if (!initialized) + { + /* No.. Get the SPI port driver */ + + spi = gd32_spibus_initialize(SPI_FLASH_CSNUM); + if (!spi) + { + syslog(LOG_ERR, "ERROR: Failed to initialize SPI port %d\n", + SPI_FLASH_CSNUM); + return -ENODEV; + } + + /* Now bind the SPI interface to the GD25 SPI FLASH driver */ + + mtd = gd25_initialize(spi, 0); + if (!mtd) + { + syslog(LOG_ERR, "ERROR: Failed to bind SPI port to the \ + GD25 FLASH driver\n"); + return -ENODEV; + } + +#if defined(CONFIG_GD32F4_GD25_FTL) + /* And finally, use the FTL layer to wrap the MTD driver as a block + * driver at /dev/mtdblockN, where N=minor device number. + */ + + ret = ftl_initialize(minor, mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize the FTL layer: %d\n", + ret); + return ret; + } + +#elif defined(CONFIG_GD32F4_GD25_NXFFS) + /* Initialize to provide NXFFS on the MTD interface */ + + ret = nxffs_initialize(mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: NXFFS initialization failed: %d\n", ret); + return ret; + } + + /* Mount the file system at /mnt/gd25 */ + + ret = nx_mount(NULL, "/mnt/gd25", "nxffs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the NXFFS volume: %d\n", + ret); + return ret; + } + + syslog(LOG_INFO, "INFO: NXFFS volume /mnt/gd25 mount \ + spi flash success: %d\n", ret); +#endif + + /* Now we are initialized */ + + initialized = true; + } + + UNUSED(ret); + + return OK; +} + +#endif /* HAVE_GD25 */ diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_gpio.c b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_gpio.c new file mode 100644 index 0000000000..83cc58d867 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_gpio.c @@ -0,0 +1,395 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_gpio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include "chip.h" + +#include "gd32f4xx.h" +#include "gd32f450z_eval.h" + +#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct gd32gpio_dev_s +{ + struct gpio_dev_s gpio; + uint8_t id; +}; + +struct gd32gpint_dev_s +{ + struct gd32gpio_dev_s gd32gpio; + pin_interrupt_t callback; +}; + +irqstate_t flags; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int gpio_setpintype(struct gpio_dev_s *dev, + enum gpio_pintype_e gp_pintype); + +#if BOARD_NGPIOIN > 0 +static int gpin_read(struct gpio_dev_s *dev, bool *value); +#endif + +#if BOARD_NGPIOOUT > 0 +static int gpout_read(struct gpio_dev_s *dev, bool *value); +static int gpout_write(struct gpio_dev_s *dev, bool value); +#endif + +#if BOARD_NGPIOINT > 0 +static int gpint_read(struct gpio_dev_s *dev, bool *value); +static int gpint_attach(struct gpio_dev_s *dev, + pin_interrupt_t callback); +static int gpint_enable(struct gpio_dev_s *dev, bool enable); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + + #if BOARD_NGPIOIN > 0 +static const struct gpio_operations_s gpin_ops = +{ + .go_read = gpin_read, + .go_write = NULL, + .go_attach = NULL, + .go_enable = NULL, + .go_setpintype = gpio_setpintype, +}; + +/* This array maps the GPIO pins used as INPUT */ + +static const uint32_t g_gpioinputs[BOARD_NGPIOIN] = +{ + GPIO_IN1, +}; + +static struct gd32gpio_dev_s g_gpin[BOARD_NGPIOIN]; +#endif + +#if BOARD_NGPIOOUT > 0 + +static const struct gpio_operations_s gpout_ops = +{ + .go_read = gpout_read, + .go_write = gpout_write, + .go_attach = NULL, + .go_enable = NULL, + .go_setpintype = gpio_setpintype, +}; + +/* This array maps the GPIO pins used as OUTPUT */ + +static const uint32_t g_gpiooutputs[BOARD_NGPIOOUT] = +{ + GPIO_OUT1, +}; + +static struct gd32gpio_dev_s g_gpout[BOARD_NGPIOOUT]; +#endif + +#if BOARD_NGPIOINT > 0 + +static const struct gpio_operations_s gpint_ops = +{ + .go_read = gpint_read, + .go_write = NULL, + .go_attach = gpint_attach, + .go_enable = gpint_enable, + .go_setpintype = gpio_setpintype, +}; + +/* This array maps the GPIO pins used as INTERRUPT INPUTS */ + +static const uint32_t g_gpiointinputs[BOARD_NGPIOINT] = +{ + GPIO_INT1, +}; + +static struct gd32gpint_dev_s g_gpint[BOARD_NGPIOINT]; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gpio_setpintype + * + * Description: + * set gpio pintype. + * + ****************************************************************************/ + +static int gpio_setpintype(struct gpio_dev_s *dev, + enum gpio_pintype_e gpio_pintype) +{ + struct gd32gpint_dev_s *gd32gpint = (struct gd32gpint_dev_s *)dev; + + UNUSED(gd32gpint); + UNUSED(gpio_pintype); + + gpioinfo("setpintype is not supported. \n"); + + return 0; +} + +#if BOARD_NGPIOIN > 0 +static int gpin_read(struct gpio_dev_s *dev, bool *value) +{ + struct gd32gpio_dev_s *gd32gpio = (struct gd32gpio_dev_s *)dev; + + DEBUGASSERT(gd32gpio != NULL && value != NULL); + DEBUGASSERT(gd32gpio->id < BOARD_NGPIOIN); + gpioinfo("Reading...\n"); + + *value = gd32_gpio_read(g_gpioinputs[gd32gpio->id]); + return OK; +} +#endif + +#if BOARD_NGPIOOUT > 0 +static int gpout_read(struct gpio_dev_s *dev, bool *value) +{ + struct gd32gpio_dev_s *gd32gpio = (struct gd32gpio_dev_s *)dev; + + DEBUGASSERT(gd32gpio != NULL && value != NULL); + DEBUGASSERT(gd32gpio->id < BOARD_NGPIOOUT); + gpioinfo("Reading...\n"); + + *value = gd32_gpio_read(g_gpiooutputs[gd32gpio->id]); + return OK; +} + +static int gpout_write(struct gpio_dev_s *dev, bool value) +{ + struct gd32gpio_dev_s *gd32gpio = (struct gd32gpio_dev_s *)dev; + + DEBUGASSERT(gd32gpio != NULL); + DEBUGASSERT(gd32gpio->id < BOARD_NGPIOOUT); + gpioinfo("Writing %d\n", (int)value); + + gd32_gpio_write(g_gpiooutputs[gd32gpio->id], value); + return OK; +} +#endif + +#if BOARD_NGPIOINT > 0 + +static int gd32gpio_interrupt(int irq, void *context, void *arg) +{ + struct gd32gpint_dev_s *gd32gpint = (struct gd32gpint_dev_s *)arg; + + DEBUGASSERT(gd32gpint != NULL && gd32gpint->callback != NULL); + gpioinfo("Interrupt! callback=%p\n", gd32gpint->callback); + + gd32gpint->callback(&gd32gpint->gd32gpio.gpio, gd32gpint->gd32gpio.id); + return OK; +} + +static int gpint_read(struct gpio_dev_s *dev, bool *value) +{ + struct gd32gpint_dev_s *gd32gpint = (struct gd32gpint_dev_s *)dev; + + DEBUGASSERT(gd32gpint != NULL && value != NULL); + DEBUGASSERT(gd32gpint->gd32gpio.id < BOARD_NGPIOINT); + gpioinfo("Reading int pin...\n"); + + *value = gd32_gpio_read(g_gpiointinputs[gd32gpint->gd32gpio.id]); + return OK; +} + +static int gpint_attach(struct gpio_dev_s *dev, pin_interrupt_t callback) +{ + struct gd32gpint_dev_s *gd32gpint = (struct gd32gpint_dev_s *)dev; + int ret; + uint8_t gpio_irq; + uint8_t gpio_irqnum; + + gpioinfo("Attaching the callback\n"); + + flags = enter_critical_section(); + + /* Make sure the interrupt is disabled */ + + ret = gd32_exti_gpioirq_init(g_gpiointinputs[gd32gpint->gd32gpio.id], + EXTI_INTERRUPT, EXTI_TRIG_RISING, &gpio_irq); + + if (ret < 0) + { + return ret; + } + + gd32_gpio_exti_irqnum_get(g_gpiointinputs[gd32gpint->gd32gpio.id], + &gpio_irqnum); + + /* Attach and disable the interrupt */ + + gd32_exti_gpio_irq_attach(gpio_irq, gd32gpio_interrupt, + &g_gpint[gd32gpint->gd32gpio.id]); + + /* Disable and the interrupt */ + + up_disable_irq(gpio_irqnum); + + leave_critical_section(flags); + gpioinfo("Attach %p\n", callback); + gd32gpint->callback = callback; + return OK; +} + +static int gpint_enable(struct gpio_dev_s *dev, bool enable) +{ + struct gd32gpint_dev_s *gd32gpint = (struct gd32gpint_dev_s *)dev; + int ret; + uint8_t gpio_irqnum; + + flags = enter_critical_section(); + + /* Get gpio irq numbers */ + + ret = gd32_gpio_exti_irqnum_get(g_gpiointinputs[gd32gpint->gd32gpio.id], + &gpio_irqnum); + if (ret < 0) + { + return ret; + } + + if (enable) + { + if (gd32gpint->callback != NULL) + { + gpioinfo("Enabling the interrupt\n"); + + /* Enable the interrupt */ + + up_disable_irq(gpio_irqnum); + } + } + else + { + up_disable_irq(gpio_irqnum); + gpioinfo("Disable the interrupt\n"); + } + + leave_critical_section(flags); + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_gpio_initialize + * + * Description: + * Initialize GPIO drivers for use with /apps/examples/gpio + * + ****************************************************************************/ + +int gd32_gpio_initialize(void) +{ + int pincount = 0; + int i; + +#if BOARD_NGPIOIN > 0 + for (i = 0; i < BOARD_NGPIOIN; i++) + { + /* Setup and register the GPIO pin */ + + g_gpin[i].gpio.gp_pintype = GPIO_INPUT_PIN; + g_gpin[i].gpio.gp_ops = &gpin_ops; + g_gpin[i].id = i; + + gpio_pin_register(&g_gpin[i].gpio, pincount); + + /* Configure the pin that will be used as input */ + + gd32_gpio_config(g_gpioinputs[i]); + + pincount++; + } +#endif + +#if BOARD_NGPIOOUT > 0 + for (i = 0; i < BOARD_NGPIOOUT; i++) + { + /* Setup and register the GPIO pin */ + + g_gpout[i].gpio.gp_pintype = GPIO_OUTPUT_PIN; + g_gpout[i].gpio.gp_ops = &gpout_ops; + g_gpout[i].id = i; + + gpio_pin_register(&g_gpout[i].gpio, pincount); + + /* Configure the pin that will be used as output */ + + gd32_gpio_write(g_gpiooutputs[i], 0); + gd32_gpio_config(g_gpiooutputs[i]); + + pincount++; + } +#endif + +#if BOARD_NGPIOINT > 0 + for (i = 0; i < BOARD_NGPIOINT; i++) + { + /* Setup and register the GPIO pin */ + + g_gpint[i].gd32gpio.gpio.gp_pintype = GPIO_INTERRUPT_PIN; + g_gpint[i].gd32gpio.gpio.gp_ops = &gpint_ops; + g_gpint[i].gd32gpio.id = i; + (void)gpio_pin_register(&g_gpint[i].gd32gpio.gpio, pincount); + + /* Configure the pin that will be used as interrupt input */ + + gd32_gpio_config(g_gpiointinputs[i]); + + pincount++; + } +#endif + + return 0; +} +#endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */ diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_romfs.c b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_romfs.c new file mode 100644 index 0000000000..f035d3c7c5 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_romfs.c @@ -0,0 +1,141 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_romfs.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include "gd32f4xx_romfs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_GD32F4_ROMFS +# error "CONFIG_GD32F4_ROMFS must be defined" +#else + +#ifndef CONFIG_GD32F4_ROMFS_IMAGEFILE +# error "CONFIG_GD32F4_ROMFS_IMAGEFILE must be defined" +#endif + +#ifndef CONFIG_GD32F4_ROMFS_DEV_MINOR +# error "CONFIG_GD32F4_ROMFS_DEV_MINOR must be defined" +#endif + +#ifndef CONFIG_GD32F4_ROMFS_MOUNTPOINT +# error "CONFIG_GD32F4_ROMFS_MOUNTPOINT must be defined" +#endif + +#define NSECTORS(size) (((size) + ROMFS_SECTOR_SIZE - 1)/ROMFS_SECTOR_SIZE) + +#define STR2(m) #m +#define STR(m) STR2(m) + +#define MKMOUNT_DEVNAME(m) "/dev/ram" STR(m) +#define MOUNT_DEVNAME MKMOUNT_DEVNAME(CONFIG_GD32F4_ROMFS_DEV_MINOR) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +__asm__ ( + " .section .rodata \n" + " .balign 16 \n" + " .globl romfs_data_begin \n" + "romfs_data_begin: \n" + " .incbin " STR(CONFIG_GD32F4_ROMFS_IMAGEFILE)"\n" + " .balign " STR(ROMFS_SECTOR_SIZE) "\n" + " .globl romfs_data_end \n" + "romfs_data_end: \n" + " .globl romfs_data_size \n" + "romfs_data_size: \n" + " .word romfs_data_end - romfs_data_begin \n" + ); + +extern const char romfs_data_begin; +extern const char romfs_data_end; +extern const int romfs_data_size; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_romfs_initialize + * + * Description: + * Registers the aboveincluded binary file as block device. + * Then mounts the block device as ROMFS filesystems. + * + * Returned Value: + * Zero (OK) on success, a negated errno value on error. + * + * Assumptions/Limitations: + * Memory addresses [&romfs_data_begin .. &romfs_data_begin) should contain + * ROMFS volume data, as included in the assembly snippet above. + * + ****************************************************************************/ + +int gd32_romfs_initialize(void) +{ + uintptr_t romfs_data_len; + int ret; + + /* Create a ROM disk for the /etc filesystem */ + + romfs_data_len = (uintptr_t)&romfs_data_end - (uintptr_t)&romfs_data_begin; + + ret = romdisk_register(CONFIG_GD32F4_ROMFS_DEV_MINOR, &romfs_data_begin, + NSECTORS(romfs_data_len), ROMFS_SECTOR_SIZE); + if (ret < 0) + { + ferr("ERROR: romdisk_register failed: %d\n", -ret); + return ret; + } + + /* Mount the file system */ + + finfo("Mounting ROMFS filesystem at target=%s with source=%s\n", + CONFIG_GD32F4_ROMFS_MOUNTPOINT, MOUNT_DEVNAME); + + ret = nx_mount(MOUNT_DEVNAME, CONFIG_GD32F4_ROMFS_MOUNTPOINT, + "romfs", MS_RDONLY, NULL); + if (ret < 0) + { + ferr("ERROR: nx_mount(%s,%s,romfs) failed: %d\n", + MOUNT_DEVNAME, CONFIG_GD32F4_ROMFS_MOUNTPOINT, ret); + return ret; + } + + return OK; +} + +#endif /* CONFIG_GD32F4_ROMFS */ diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_romfs.h b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_romfs.h new file mode 100644 index 0000000000..93277325a1 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_romfs.h @@ -0,0 +1,62 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_romfs.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_GD32F4_GD32F450ZK_EVAL_SRC_GD32F4XX_ROMFS_H +#define __BOARDS_ARM_GD32F4_GD32F450ZK_EVAL_SRC_GD32F4XX_ROMFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_GD32F4_ROMFS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ROMFS_SECTOR_SIZE 64 + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_romfs_initialize + * + * Description: + * Registers built-in ROMFS image as block device and mounts it. + * + * Returned Value: + * Zero (OK) on success, a negated errno value on error. + * + * Assumptions/Limitations: + * Memory addresses [&romfs_data_begin .. &romfs_data_begin) should contain + * ROMFS volume data, as included in the assembly snippet in + * gd32f4xx_romfs.c. + * + ****************************************************************************/ + +int gd32_romfs_initialize(void); + +#endif /* CONFIG_GD32F4_ROMFS */ + +#endif /* __BOARDS_ARM_GD32F4_GD32F450ZK_EVAL_SRC_GD32F4XX_ROMFS_H */ diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_spi.c b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_spi.c new file mode 100644 index 0000000000..fb1c6e1876 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_spi.c @@ -0,0 +1,283 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_spi.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "gd32f4xx.h" +#include "gd32f450z_eval.h" + +#if defined(CONFIG_SPI) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gd32_spidev_initialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the GD32F450Z-EVAL. + * + ****************************************************************************/ + +void weak_function gd32_spidev_initialize(void) +{ +#ifdef CONFIG_GD32F4_SPI0 + /* Configure SPI0 CS GPIO for output */ + + gd32_gpio_config(GPIO_SPI0_CSPIN); + gd32_gpio_write(GPIO_SPI0_CSPIN, 1); +#endif +#ifdef CONFIG_GD32F4_SPI1 + /* Configure SPI1 CS GPIO for output */ + + gd32_gpio_config(GPIO_SPI1_CSPIN); + gd32_gpio_write(GPIO_SPI1_CSPIN, 1); +#endif +#ifdef CONFIG_GD32F4_SPI2 + /* Configure SPI2 CS GPIO for output */ + + gd32_gpio_config(GPIO_SPI2_CSPIN); + gd32_gpio_write(GPIO_SPI2_CSPIN, 1); +#endif +#ifdef CONFIG_GD32F4_SPI3 + /* Configure SPI3 CS GPIO for output */ + + gd32_gpio_config(GPIO_SPI3_CSPIN); + gd32_gpio_write(GPIO_SPI3_CSPIN, 1); +#endif +#ifdef CONFIG_GD32F4_SPI4 + /* Configure SPI4 CS GPIO for output */ + + gd32_gpio_config(GPIO_SPI4_CSPIN); + gd32_gpio_write(GPIO_SPI4_CSPIN, 1); +#endif +#ifdef CONFIG_GD32F4_SPI5 + /* Configure SPI5 CS GPIO for output */ + + gd32_gpio_config(GPIO_SPI5_CSPIN); + gd32_gpio_write(GPIO_SPI5_CSPIN, 1); +#endif +} + +/**************************************************************************** + * Name: gd32_spi[n]select and gd32_spi[n]status + * + * Description: + * The external functions, gd32_spi0-5select and gd32_spi0-5 status + * must be provided by board-specific logic. They are implementations of the + * select and status methods of the SPI interface defined by struct spi_ops_s + * (see include/nuttx/spi/spi.h). + * All other methods (including gd32_spibus_initialize()) are provided by + * common GD32F4 logic. To use this common SPI logic on your board: + * + * 1. Provide logic in gd32_boardinitialize() to configure SPI chip select + * pins. + * 2. Provide gd32_spi[n]select() and gd32_spi[n]status() functions + * in your board-specific logic. These functions will perform chip + * selection and status operations using GPIOs in the way your board is + * configured. + * 3. Add a calls to gd32_spibus_initialize() in your low level + * application initialization logic + * 4. The handle returned by gd32_spibus_initialize() may then be used to + * bind the SPI driver to higher level logic (e.g., calling + * mmcsd_spislotinitialize(), for example, will bind the SPI driver to + * the SPI MMC/SD driver). + * + ****************************************************************************/ + +#ifdef CONFIG_GD32F4_SPI0 +void gd32_spi0select(struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("devid: %d CS: %s\n", (int)devid, + selected ? "assert" : "de-assert"); + + gd32_gpio_write(GPIO_SPI0_CSPIN, !selected); +} + +uint8_t gd32_spi0status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_GD32F4_SPI1 +void gd32_spi1select(struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("devid: %d CS: %s\n", (int)devid, + selected ? "assert" : "de-assert"); + + gd32_gpio_write(GPIO_SPI1_CSPIN, !selected); +} + +uint8_t gd32_spi1status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_GD32F4_SPI2 +void gd32_spi2select(struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("devid: %d CS: %s\n", (int)devid, + selected ? "assert" : "de-assert"); + + gd32_gpio_write(GPIO_SPI2_CSPIN, !selected); +} + +uint8_t gd32_spi2status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_GD32F4_SPI3 +void gd32_spi3select(struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("devid: %d CS: %s\n", (int)devid, + selected ? "assert" : "de-assert"); + + gd32_gpio_write(GPIO_SPI3_CSPIN, !selected); +} + +uint8_t gd32_spi3status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_GD32F4_SPI4 +void gd32_spi4select(struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("devid: %d CS: %s\n", (int)devid, + selected ? "assert" : "de-assert"); + + gd32_gpio_write(GPIO_SPI4_CSPIN, !selected); +} + +uint8_t gd32_spi4status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_GD32F4_SPI5 +void gd32_spi5select(struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("devid: %d CS: %s\n", (int)devid, + selected ? "assert" : "de-assert"); + + gd32_gpio_write(GPIO_SPI5_CSPIN, !selected); +} + +uint8_t gd32_spi5status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +/**************************************************************************** + * Name: gd32_spi[n]cmddata + * + * Description: + * Set or clear the SH1101A A0 or SD1306 D/C n bit to select data (true) + * or command (false). This function must be provided by platform-specific + * logic. This is an implementation of the cmddata method of the SPI + * interface defined by struct spi_ops_s (see include/nuttx/spi/spi.h). + * + * Input Parameters: + * + * spi - SPI device that controls the bus the device that requires the CMD/ + * DATA selection. + * devid - If there are multiple devices on the bus, this selects which one + * to select cmd or data. NOTE: This design restricts, for example, + * one one SPI display per SPI bus. + * cmd - true: select command; false: select data + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_CMDDATA +#ifdef CONFIG_GD32F4_SPI0 +int gd32_spi0cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_GD32F4_SPI1 +int gd32_spi1cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_GD32F4_SPI2 +int gd32_spi2cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_GD32F4_SPI3 +int gd32_spi3cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_GD32F4_SPI5 +int gd32_spi4cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_GD32F4_SPI5 +int gd32_spi5cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#endif /* CONFIG_SPI_CMDDATA */ + +#endif /* defined(CONFIG_SPI) */ diff --git a/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_userleds.c b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_userleds.c new file mode 100644 index 0000000000..c93549bcd7 --- /dev/null +++ b/boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_userleds.c @@ -0,0 +1,153 @@ +/**************************************************************************** + * boards/arm/gd32f4/gd32f450zk-eval/src/gd32f4xx_userleds.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "gd32f4xx_gpio.h" +#include "gd32f450z_eval.h" + +#ifndef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0])) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* LED index */ + +static const uint32_t g_led_map[BOARD_LEDS] = +{ + LED1, + LED2, + LED3 +}; + +static const uint32_t g_led_setmap[BOARD_LEDS] = +{ + BOARD_LED1_BIT, + BOARD_LED2_BIT, + BOARD_LED3_BIT +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Turn on selected led */ + +static void gd32_eval_led_on(led_typedef_enum led_num) +{ + gd32_gpio_write(g_led_map[led_num], true); +} + +/* Turn off selected led */ + +static void gd32_eval_led_off(led_typedef_enum led_num) +{ + gd32_gpio_write(g_led_map[led_num], false); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_userled_initialize + * + * Description: + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then the + * board_userled_initialize() is available to initialize the LED from user + * application logic. + * + ****************************************************************************/ + +uint32_t board_userled_initialize(void) +{ + int i; + + /* Configure the LED GPIO for output. */ + + for (i = 0; i < ARRAYSIZE(g_led_map); i++) + { + gd32_gpio_config(g_led_map[i]); + } + + return BOARD_LEDS; +} + +/**************************************************************************** + * Name: board_userled + * + * Description: + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then the board_userled() is + * available to control the LED from user application logic. + * + ****************************************************************************/ + +void board_userled(int led, bool ledon) +{ + if ((unsigned)led < ARRAYSIZE(g_led_map)) + { + gd32_gpio_write(g_led_map[led], ledon); + } +} + +/**************************************************************************** + * Name: board_userled_all + * + * Description: + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then the board_userled_all() + * is available to control the LED from user application logic. + * NOTE: since there is only a single LED on-board, this is function + * is not very useful. + * + ****************************************************************************/ + +void board_userled_all(uint32_t ledset) +{ + int i; + + /* Configure LED1-3 GPIOs for output */ + + for (i = 0; i < ARRAYSIZE(g_led_map); i++) + { + gd32_gpio_write(g_led_map[i], (ledset & g_led_setmap[i]) != 0); + } +} + +#endif /* !CONFIG_ARCH_LEDS */