~ruther/qmk_firmware

e50867d52d9c255570630a23514842749b45e4c1 — Stefan Kerkmann 3 years ago 7e3ff20
[Core] Add support for RISC-V builds and GD32VF103 MCU (#12508)

* Add support for RISC-V builds and GD32VF103 MCU

* Add toolchain selection in chibios.mk based on the mcu selected in
mcu_selection.mk
* Reorder and added comments to chibios.mk to have a streamlined makefile
* Add GD32VF103 mcu to possible targets for QMK.
* Add STM32 compatibility for GD32VF103 MCU, this is hacky but more efficent
  then rewriting every driver.
* Add GigaDevice DFU bootloader as flash target, please note that
  dfu-util of at least version 0.10 is needed.
* Add analog driver compatibility
* Add apa102 bitbang driver compatibility
* Add ws2812 bitbang driver compatibility
* Add eeprom in flash emulation compatibility
* Allow faster re-builds with ccache

* Add SiPeed Longan Nano to platform files

* Add SiPeed Longan Nano Onekeys

* Make quine compatible with other bootloaders

* Support builds with picolibc

* Add risc-v toolchain to arch and debian/ubuntu scripts
M bootloader.mk => bootloader.mk +9 -0
@@ 34,6 34,8 @@
#     stm32duino   STM32Duino (STM32F103x8)
#     stm32-dfu    STM32 USB DFU in ROM
#     apm32-dfu    APM32 USB DFU in ROM
# RISC-V:
#     gd32v-dfu    GD32V USB DFU in ROM
#
# BOOTLOADER_SIZE can still be defined manually, but it's recommended
# you add any possible configuration to this list


@@ 125,6 127,13 @@ ifeq ($(strip $(BOOTLOADER)), apm32-dfu)
    DFU_ARGS ?= -d 314B:0106 -a 0 -s 0x08000000:leave
    DFU_SUFFIX_ARGS ?= -v 314B -p 0106
endif
ifeq ($(strip $(BOOTLOADER)), gd32v-dfu)
    OPT_DEFS += -DBOOTLOADER_GD32V_DFU

    # Options to pass to dfu-util when flashing
    DFU_ARGS ?= -d 28E9:0189 -a 0 -s 0x08000000:leave
    DFU_SUFFIX_ARGS ?= -v 28E9 -p 0189
endif
ifeq ($(strip $(BOOTLOADER)), kiibohd)
    OPT_DEFS += -DBOOTLOADER_KIIBOHD
    ifeq ($(strip $(MCU_ORIG)), MK20DX128)

M common_features.mk => common_features.mk +1 -1
@@ 142,7 142,7 @@ else
    ifeq ($(PLATFORM),AVR)
      # Automatically provided by avr-libc, nothing required
    else ifeq ($(PLATFORM),CHIBIOS)
      ifneq ($(filter STM32F3xx_% STM32F1xx_% %_STM32F401xC %_STM32F401xE %_STM32F405xG %_STM32F411xE %_STM32F072xB %_STM32F042x6, $(MCU_SERIES)_$(MCU_LDSCRIPT)),)
      ifneq ($(filter STM32F3xx_% STM32F1xx_% %_STM32F401xC %_STM32F401xE %_STM32F405xG %_STM32F411xE %_STM32F072xB %_STM32F042x6 %_GD32VF103xB %_GD32VF103x8, $(MCU_SERIES)_$(MCU_LDSCRIPT)),)
        OPT_DEFS += -DEEPROM_DRIVER
        COMMON_VPATH += $(DRIVER_PATH)/eeprom
        SRC += eeprom_driver.c

M data/schemas/keyboard.jsonschema => data/schemas/keyboard.jsonschema +2 -2
@@ 13,7 13,7 @@
        },
        "processor": {
            "type": "string",
            "enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "MK66FX1M0", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F405", "STM32F407", "STM32F411", "STM32F446", "STM32G431", "STM32G474", "STM32L412", "STM32L422", "STM32L433", "STM32L443", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"]
            "enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "MK66FX1M0", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F405", "STM32F407", "STM32F411", "STM32F446", "STM32G431", "STM32G474", "STM32L412", "STM32L422", "STM32L433", "STM32L443", "GD32VF103", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"]
        },
        "audio": {
            "type": "object",


@@ 56,7 56,7 @@
        },
        "bootloader": {
            "type": "string",
            "enum": ["atmel-dfu", "bootloadhid", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "unknown", "usbasploader", "USBasp", "tinyuf2"],
            "enum": ["atmel-dfu", "bootloadhid", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "gd32v-dfu", "unknown", "usbasploader", "USBasp", "tinyuf2"],
        },
        "bootloader_instructions": {
            "type": "string",

M docs/compatible_microcontrollers.md => docs/compatible_microcontrollers.md +6 -0
@@ 48,3 48,9 @@ You can also use any ARM chip with USB that [ChibiOS](https://www.chibios.org) s
## Atmel ATSAM

There is limited support for one of Atmel's ATSAM microcontrollers, that being the [ATSAMD51J18A](https://www.microchip.com/wwwproducts/en/ATSAMD51J18A) used by the [Massdrop keyboards](https://github.com/qmk/qmk_firmware/tree/master/keyboards/massdrop).

## RISC-V

### GigaDevice

[ChibiOS-Contrib](https://github.com/ChibiOS/ChibiOS-Contrib) has support for the GigaDevice [GD32VF103 series](https://www.gigadevice.com/products/microcontrollers/gd32/risc-v/mainstream-line/gd32vf103-series/) microcontrollers and provides configurations for the [SiPeed Longan Nano](https://longan.sipeed.com/en/) development board that uses this microcontroller. It is largely pin and feature compatible with STM32F103 and STM32F303 microcontrollers.
\ No newline at end of file

M docs/driver_installation_zadig.md => docs/driver_installation_zadig.md +1 -0
@@ 93,6 93,7 @@ The device name here is the name that appears in Zadig, and may not be what the 
|`usbasploader`|USBasp                        |`16C0:05DC`   |libusbK|
|`apm32-dfu`   |APM32 DFU ISP Mode            |`314B:0106`   |WinUSB |
|`stm32-dfu`   |STM32 BOOTLOADER              |`0483:DF11`   |WinUSB |
|`gd32v-dfu`   |GD32V BOOTLOADER              |`28E9:0189`   |WinUSB |
|`kiibohd`     |Kiibohd DFU Bootloader        |`1C11:B007`   |WinUSB |
|`stm32duino`  |Maple 003                     |`1EAF:0003`   |WinUSB |
|`qmk-hid`     |(keyboard name) Bootloader    |`03EB:2067`   |HidUsb |

M drivers/led/apa102.c => drivers/led/apa102.c +1 -1
@@ 24,7 24,7 @@
#    elif defined(PROTOCOL_CHIBIOS)

#        include "hal.h"
#        if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
#        if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) || defined(GD32VF103)
#            define APA102_NOPS (100 / (1000000000L / (CPU_CLOCK / 4)))  // This calculates how many loops of 4 nops to run to delay 100 ns
#        else
#            error("APA102_NOPS configuration required")

D keyboards/handwired/onekey/keymaps/quine/rules.mk => keyboards/handwired/onekey/keymaps/quine/rules.mk +0 -1
@@ 1,1 0,0 @@
BOOTLOADER = atmel-dfu

M keyboards/handwired/onekey/readme.md => keyboards/handwired/onekey/readme.md +1 -1
@@ 3,7 3,7 @@
Custom handwired one key keyboard. **See each individual board for pin information.**

* Keyboard Maintainer: QMK Community
* Hardware Supported: bluepill, Elite-C, Pro Micro, Proton C, Teensy 2.0, Teensy++ 2.0, Teensy LC, Teensy 3.2
* Hardware Supported: Blackpill F401/F411, Bluepill, Elite-C, Pro Micro, Proton C, Sipeed Longan Nano, STM32F0 Disco, Teensy 2.0, Teensy++ 2.0, Teensy LC, Teensy 3.2
* Hardware Availability: *n/a*

Make example for this keyboard (after setting up your build environment):

A keyboards/handwired/onekey/sipeed_longan_nano/chconf.h => keyboards/handwired/onekey/sipeed_longan_nano/chconf.h +23 -0
@@ 0,0 1,23 @@
/* Copyright 2021 QMK
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#define CH_CFG_ST_RESOLUTION 16

#define CH_CFG_ST_FREQUENCY 10000

#include_next <chconf.h>

A keyboards/handwired/onekey/sipeed_longan_nano/config.h => keyboards/handwired/onekey/sipeed_longan_nano/config.h +37 -0
@@ 0,0 1,37 @@
/* Copyright 2021 QMK
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "config_common.h"

#define MATRIX_COL_PINS \
    { B0 }
#define MATRIX_ROW_PINS \
    { A7 }
#define UNUSED_PINS

#define BACKLIGHT_PIN A1           /* Green LED. */
#define BACKLIGHT_PWM_DRIVER PWMD5 /* GD32 numbering scheme starts from 0, TIMER4 on GD32 boards is TIMER5 on STM32 boards. */
#define BACKLIGHT_PWM_CHANNEL 2    /* GD32 numbering scheme starts from 0, Channel 1 on GD32 boards is Channel 2 on STM32 boards. */

#define RGB_DI_PIN A2
#define RGB_CI_PIN B13

#define ADC_PIN A0

#define I2C1_CLOCK_SPEED 1000000 /* GD32VF103 supports fast mode plus. */
#define I2C1_DUTY_CYCLE FAST_DUTY_CYCLE_2

A keyboards/handwired/onekey/sipeed_longan_nano/halconf.h => keyboards/handwired/onekey/sipeed_longan_nano/halconf.h +23 -0
@@ 0,0 1,23 @@
/* Copyright 2021 QMK
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#define HAL_USE_PWM TRUE
#define HAL_USE_ADC TRUE
#define HAL_USE_I2C TRUE

#include_next <halconf.h>

A keyboards/handwired/onekey/sipeed_longan_nano/mcuconf.h => keyboards/handwired/onekey/sipeed_longan_nano/mcuconf.h +29 -0
@@ 0,0 1,29 @@
/*
    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
    ChibiOS - Copyright (C) 2021 Stefan Kerkmann

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        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.
*/

#pragma once

#include_next <mcuconf.h>

#undef GD32_ADC_USE_ADC0
#define GD32_ADC_USE_ADC0 TRUE

#undef GD32_I2C_USE_I2C0
#define GD32_I2C_USE_I2C0 TRUE

#undef GD32_PWM_USE_TIM4
#define GD32_PWM_USE_TIM4 TRUE

A keyboards/handwired/onekey/sipeed_longan_nano/readme.md => keyboards/handwired/onekey/sipeed_longan_nano/readme.md +5 -0
@@ 0,0 1,5 @@
# Sipeed Longan Nano onekey

Supported Hardware: *GD32VF103CB Sipeed Longan Nano*.

To trigger keypress, short together pins *B0* and *A7*.
\ No newline at end of file

A keyboards/handwired/onekey/sipeed_longan_nano/rules.mk => keyboards/handwired/onekey/sipeed_longan_nano/rules.mk +11 -0
@@ 0,0 1,11 @@
# MCU name
MCU   = GD32VF103
BOARD = SIPEED_LONGAN_NANO

# Bootloader selection
BOOTLOADER = gd32v-dfu

# Build Options
#   change yes to no to disable
#
KEYBOARD_SHARED_EP = yes

M lib/python/qmk/constants.py => lib/python/qmk/constants.py +1 -1
@@ 13,7 13,7 @@ QMK_FIRMWARE_UPSTREAM = 'qmk/qmk_firmware'
MAX_KEYBOARD_SUBFOLDERS = 5

# Supported processor types
CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK66FX1M0', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F407', 'STM32F411', 'STM32F446', 'STM32G431', 'STM32G474', 'STM32L412', 'STM32L422', 'STM32L433', 'STM32L443'
CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK66FX1M0', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F407', 'STM32F411', 'STM32F446', 'STM32G431', 'STM32G474', 'STM32L412', 'STM32L422', 'STM32L433', 'STM32L443', 'GD32VF103'
LUFA_PROCESSORS = 'at90usb162', 'atmega16u2', 'atmega32u2', 'atmega16u4', 'atmega32u4', 'at90usb646', 'at90usb647', 'at90usb1286', 'at90usb1287', None
VUSB_PROCESSORS = 'atmega32a', 'atmega328p', 'atmega328', 'attiny85'


A platforms/chibios/boards/SIPEED_LONGAN_NANO/board/board.mk => platforms/chibios/boards/SIPEED_LONGAN_NANO/board/board.mk +9 -0
@@ 0,0 1,9 @@
# List of all the board related files.
BOARDSRC = ${CHIBIOS_CONTRIB}/os/hal/boards/SIPEED_LONGAN_NANO/board.c

# Required include directories
BOARDINC = ${CHIBIOS_CONTRIB}/os/hal/boards/SIPEED_LONGAN_NANO

# Shared variables
ALLCSRC += $(BOARDSRC)
ALLINC  += $(BOARDINC)

A platforms/chibios/boards/SIPEED_LONGAN_NANO/configs/chconf.h => platforms/chibios/boards/SIPEED_LONGAN_NANO/configs/chconf.h +23 -0
@@ 0,0 1,23 @@
/* Copyright 2021 QMK
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* To compile the ChibiOS syscall stubs with picolibc
 * the _reent struct has to be defined. */
#if !defined(_FROM_ASM_) && defined(USE_PICOLIBC)
struct _reent;
#endif

#include_next <chconf.h>
\ No newline at end of file

A platforms/chibios/boards/SIPEED_LONGAN_NANO/configs/mcuconf.h => platforms/chibios/boards/SIPEED_LONGAN_NANO/configs/mcuconf.h +302 -0
@@ 0,0 1,302 @@
/*
    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
    ChibiOS - Copyright (C) 2021 Stefan Kerkmann

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        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.
*/

#pragma once

#define GD32VF103_MCUCONF
#define GD32VF103CB

/*
 * GD32VF103 drivers configuration.
 * The following settings override the default settings present in
 * the various device driver implementation headers.
 * Note that the settings for each driver only have effect if the whole
 * driver is enabled in halconf.h.
 *
 * IRQ priorities:
 * 0...15       Lowest...Highest.
 *
 * DMA priorities:
 * 0...3        Lowest...Highest.
 */

/*
 * HAL driver system settings.
*/

#if defined(OVERCLOCK_120MHZ)
/* (8MHz / 2) * 30 = 120MHz Sysclock */
#define GD32_ALLOW_120MHZ_SYSCLK
#define GD32_PLLMF_VALUE                     30
#define GD32_USBFSPSC                        GD32_USBFSPSC_DIV2P5
#else
/* (8MHz / 2) * 24 = 96MHz Sysclock */
#define GD32_PLLMF_VALUE                     24
#define GD32_USBFSPSC                        GD32_USBFSPSC_DIV2
#endif

#define GD32_NO_INIT                         FALSE
#define GD32_IRC8M_ENABLED                   TRUE
#define GD32_IRC40K_ENABLED                  FALSE
#define GD32_HXTAL_ENABLED                   TRUE
#define GD32_LXTAL_ENABLED                   FALSE
#define GD32_SCS                             GD32_SCS_PLL
#define GD32_PLLSEL                          GD32_PLLSEL_PREDV0
#define GD32_PREDV0SEL                       GD32_PREDV0SEL_HXTAL
#define GD32_PREDV0_VALUE                    2
#define GD32_PREDV1_VALUE                    2
#define GD32_PLL1MF_VALUE                    14
#define GD32_PLL2MF_VALUE                    13
#define GD32_AHBPSC                          GD32_AHBPSC_DIV1
#define GD32_APB1PSC                         GD32_APB1PSC_DIV2
#define GD32_APB2PSC                         GD32_APB2PSC_DIV1
#define GD32_ADCPSC                          GD32_ADCPSC_DIV16
#define GD32_USB_CLOCK_REQUIRED              TRUE
#define GD32_I2S_CLOCK_REQUIRED              FALSE
#define GD32_CKOUT0SEL                       GD32_CKOUT0SEL_NOCLOCK
#define GD32_RTCSRC                          GD32_RTCSRC_NOCLOCK
#define GD32_PVD_ENABLE                      FALSE
#define GD32_LVDT                            GD32_LVDT_LEV0

/*
 * ECLIC system settings.
 */
#define ECLIC_TRIGGER_DEFAULT                ECLIC_POSTIVE_EDGE_TRIGGER
#define ECLIC_DMA_TRIGGER                    ECLIC_TRIGGER_DEFAULT

/*
 * IRQ system settings.
 */
#define GD32_IRQ_EXTI0_PRIORITY              6
#define GD32_IRQ_EXTI1_PRIORITY              6
#define GD32_IRQ_EXTI2_PRIORITY              6
#define GD32_IRQ_EXTI3_PRIORITY              6
#define GD32_IRQ_EXTI4_PRIORITY              6
#define GD32_IRQ_EXTI5_9_PRIORITY            6
#define GD32_IRQ_EXTI10_15_PRIORITY          6
#define GD32_IRQ_EXTI0_TRIGGER               ECLIC_TRIGGER_DEFAULT
#define GD32_IRQ_EXTI1_TRIGGER               ECLIC_TRIGGER_DEFAULT
#define GD32_IRQ_EXTI2_TRIGGER               ECLIC_TRIGGER_DEFAULT
#define GD32_IRQ_EXTI3_TRIGGER               ECLIC_TRIGGER_DEFAULT
#define GD32_IRQ_EXTI4_TRIGGER               ECLIC_TRIGGER_DEFAULT
#define GD32_IRQ_EXTI5_9_TRIGGER             ECLIC_TRIGGER_DEFAULT
#define GD32_IRQ_EXTI10_15_TRIGGER           ECLIC_TRIGGER_DEFAULT

/*
 * ADC driver system settings.
 */
#define GD32_ADC_USE_ADC0                    FALSE
#define GD32_ADC_ADC0_DMA_PRIORITY           2
#define GD32_ADC_ADC0_IRQ_PRIORITY           6

/*
 * CAN driver system settings.
 */
#define GD32_CAN_USE_CAN0                    FALSE
#define GD32_CAN_CAN0_IRQ_PRIORITY           11
#define GD32_CAN_USE_CAN1                    FALSE
#define GD32_CAN_CAN1_IRQ_PRIORITY           11
#define GD32_CAN_CAN0_IRQ_TRIGGER            ECLIC_TRIGGER_DEFAULT
#define GD32_CAN_CAN1_IRQ_TRIGGER            ECLIC_TRIGGER_DEFAULT

/*
 * CRC driver system settings.
 */
#define GD32_CRC_USE_CRC0                   FALSE
#define GD32_CRC_CRC0_DMA_IRQ_PRIORITY      14
#define GD32_CRC_CRC0_DMA_PRIORITY          2
#define GD32_CRC_CRC0_DMA_STREAM            GD32_DMA_STREAM_ID(0, 0)
#define CRC_USE_DMA                         FALSE
#define CRCSW_USE_CRC1                      FALSE
#define CRCSW_CRC32_TABLE                   FALSE
#define CRCSW_CRC16_TABLE                   FALSE
#define CRCSW_PROGRAMMABLE                  FALSE

/*
 * DAC driver system settings.
 */
#define GD32_DAC_USE_DAC_CH1                FALSE
#define GD32_DAC_USE_DAC_CH2                FALSE

/*
 * GPT driver system settings.
 */
#define GD32_GPT_USE_TIM0                   FALSE
#define GD32_GPT_USE_TIM1                   FALSE
#define GD32_GPT_USE_TIM2                   FALSE
#define GD32_GPT_USE_TIM3                   FALSE
#define GD32_GPT_USE_TIM4                   FALSE
#define GD32_GPT_TIM0_IRQ_PRIORITY          7
#define GD32_GPT_TIM1_IRQ_PRIORITY          7
#define GD32_GPT_TIM2_IRQ_PRIORITY          7
#define GD32_GPT_TIM3_IRQ_PRIORITY          7
#define GD32_GPT_TIM4_IRQ_PRIORITY          7
#define GD32_GPT_TIM0_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_GPT_TIM1_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_GPT_TIM2_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_GPT_TIM3_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_GPT_TIM4_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_GPT_TIM5_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_GPT_TIM6_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT

/*
 * I2S driver system settings.
 */
#define GD32_I2S_USE_SPI1                   FALSE
#define GD32_I2S_USE_SPI2                   FALSE
#define GD32_I2S_SPI1_IRQ_PRIORITY          10
#define GD32_I2S_SPI2_IRQ_PRIORITY          10
#define GD32_I2S_SPI1_DMA_PRIORITY          1
#define GD32_I2S_SPI2_DMA_PRIORITY          1
#define GD32_I2S_DMA_ERROR_HOOK(i2sp)       osalSysHalt("DMA failure")

/*
 * I2C driver system settings.
 */
#define GD32_I2C_USE_I2C0                   FALSE
#define GD32_I2C_USE_I2C1                   FALSE
#define GD32_I2C_BUSY_TIMEOUT               50
#define GD32_I2C_I2C0_IRQ_PRIORITY          10
#define GD32_I2C_I2C1_IRQ_PRIORITY          5
#define GD32_I2C_I2C0_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_I2C_I2C1_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_I2C_I2C0_DMA_PRIORITY          2
#define GD32_I2C_I2C1_DMA_PRIORITY          2
#define GD32_I2C_DMA_ERROR_HOOK(i2cp)       osalSysHalt("DMA failure")

/*
 * ICU driver system settings.
 */
#define GD32_ICU_USE_TIM0                   FALSE
#define GD32_ICU_USE_TIM1                   FALSE
#define GD32_ICU_USE_TIM2                   FALSE
#define GD32_ICU_USE_TIM3                   FALSE
#define GD32_ICU_USE_TIM4                   FALSE
#define GD32_ICU_TIM0_IRQ_PRIORITY          7
#define GD32_ICU_TIM1_IRQ_PRIORITY          7
#define GD32_ICU_TIM2_IRQ_PRIORITY          7
#define GD32_ICU_TIM3_IRQ_PRIORITY          7
#define GD32_ICU_TIM4_IRQ_PRIORITY          7
#define GD32_ICU_TIM0_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_ICU_TIM1_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_ICU_TIM2_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_ICU_TIM3_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_ICU_TIM4_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT

/*
 * PWM driver system settings.
 */
#define GD32_PWM_USE_ADVANCED               FALSE
#define GD32_PWM_USE_TIM0                   FALSE
#define GD32_PWM_USE_TIM1                   FALSE
#define GD32_PWM_USE_TIM2                   FALSE
#define GD32_PWM_USE_TIM3                   FALSE
#define GD32_PWM_USE_TIM4                   FALSE
#define GD32_PWM_TIM0_IRQ_PRIORITY          10
#define GD32_PWM_TIM1_IRQ_PRIORITY          10
#define GD32_PWM_TIM2_IRQ_PRIORITY          10
#define GD32_PWM_TIM3_IRQ_PRIORITY          10
#define GD32_PWM_TIM4_IRQ_PRIORITY          10
#define GD32_PWM_TIM0_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_PWM_TIM1_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_PWM_TIM2_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_PWM_TIM3_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_PWM_TIM4_IRQ_TRIGGER           ECLIC_TRIGGER_DEFAULT

/*
 * RTC driver system settings.
 */
#define GD32_RTC_IRQ_PRIORITY               15
#define GD32_RTC_IRQ_TRIGGER                ECLIC_TRIGGER_DEFAULT

/*
 * SERIAL driver system settings.
 */
#define GD32_SERIAL_USE_USART0              FALSE
#define GD32_SERIAL_USE_USART1              FALSE
#define GD32_SERIAL_USE_USART2              FALSE
#define GD32_SERIAL_USE_UART3               FALSE
#define GD32_SERIAL_USE_UART4               FALSE
#define GD32_SERIAL_USART0_PRIORITY         10
#define GD32_SERIAL_USART1_PRIORITY         10
#define GD32_SERIAL_USART2_PRIORITY         10
#define GD32_SERIAL_UART3_PRIORITY          10
#define GD32_SERIAL_UART4_PRIORITY          10
#define GD32_SERIAL_USART0_TRIGGER          ECLIC_TRIGGER_DEFAULT
#define GD32_SERIAL_USART1_TRIGGER          ECLIC_TRIGGER_DEFAULT
#define GD32_SERIAL_USART2_TRIGGER          ECLIC_TRIGGER_DEFAULT
#define GD32_SERIAL_UART3_TRIGGER           ECLIC_TRIGGER_DEFAULT
#define GD32_SERIAL_UART4_TRIGGER           ECLIC_TRIGGER_DEFAULT

/*
 * SPI driver system settings.
 */
#define GD32_SPI_USE_SPI0                   FALSE
#define GD32_SPI_USE_SPI1                   FALSE
#define GD32_SPI_USE_SPI2                   FALSE
#define GD32_SPI_SPI0_DMA_PRIORITY          1
#define GD32_SPI_SPI1_DMA_PRIORITY          1
#define GD32_SPI_SPI2_DMA_PRIORITY          1
#define GD32_SPI_SPI0_IRQ_PRIORITY          10
#define GD32_SPI_SPI1_IRQ_PRIORITY          10
#define GD32_SPI_SPI2_IRQ_PRIORITY          10
#define GD32_SPI_DMA_ERROR_HOOK(spip)       osalSysHalt("DMA failure")

/*
 * ST driver system settings.
 */
#define GD32_ST_IRQ_PRIORITY                10
#define GD32_ST_IRQ_TRIGGER                 ECLIC_TRIGGER_DEFAULT
#define GD32_ST_USE_TIMER                   1

/*
 * UART driver system settings.
 */
#define GD32_UART_USE_USART0                FALSE
#define GD32_UART_USE_USART1                FALSE
#define GD32_UART_USE_USART2                FALSE
#define GD32_UART_USE_UART3                 FALSE
#define GD32_UART_USE_UART4                 FALSE
#define GD32_UART_USART0_IRQ_PRIORITY       10
#define GD32_UART_USART1_IRQ_PRIORITY       10
#define GD32_UART_USART2_IRQ_PRIORITY       10
#define GD32_UART_UART3_IRQ_PRIORITY        10
#define GD32_UART_UART4_IRQ_PRIORITY        10
#define GD32_UART_USART0_IRQ_TRIGGER        ECLIC_TRIGGER_DEFAULT
#define GD32_UART_USART1_IRQ_TRIGGER        ECLIC_TRIGGER_DEFAULT
#define GD32_UART_USART2_IRQ_TRIGGER        ECLIC_TRIGGER_DEFAULT
#define GD32_UART_UART3_IRQ_TRIGGER         ECLIC_TRIGGER_DEFAULT
#define GD32_UART_UART4_IRQ_TRIGGER         ECLIC_TRIGGER_DEFAULT
#define GD32_UART_USART0_DMA_PRIORITY       3
#define GD32_UART_USART1_DMA_PRIORITY       3
#define GD32_UART_USART2_DMA_PRIORITY       3
#define GD32_UART_UART3_DMA_PRIORITY        3
#define GD32_UART_UART4_DMA_PRIORITY        3
#define GD32_UART_DMA_ERROR_HOOK(uartp)     osalSysHalt("DMA failure")

/*
 * USB driver system settings.
 */
#define GD32_USB_USE_USBFS                  TRUE
#define GD32_USB_USBFS_IRQ_PRIORITY         10
#define GD32_USB_USBFS_IRQ_TRIGGER          ECLIC_TRIGGER_DEFAULT
#define GD32_USB_USBFS_RX_FIFO_SIZE         256

/*
 * WDG driver system settings.
 */
#define GD32_WDG_USE_FWDGT                  FALSE

M platforms/chibios/drivers/analog.c => platforms/chibios/drivers/analog.c +5 -5
@@ 38,7 38,7 @@
// Otherwise assume V3
#if defined(STM32F0XX) || defined(STM32L0XX)
#    define USE_ADCV1
#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX)
#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(GD32VF103)
#    define USE_ADCV2
#endif



@@ 75,7 75,7 @@

/* User configurable ADC options */
#ifndef ADC_COUNT
#    if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX)
#    if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX) || defined(GD32VF103)
#        define ADC_COUNT 1
#    elif defined(STM32F3XX)
#        define ADC_COUNT 4


@@ 122,8 122,8 @@ static ADCConversionGroup adcConversionGroup = {
    .cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION,
    .smpr  = ADC_SAMPLING_RATE,
#elif defined(USE_ADCV2)
#    if !defined(STM32F1XX)
    .cr2 = ADC_CR2_SWSTART,  // F103 seem very unhappy with, F401 seems very unhappy without...
#    if !defined(STM32F1XX) && !defined(GD32VF103)
    .cr2   = ADC_CR2_SWSTART,  // F103 seem very unhappy with, F401 seems very unhappy without...
#    endif
    .smpr2 = ADC_SMPR2_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN9(ADC_SAMPLING_RATE),
    .smpr1 = ADC_SMPR1_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN15(ADC_SAMPLING_RATE),


@@ 220,7 220,7 @@ __attribute__((weak)) adc_mux pinToMux(pin_t pin) {
        case F9:  return TO_MUX( ADC_CHANNEL_IN7,  2 );
        case F10: return TO_MUX( ADC_CHANNEL_IN8,  2 );
#    endif
#elif defined(STM32F1XX)
#elif defined(STM32F1XX) || defined(GD32VF103)
        case A0:  return TO_MUX( ADC_CHANNEL_IN0,  0 );
        case A1:  return TO_MUX( ADC_CHANNEL_IN1,  0 );
        case A2:  return TO_MUX( ADC_CHANNEL_IN2,  0 );

M platforms/chibios/drivers/ws2812.c => platforms/chibios/drivers/ws2812.c +1 -1
@@ 6,7 6,7 @@
/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */

#ifndef NOP_FUDGE
#    if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
#    if defined(STM32F0XX) || defined(STM32F1XX) || defined(GD32VF103) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
#        define NOP_FUDGE 0.4
#    else
#        error("NOP_FUDGE configuration required")

M platforms/chibios/flash.mk => platforms/chibios/flash.mk +2 -0
@@ 82,6 82,8 @@ else ifeq ($(strip $(MCU_FAMILY)),MIMXRT1062)
	$(UNSYNC_OUTPUT_CMD) && $(call EXEC_TEENSY)
else ifeq ($(strip $(MCU_FAMILY)),STM32)
	$(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL)
else ifeq ($(strip $(MCU_FAMILY)),GD32V)
	$(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL)
else
	$(PRINT_OK); $(SILENT) || printf "$(MSG_FLASH_BOOTLOADER)"
endif

M quantum/mcu_selection.mk => quantum/mcu_selection.mk +31 -0
@@ 541,6 541,37 @@ ifneq (,$(filter $(MCU),STM32L412 STM32L422))
  UF2_FAMILY ?= STM32L4
endif

ifneq ($(findstring GD32VF103, $(MCU)),)
  # RISC-V
  MCU = risc-v
  
  # RISC-V extensions and abi configuration
  MCU_ARCH = rv32imac
  MCU_ABI = ilp32
  MCU_CMODEL = medlow

  ## chip/board settings
  # - the next two should match the directories in
  #   <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
  MCU_FAMILY = GD32V
  MCU_SERIES = GD32VF103

  # Linker script to use
  # - it should exist either in <chibios>/os/common/startup/RISCV-ECLIC/compilers/GCC/ld/
  #   or <keyboard_dir>/ld/
  MCU_LDSCRIPT ?= GD32VF103xB

  # Startup code to use
  #  - it should exist in <chibios>/os/common/startup/RISCV-ECLIC/compilers/GCC/mk/
  MCU_STARTUP ?= gd32vf103

  # Board: it should exist either in <chibios>/os/hal/boards/,
  # <keyboard_dir>/boards/, or drivers/boards/
  BOARD ?= SIPEED_LONGAN_NANO

  USE_FPU ?= no
endif

ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287))
  PROTOCOL = LUFA


M tmk_core/chibios.mk => tmk_core/chibios.mk +201 -109
@@ 27,29 27,62 @@ endif
OPT_OS = chibios
CHIBIOS = $(TOP_DIR)/lib/chibios
CHIBIOS_CONTRIB = $(TOP_DIR)/lib/chibios-contrib
# Startup files. Try a few different locations, for compability with old versions and
# for things hardware in the contrib repository
STARTUP_MK = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
ifeq ("$(wildcard $(STARTUP_MK))","")
	STARTUP_MK = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
	ifeq ("$(wildcard $(STARTUP_MK))","")
		STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
	endif

#
# Startup, Port and Platform support selection
##############################################################################

ifeq ($(strip $(MCU)), risc-v)
    # RISC-V Support
    # As of 7.4.2021 there is only one supported RISC-V platform in Chibios-Contrib,
    # therefore all required settings are hard-coded
    STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/RISCV-ECLIC/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
    PORT_V = $(CHIBIOS_CONTRIB)/os/common/ports/RISCV-ECLIC/compilers/GCC/mk/port.mk
    RULESPATH = $(CHIBIOS_CONTRIB)/os/common/startup/RISCV-ECLIC/compilers/GCC
    PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/GD/GD32VF103/platform.mk
else
    # ARM Support
    # Startup files. Try a few different locations, for compability with old versions and
    # for things hardware in the contrib repository
    STARTUP_MK = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
    ifeq ("$(wildcard $(STARTUP_MK))","")
        STARTUP_MK = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
        ifeq ("$(wildcard $(STARTUP_MK))","")
            STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
        endif
    endif

    # Compability with old version
    PORT_V = $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
    ifeq ("$(wildcard $(PORT_V))","")
        PORT_V = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
    endif

    RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
    ifeq ("$(wildcard $(RULESPATH)/rules.mk)","")
        RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
    endif
endif
include $(STARTUP_MK)
# HAL-OSAL files (optional).
include $(CHIBIOS)/os/hal/hal.mk

ifeq ("$(PLATFORM_NAME)","")
	PLATFORM_NAME = platform
    PLATFORM_NAME = platform
endif

PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
ifeq ("$(wildcard $(PLATFORM_MK))","")
PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
    PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
    ifeq ("$(wildcard $(PLATFORM_MK))","")
        PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
    endif
endif

include $(STARTUP_MK)
include $(PORT_V)
include $(PLATFORM_MK)

#
# Board support selection.
##############################################################################

BOARD_MK :=

ifneq ("$(wildcard $(KEYBOARD_PATH_5)/boards/$(BOARD)/board.mk)","")


@@ 77,13 110,19 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/board/board
endif

ifeq ("$(wildcard $(BOARD_MK))","")
	BOARD_MK = $(CHIBIOS)/os/hal/boards/$(BOARD)/board.mk
	ifeq ("$(wildcard $(BOARD_MK))","")
		BOARD_MK = $(CHIBIOS_CONTRIB)/os/hal/boards/$(BOARD)/board.mk
	endif
    BOARD_MK = $(CHIBIOS)/os/hal/boards/$(BOARD)/board.mk
    ifeq ("$(wildcard $(BOARD_MK))","")
        BOARD_MK = $(CHIBIOS_CONTRIB)/os/hal/boards/$(BOARD)/board.mk
    endif
endif

# Bootloader address
include $(BOARD_MK)

#
# Bootloader selection.
##############################################################################

# Set bootloader address if supplied.
ifdef STM32_BOOTLOADER_ADDRESS
    OPT_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS)
endif


@@ 113,6 152,10 @@ else ifneq ("$(wildcard $(BOARD_PATH)/configs/bootloader_defs.h)","")
    OPT_DEFS += -include $(BOARD_PATH)/configs/bootloader_defs.h
endif

#
# ChibiOS config selection.
##############################################################################

# Work out the config file directories
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/chconf.h)","")
    CHCONFDIR = $(KEYBOARD_PATH_5)


@@ 130,6 173,10 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/boards/chibios/common/configs/chcon
    CHCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs
endif

#
# HAL config selection.
##############################################################################

ifneq ("$(wildcard $(KEYBOARD_PATH_5)/halconf.h)","")
    HALCONFDIR = $(KEYBOARD_PATH_5)
else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/halconf.h)","")


@@ 146,40 193,10 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/common/configs/halco
    HALCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs
endif

# HAL-OSAL files (optional).
include $(CHIBIOS)/os/hal/hal.mk

ifeq ("$(PLATFORM_NAME)","")
	PLATFORM_NAME = platform
endif

PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
ifeq ("$(wildcard $(PLATFORM_MK))","")
PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
endif
include $(PLATFORM_MK)


include $(BOARD_MK)
-include $(CHIBIOS)/os/hal/osal/rt/osal.mk         # ChibiOS <= 19.x
-include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk     # ChibiOS >= 20.x
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
# Compability with old version
PORT_V = $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
ifeq ("$(wildcard $(PORT_V))","")
PORT_V = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
endif
include $(PORT_V)
# Other files (optional).
include $(CHIBIOS)/os/hal/lib/streams/streams.mk

RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
ifeq ("$(wildcard $(RULESPATH)/rules.mk)","")
RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
endif
#
# Linker script selection.
##############################################################################

# Define linker script file here
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/ld/$(MCU_LDSCRIPT).ld)","")
    LDSCRIPT = $(KEYBOARD_PATH_5)/ld/$(MCU_LDSCRIPT).ld
else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/ld/$(MCU_LDSCRIPT).ld)","")


@@ 202,17 219,30 @@ else
    LDSCRIPT = $(STARTUPLD)/$(MCU_LDSCRIPT).ld
endif

#
# Include ChibiOS makefiles.
##############################################################################

# HAL-OSAL files (optional).
include $(CHIBIOS)/os/hal/hal.mk
-include $(CHIBIOS)/os/hal/osal/rt/osal.mk         # ChibiOS <= 19.x
-include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk     # ChibiOS >= 20.x
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
# Other files (optional).
include $(CHIBIOS)/os/hal/lib/streams/streams.mk

CHIBISRC = $(STARTUPSRC) \
       $(KERNSRC) \
       $(PORTSRC) \
       $(OSALSRC) \
       $(HALSRC) \
       $(PLATFORMSRC) \
       $(BOARDSRC) \
       $(STREAMSSRC) \
       $(CHIBIOS)/os/various/syscalls.c \
       $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \
       $(PLATFORM_COMMON_DIR)/wait.c
        $(KERNSRC) \
        $(PORTSRC) \
        $(OSALSRC) \
        $(HALSRC) \
        $(PLATFORMSRC) \
        $(BOARDSRC) \
        $(STREAMSSRC) \
        $(CHIBIOS)/os/various/syscalls.c \
        $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \
        $(PLATFORM_COMMON_DIR)/wait.c

# Ensure the ASM files are not subjected to LTO -- it'll strip out interrupt handlers otherwise.
QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM)


@@ 247,9 277,9 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs/hal
endif

ifeq ($(strip $(USE_CHIBIOS_CONTRIB)),yes)
	include $(CHIBIOS_CONTRIB)/os/hal/hal.mk
	CHIBISRC += $(PLATFORMSRC_CONTRIB) $(HALSRC_CONTRIB)
	EXTRAINCDIRS += $(PLATFORMINC_CONTRIB) $(HALINC_CONTRIB) $(CHIBIOS_CONTRIB)/os/various
    include $(CHIBIOS_CONTRIB)/os/hal/hal.mk
    CHIBISRC += $(PLATFORMSRC_CONTRIB) $(HALSRC_CONTRIB)
    EXTRAINCDIRS += $(PLATFORMINC_CONTRIB) $(HALINC_CONTRIB) $(CHIBIOS_CONTRIB)/os/various
endif

#


@@ 267,61 297,123 @@ ifneq ("$(wildcard $(BOARD_PATH)/configs/post_config.h)","")
endif

##############################################################################
# Compiler settings
# Compiler and Linker configuration
#
CC = arm-none-eabi-gcc
OBJCOPY = arm-none-eabi-objcopy
OBJDUMP = arm-none-eabi-objdump
SIZE = arm-none-eabi-size
AR = arm-none-eabi-ar
NM = arm-none-eabi-nm
HEX = $(OBJCOPY) -O $(FORMAT)
EEP =
BIN = $(OBJCOPY) -O binary

THUMBFLAGS = -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb -DTHUMB

COMPILEFLAGS += -fomit-frame-pointer
COMPILEFLAGS += -falign-functions=16
COMPILEFLAGS += -ffunction-sections
COMPILEFLAGS += -fdata-sections
COMPILEFLAGS += -fno-common
COMPILEFLAGS += -fshort-wchar
COMPILEFLAGS += $(THUMBFLAGS)

# FPU options default (Cortex-M4 and Cortex-M7 single precision).
USE_FPU_OPT ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant

# FPU-related options
USE_FPU ?= no
ifneq ($(USE_FPU),no)
  COMPILEFLAGS += $(USE_FPU_OPT)
  OPT_DEFS += -DCORTEX_USE_FPU=TRUE

# Use defined stack sizes of the main thread in linker scripts
LDSYMBOLS =--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)

# Shared Compiler flags for all toolchains
SHARED_CFLAGS = -fomit-frame-pointer \
                -ffunction-sections \
                -fdata-sections \
                -fno-common \
                -fshort-wchar

# Shared Linker flags for all toolchains
SHARED_LDFLAGS = -T $(LDSCRIPT) \
                 -Wl,$(LDSYMBOLS) \
                 -Wl,--gc-sections \
                 -nostartfiles

ifeq ($(strip $(MCU)), risc-v)
    # RISC-V toolchain specific configuration
    # Find suitable GCC compiler
    ifeq ($(strip $(TOOLCHAIN)),)
        ifneq ($(shell which riscv32-unknown-elf-gcc 2>/dev/null),)
            TOOLCHAIN = riscv32-unknown-elf-
        else
            ifneq ($(shell which riscv64-unknown-elf-gcc 2>/dev/null),)
                TOOLCHAIN = riscv64-unknown-elf-
            else
                $(error "No RISC-V toolchain found. Can't find riscv32-unknown-elf-gcc or riscv64-unknown-elf-gcc found in your systems PATH variable. Please install a valid toolchain and make it accessible!")
            endif
        endif
    endif
    
    # Default to compiling with picolibc for RISC-V targets if available,
    # which is available by default on current (bullseye) debian based systems.
    ifeq ($(shell $(TOOLCHAIN)gcc --specs=picolibc.specs -E - 2>/dev/null >/dev/null </dev/null ; echo $$?),0)
        # Toolchain specific Compiler flags
        # Note that we still link with our own linker script
        # by providing it via the -T flag above.
        TOOLCHAIN_CFLAGS = --specs=picolibc.specs
        
        # Tell QMK that we are compiling with picolibc.
        OPT_DEFS += -DUSE_PICOLIBC
    endif
    
    # MCU architecture flags
    MCUFLAGS = -march=$(MCU_ARCH) \
               -mabi=$(MCU_ABI) \
               -mcmodel=$(MCU_CMODEL) \
               -mstrict-align
else
  OPT_DEFS += -DCORTEX_USE_FPU=FALSE
    # ARM toolchain specific configuration
    TOOLCHAIN ?= arm-none-eabi-

    # Toolchain specific Linker flags
    TOOLCHAIN_LDFLAGS = -Wl,--no-wchar-size-warning \
                        --specs=nano.specs

    # MCU architecture flags
    MCUFLAGS = -mcpu=$(MCU) \
               -mthumb -DTHUMB_PRESENT \
               -mno-thumb-interwork -DTHUMB_NO_INTERWORKING \
               -mno-unaligned-access

    # Some ARM cores like the M4 and M7 have floating point units which can be enabled
    USE_FPU ?= no

    ifneq ($(USE_FPU),no)
        OPT_DEFS += -DCORTEX_USE_FPU=TRUE

        # Default is single precision floats
        USE_FPU_OPT ?= -mfloat-abi=hard \
                       -mfpu=fpv4-sp-d16 \
                       -fsingle-precision-constant

        MCUFLAGS += $(USE_FPU_OPT)
    else
        OPT_DEFS += -DCORTEX_USE_FPU=FALSE
    endif
endif

CFLAGS += $(COMPILEFLAGS)
# Assembler flags
ASFLAGS  += $(SHARED_ASFLAGS) $(TOOLCHAIN_ASFLAGS)

ASFLAGS += $(THUMBFLAGS)
# C Compiler flags
CFLAGS   += $(SHARED_CFLAGS) $(TOOLCHAIN_CFLAGS)

CXXFLAGS += $(COMPILEFLAGS)
CXXFLAGS += -fno-rtti
# C++ Compiler flags
CXXFLAGS += $(CFLAGS) $(SHARED_CXXFLAGS) $(TOOLCHAIN_CXXFLAGS) -fno-rtti

LDFLAGS +=-Wl,--gc-sections
LDFLAGS +=-Wl,--no-wchar-size-warning
LDFLAGS += -mno-thumb-interwork -mthumb
LDSYMBOLS =,--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE)
LDSYMBOLS :=$(LDSYMBOLS),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)
LDFLAGS += -Wl,--script=$(LDSCRIPT)$(LDSYMBOLS)
LDFLAGS += --specs=nano.specs
# Linker flags
LDFLAGS  += $(SHARED_LDFLAGS) $(TOOLCHAIN_LDFLAGS) $(MCUFLAGS)

# Tell QMK that we are hosting it on ChibiOS.
OPT_DEFS += -DPROTOCOL_CHIBIOS

# Workaround to stop ChibiOS from complaining about new GCC -- it's been fixed for 7/8/9 already
OPT_DEFS += -DPORT_IGNORE_GCC_VERSION_CHECK=1
# Speed up recompilations by opt-in usage of ccache
USE_CCACHE ?= no
ifneq ($(USE_CCACHE),no)
    CC_PREFIX ?= ccache
endif

# Construct GCC toolchain
CC      = $(CC_PREFIX) $(TOOLCHAIN)gcc
OBJCOPY = $(TOOLCHAIN)objcopy
OBJDUMP = $(TOOLCHAIN)objdump
SIZE    = $(TOOLCHAIN)size
AR      = $(TOOLCHAIN)ar
NM      = $(TOOLCHAIN)nm
HEX     = $(OBJCOPY) -O $(FORMAT)
EEP     =
BIN     = $(OBJCOPY) -O binary

MCUFLAGS = -mcpu=$(MCU)
##############################################################################
# Make targets
#

DEBUG = gdb


M tmk_core/common/chibios/bootloader.c => tmk_core/common/chibios/bootloader.c +22 -0
@@ 95,6 95,28 @@ void enter_bootloader_mode_if_requested(void) {
    }
}

#elif defined(GD32VF103)

#    define DBGMCU_KEY_UNLOCK 0x4B5A6978
#    define DBGMCU_CMD_RESET 0x1

__IO uint32_t *DBGMCU_KEY = (uint32_t *)DBGMCU_BASE + 0x0CU;
__IO uint32_t *DBGMCU_CMD = (uint32_t *)DBGMCU_BASE + 0x08U;

__attribute__((weak)) void bootloader_jump(void) {
    /* The MTIMER unit of the GD32VF103 doesn't have the MSFRST
     * register to generate a software reset request.
     * BUT instead two undocumented registers in the debug peripheral
     * that allow issueing a software reset. WHO would need the MSFRST
     * register anyway? Source:
     * https://github.com/esmil/gd32vf103inator/blob/master/include/gd32vf103/dbg.h */
    *DBGMCU_KEY = DBGMCU_KEY_UNLOCK;
    *DBGMCU_CMD = DBGMCU_CMD_RESET;
}

void enter_bootloader_mode_if_requested(void) { /* Jumping to bootloader is not possible from user code. */
}

#elif defined(KL2x) || defined(K20x) || defined(MK66F18) || defined(MIMXRT1062)  // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS
/* Kinetis */


M tmk_core/common/chibios/chibios_config.h => tmk_core/common/chibios/chibios_config.h +19 -0
@@ 39,6 39,25 @@
#    endif
#endif

// GD32 compatibility
#if defined(MCU_GD32V)
#    define CPU_CLOCK GD32_SYSCLK

#    if defined(GD32VF103)
#        define USE_GPIOV1
#        define USE_I2CV1
#        define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_GD32_ALTERNATE_OPENDRAIN
#        define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_GD32_ALTERNATE_PUSHPULL
#    endif
#endif

#if defined(GD32VF103)
/* This chip has the same API as STM32F103, but uses different names for literally the same thing.
 * As of 4.7.2021 QMK is tailored to use STM32 defines/names, for compatibility sake
 * we just redefine the GD32 names. */
#    include "gd32v_compatibility.h"
#endif

// teensy compatibility
#if defined(MCU_KINETIS)
#    define CPU_CLOCK KINETIS_SYSCLK_FREQUENCY

M tmk_core/common/chibios/eeprom_stm32_defs.h => tmk_core/common/chibios/eeprom_stm32_defs.h +4 -2
@@ 18,7 18,7 @@
#include <hal.h>

#if !defined(FEE_PAGE_SIZE) || !defined(FEE_PAGE_COUNT)
#    if defined(STM32F103xB) || defined(STM32F042x6)
#    if defined(STM32F103xB) || defined(STM32F042x6) || defined(GD32VF103C8) || defined(GD32VF103CB)
#        ifndef FEE_PAGE_SIZE
#            define FEE_PAGE_SIZE 0x400  // Page size = 1KByte
#        endif


@@ 45,7 45,9 @@
#if !defined(FEE_MCU_FLASH_SIZE)
#    if defined(STM32F042x6)
#        define FEE_MCU_FLASH_SIZE 32  // Size in Kb
#    elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB)
#    elif defined(GD32VF103C8)
#        define FEE_MCU_FLASH_SIZE 64  // Size in Kb
#    elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB) || defined(GD32VF103CB)
#        define FEE_MCU_FLASH_SIZE 128  // Size in Kb
#    elif defined(STM32F303xC) || defined(STM32F401xC)
#        define FEE_MCU_FLASH_SIZE 256  // Size in Kb

M tmk_core/common/chibios/flash_stm32.c => tmk_core/common/chibios/flash_stm32.c +5 -0
@@ 23,6 23,11 @@
#    define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
#endif

#if defined(MCU_GD32V)
/* GigaDevice GD32VF103 is a STM32F103 clone at heart. */
#    include "gd32v_compatibility.h"
#endif

#if defined(STM32F4XX)
#    define FLASH_SR_PGERR (FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR)


A tmk_core/common/chibios/gd32v_compatibility.h => tmk_core/common/chibios/gd32v_compatibility.h +120 -0
@@ 0,0 1,120 @@
/* Copyright 2021 QMK
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

/* GD32VF103 has the same API as STM32F103, but uses different names for literally the same thing.
 * As of 23.7.2021 QMK is tailored to use STM32 defines/names, for compatibility sake
 * we just redefine the GD32 names. */

/* Close your eyes kids. */
#define MCU_STM32

/* AFIO redefines */
#define MAPR PCF0
#define AFIO_MAPR_USART1_REMAP AFIO_PCF0_USART0_REMAP
#define AFIO_MAPR_USART2_REMAP AFIO_PCF0_USART1_REMAP
#define AFIO_MAPR_USART3_REMAP_PARTIALREMAP AFIO_PCF0_USART2_REMAP_PARTIALREMAP
#define AFIO_MAPR_USART3_REMAP_FULLREMAP AFIO_PCF0_USART2_REMAP_FULLREMAP

/* DMA redefines. */
#define STM32_DMA_STREAM(stream) GD32_DMA_STREAM(stream)
#define STM32_DMA_STREAM_ID(peripheral, channel) GD32_DMA_STREAM_ID(peripheral - 1, channel - 1)
#define STM32_DMA_CR_DIR_M2P GD32_DMA_CTL_DIR_M2P
#define STM32_DMA_CR_PSIZE_WORD GD32_DMA_CTL_PWIDTH_WORD
#define STM32_DMA_CR_MSIZE_WORD GD32_DMA_CTL_MWIDTH_WORD
#define STM32_DMA_CR_MINC GD32_DMA_CTL_MNAGA
#define STM32_DMA_CR_CIRC GD32_DMA_CTL_CMEN
#define STM32_DMA_CR_PL GD32_DMA_CTL_PRIO
#define STM32_DMA_CR_CHSEL GD32_DMA_CTL_CHSEL
#define cr1 ctl0
#define cr2 ctl1
#define cr3 ctl2
#define dier dmainten

/* ADC redefines */
#if HAL_USE_ADC
#    define STM32_ADC_USE_ADC1 GD32_ADC_USE_ADC0

#    define smpr1 sampt0
#    define smpr2 sampt1
#    define sqr1 rsq0
#    define sqr2 rsq1
#    define sqr3 rsq2

#    define ADC_SMPR2_SMP_AN0 ADC_SAMPT1_SMP_SPT0
#    define ADC_SMPR2_SMP_AN1 ADC_SAMPT1_SMP_SPT1
#    define ADC_SMPR2_SMP_AN2 ADC_SAMPT1_SMP_SPT2
#    define ADC_SMPR2_SMP_AN3 ADC_SAMPT1_SMP_SPT3
#    define ADC_SMPR2_SMP_AN4 ADC_SAMPT1_SMP_SPT4
#    define ADC_SMPR2_SMP_AN5 ADC_SAMPT1_SMP_SPT5
#    define ADC_SMPR2_SMP_AN6 ADC_SAMPT1_SMP_SPT6
#    define ADC_SMPR2_SMP_AN7 ADC_SAMPT1_SMP_SPT7
#    define ADC_SMPR2_SMP_AN8 ADC_SAMPT1_SMP_SPT8
#    define ADC_SMPR2_SMP_AN9 ADC_SAMPT1_SMP_SPT9

#    define ADC_SMPR1_SMP_AN10 ADC_SAMPT0_SMP_SPT10
#    define ADC_SMPR1_SMP_AN11 ADC_SAMPT0_SMP_SPT11
#    define ADC_SMPR1_SMP_AN12 ADC_SAMPT0_SMP_SPT12
#    define ADC_SMPR1_SMP_AN13 ADC_SAMPT0_SMP_SPT13
#    define ADC_SMPR1_SMP_AN14 ADC_SAMPT0_SMP_SPT14
#    define ADC_SMPR1_SMP_AN15 ADC_SAMPT0_SMP_SPT15

#    define ADC_SQR3_SQ1_N ADC_RSQ2_RSQ1_N
#endif

/* FLASH redefines */
#if defined(EEPROM_ENABLE)
#    define SR STAT
#    define FLASH_SR_BSY FLASH_STAT_BUSY
#    define FLASH_SR_PGERR FLASH_STAT_PGERR
#    define FLASH_SR_EOP FLASH_STAT_ENDF
#    define FLASH_SR_WRPRTERR FLASH_STAT_WPERR
#    define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
#    define FLASH_OBR_OPTERR FLASH_OBSTAT_OBERR
#    define AR ADDR
#    define CR CTL
#    define FLASH_CR_PER FLASH_CTL_PER
#    define FLASH_CR_STRT FLASH_CTL_START
#    define FLASH_CR_LOCK FLASH_CTL_LK
#    define FLASH_CR_PG FLASH_CTL_PG
#    define KEYR KEY
#endif

/* Serial USART redefines. */
#if HAL_USE_SERIAL
#    if !defined(SERIAL_USART_CR1)
#        define SERIAL_USART_CR1 (USART_CTL0_PCEN | USART_CTL0_PM | USART_CTL0_WL)  // parity enable, odd parity, 9 bit length
#    endif
#    if !defined(SERIAL_USART_CR2)
#        define SERIAL_USART_CR2 (USART_CTL1_STB_1)  // 2 stop bits
#    endif
#    if !defined(SERIAL_USART_CR3)
#        define SERIAL_USART_CR3 0x0
#    endif
#    define USART_CR3_HDSEL USART_CTL2_HDEN
#    define CCR CHCV
#endif

/* SPI redefines. */
#if HAL_USE_SPI
#    define SPI_CR1_LSBFIRST SPI_CTL0_LF
#    define SPI_CR1_CPHA SPI_CTL0_CKPH
#    define SPI_CR1_CPOL SPI_CTL0_CKPL
#    define SPI_CR1_BR_0 SPI_CTL0_PSC_0
#    define SPI_CR1_BR_1 SPI_CTL0_PSC_1
#    define SPI_CR1_BR_2 SPI_CTL0_PSC_2
#endif

M tmk_core/common/chibios/syscall-fallbacks.c => tmk_core/common/chibios/syscall-fallbacks.c +6 -0
@@ 18,6 18,12 @@
#include <sys/stat.h>
#include <sys/types.h>

/* To compile the ChibiOS syscall stubs with picolibc
 * the _reent struct has to be defined. */
#if defined(USE_PICOLIBC)
struct _reent;
#endif

#pragma GCC diagnostic ignored "-Wmissing-prototypes"

__attribute__((weak, used)) int _open_r(struct _reent *r, const char *path, int flag, int m) {

M util/install/arch.sh => util/install/arch.sh +2 -1
@@ 6,7 6,8 @@ _qmk_install() {
    sudo pacman --needed  --noconfirm -S \
        base-devel clang diffutils gcc git unzip wget zip python-pip \
        avr-binutils arm-none-eabi-binutils arm-none-eabi-gcc \
        arm-none-eabi-newlib avrdude dfu-programmer dfu-util
        arm-none-eabi-newlib avrdude dfu-programmer dfu-util \
        riscv64-elf-binutils riscv64-elf-gcc riscv64-elf-newlib
    sudo pacman --needed --noconfirm -U https://archive.archlinux.org/packages/a/avr-gcc/avr-gcc-8.3.0-1-x86_64.pkg.tar.xz
    sudo pacman --needed --noconfirm -S avr-libc # Must be installed after the above, or it will bring in the latest avr-gcc instead


M util/install/debian.sh => util/install/debian.sh +2 -1
@@ 15,7 15,8 @@ _qmk_install() {
        build-essential clang-format diffutils gcc git unzip wget zip \
        python3-pip binutils-avr gcc-avr avr-libc binutils-arm-none-eabi \
        gcc-arm-none-eabi libnewlib-arm-none-eabi avrdude dfu-programmer \
        dfu-util teensy-loader-cli libhidapi-hidraw0 libusb-dev
        dfu-util teensy-loader-cli libhidapi-hidraw0 libusb-dev \
        picolibc-riscv64-unknown-elf gcc-riscv64-unknown-elf binutils-riscv64-unknown-elf

    python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt
}