39161b9ee793f4c62836b209ec877acda457b88d
- Author
- HorrorTroll <sonicvipduc@gmail.com>
- Committer
- GitHub <noreply@github.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk
2index f5b01de015d04de6f26bdaf9b17d0ee04a22f6c7..86ced30902916687e2274cf8dd61588283f57a36 100644
3--- a/builddefs/common_features.mk
4+++ b/builddefs/common_features.mk
5@@ -215,7 +215,7 @@ else
6 COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/flash
7 COMMON_VPATH += $(DRIVER_PATH)/flash
8 SRC += eeprom_driver.c eeprom_legacy_emulated_flash.c legacy_flash_ops.c
9- else ifneq ($(filter $(MCU_SERIES),STM32F1xx STM32F3xx STM32F4xx STM32L4xx STM32G4xx WB32F3G71xx WB32FQ95xx GD32VF103),)
10+ else ifneq ($(filter $(MCU_SERIES),STM32F1xx STM32F3xx STM32F4xx STM32L4xx STM32G4xx WB32F3G71xx WB32FQ95xx AT32F415 GD32VF103),)
11 # Wear-leveling EEPROM implementation, backed by MCU flash
12 OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_WEAR_LEVELING
13 SRC += eeprom_driver.c eeprom_wear_leveling.c
14diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema
15index 72a33f55ad156a85cb833e1c87aebd1265978e41..9f1f6dd74a58a03ad513642959bffb39e4924736 100644
16--- a/data/schemas/keyboard.jsonschema
17+++ b/data/schemas/keyboard.jsonschema
18@@ -92,6 +92,7 @@
19 "GD32VF103",
20 "WB32F3G71",
21 "WB32FQ95",
22+ "AT32F415",
23 "atmega16u2",
24 "atmega32u2",
25 "atmega16u4",
26@@ -216,6 +217,7 @@
27 "type": "string",
28 "enum": [
29 "apm32-dfu",
30+ "at32-dfu",
31 "atmel-dfu",
32 "bootloadhid",
33 "caterina",
34diff --git a/docs/compatible_microcontrollers.md b/docs/compatible_microcontrollers.md
35index e2d27e06f2f1de281fd38a72ff1b15063f498f4b..f148c39191e1d646dd337e514bffb0c212c9ad51 100644
36--- a/docs/compatible_microcontrollers.md
37+++ b/docs/compatible_microcontrollers.md
38@@ -57,6 +57,10 @@ You can also use any ARM chip with USB that [ChibiOS](https://www.chibios.org) s
39 * [WB32F3G71xx](http://www.westberrytech.com)
40 * [WB32FQ95xx](http://www.westberrytech.com)
41
42+### Artery (AT32)
43+
44+ * [AT32F415](https://www.arterychip.com/en/product/AT32F415.jsp)
45+
46 ### NXP (Kinetis)
47
48 * [MKL26Z64](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/kl-series-cortex-m0-plus/kinetis-kl2x-72-96-mhz-usb-ultra-low-power-microcontrollers-mcus-based-on-arm-cortex-m0-plus-core:KL2x)
49diff --git a/docs/driver_installation_zadig.md b/docs/driver_installation_zadig.md
50index 9743c0adc2fb0db5124bfc04dc22802e8c07d69e..1a5bd1cc3464d6f19ea68a2ffab431799be3b7aa 100644
51--- a/docs/driver_installation_zadig.md
52+++ b/docs/driver_installation_zadig.md
53@@ -98,6 +98,7 @@ The device name here is the name that appears in Zadig, and may not be what the
54 |`bootloadhid` |HIDBoot |`16C0:05DF` |HidUsb |
55 |`usbasploader`|USBasp |`16C0:05DC` |libusbK|
56 |`apm32-dfu` |APM32 DFU ISP Mode |`314B:0106` |WinUSB |
57+|`at32-dfu` |AT32 Bootloader DFU |`2E3C:DF11` |WinUSB |
58 |`stm32-dfu` |STM32 BOOTLOADER |`0483:DF11` |WinUSB |
59 |`gd32v-dfu` |GD32V BOOTLOADER |`28E9:0189` |WinUSB |
60 |`kiibohd` |Kiibohd DFU Bootloader |`1C11:B007` |WinUSB |
61diff --git a/docs/flashing.md b/docs/flashing.md
62index 2afb85886025214dbdd9a3a4331b4e3a2e813e9b..29dc780aaf035f6c5fc2d05257d81242b102109b 100644
63--- a/docs/flashing.md
64+++ b/docs/flashing.md
65@@ -345,6 +345,39 @@ Flashing sequence:
66 3. Flash a .bin file
67 4. Reset the device into application mode (may be done automatically)
68
69+## AT32 DFU
70+
71+All AT32 MCUs come preloaded with a factory bootloader that cannot be modified nor deleted.
72+
73+To ensure compatibility with the AT32-DFU bootloader, make sure this block is present in your `rules.mk`:
74+
75+```make
76+# Bootloader selection
77+BOOTLOADER = at32-dfu
78+```
79+
80+Compatible flashers:
81+
82+* [dfu-util](https://dfu-util.sourceforge.net/) / `:dfu-util` target in QMK (recommended command line)
83+ ```
84+ dfu-util -a 0 -d 2E3C:DF11 -s 0x8000000:leave -D <filename>
85+ ```
86+
87+Flashing sequence:
88+
89+1. Enter the bootloader using any of the following methods:
90+ * Tap the `QK_BOOT` keycode
91+ * If a reset circuit is present, tap the `RESET` button on the PCB; some boards may also have a toggle switch that must be flipped
92+ * Otherwise, you need to bridge `BOOT0` to VCC (via `BOOT0` button or jumper), short `RESET` to GND (via `RESET` button or jumper), and then let go of the `BOOT0` bridge
93+2. Wait for the OS to detect the device
94+3. Flash a .bin file
95+4. Reset the device into application mode (may be done automatically)
96+
97+### `make` Targets
98+
99+* `:dfu-util`: Waits until an AT32 bootloader device is available, and then flashes the firmware.
100+* `:dfu-util-split-left` and `:dfu-util-split-right`: Flashes the firmware as with `:dfu-util`, but also sets the handedness setting in EEPROM.
101+
102 ## tinyuf2
103
104 Keyboards may opt into supporting the tinyuf2 bootloader. This is currently only supported on F303/F401/F411.
105diff --git a/keyboards/handwired/onekey/at_start_f415/board.h b/keyboards/handwired/onekey/at_start_f415/board.h
106new file mode 100644
107index 0000000000000000000000000000000000000000..f4adc2d4183abf3ad8453b1e06d50118a4db63fb
108--- /dev/null
109+++ b/keyboards/handwired/onekey/at_start_f415/board.h
110@@ -0,0 +1,10 @@
111+// Copyright 2023-2024 HorrorTroll <https://github.com/HorrorTroll>
112+// Copyright 2023-2024 Zhaqian <https://github.com/zhaqian12>
113+// SPDX-License-Identifier: GPL-2.0-or-later
114+
115+#pragma once
116+
117+#include_next <board.h>
118+
119+#undef AT32F415KB
120+#define AT32F415RC
121diff --git a/keyboards/handwired/onekey/at_start_f415/config.h b/keyboards/handwired/onekey/at_start_f415/config.h
122new file mode 100644
123index 0000000000000000000000000000000000000000..266e45dd0046361debba946bdbeafbf618bda8a1
124--- /dev/null
125+++ b/keyboards/handwired/onekey/at_start_f415/config.h
126@@ -0,0 +1,10 @@
127+// Copyright 2023-2024 HorrorTroll <https://github.com/HorrorTroll>
128+// Copyright 2023-2024 Zhaqian <https://github.com/zhaqian12>
129+// SPDX-License-Identifier: GPL-2.0-or-later
130+
131+#pragma once
132+
133+#define ADC_PIN A0
134+
135+#define BACKLIGHT_PWM_DRIVER PWMD5
136+#define BACKLIGHT_PWM_CHANNEL 1
137diff --git a/keyboards/handwired/onekey/at_start_f415/halconf.h b/keyboards/handwired/onekey/at_start_f415/halconf.h
138new file mode 100644
139index 0000000000000000000000000000000000000000..1423633d15fc75a045a787dfd27647e65b04e214
140--- /dev/null
141+++ b/keyboards/handwired/onekey/at_start_f415/halconf.h
142@@ -0,0 +1,13 @@
143+// Copyright 2023-2024 HorrorTroll <https://github.com/HorrorTroll>
144+// Copyright 2023-2024 Zhaqian <https://github.com/zhaqian12>
145+// SPDX-License-Identifier: GPL-2.0-or-later
146+
147+#pragma once
148+
149+#define HAL_USE_ADC TRUE
150+
151+#define HAL_USE_I2C TRUE
152+
153+#define HAL_USE_PWM TRUE
154+
155+#include_next <halconf.h>
156diff --git a/keyboards/handwired/onekey/at_start_f415/keyboard.json b/keyboards/handwired/onekey/at_start_f415/keyboard.json
157new file mode 100644
158index 0000000000000000000000000000000000000000..f598923a6a55fb6fcdf8128f1b453c59946640a3
159--- /dev/null
160+++ b/keyboards/handwired/onekey/at_start_f415/keyboard.json
161@@ -0,0 +1,20 @@
162+{
163+ "keyboard_name": "Onekey AT-START-F415",
164+ "processor": "AT32F415",
165+ "bootloader": "at32-dfu",
166+ "usb": {
167+ "shared_endpoint": {
168+ "keyboard": true
169+ }
170+ },
171+ "matrix_pins": {
172+ "cols": ["B3"],
173+ "rows": ["B4"]
174+ },
175+ "backlight": {
176+ "pin": "A0"
177+ },
178+ "ws2812": {
179+ "pin": "B0"
180+ }
181+}
182diff --git a/keyboards/handwired/onekey/at_start_f415/mcuconf.h b/keyboards/handwired/onekey/at_start_f415/mcuconf.h
183new file mode 100644
184index 0000000000000000000000000000000000000000..9bc11d507cce9b5d612b66518ecedffbb3ad5c37
185--- /dev/null
186+++ b/keyboards/handwired/onekey/at_start_f415/mcuconf.h
187@@ -0,0 +1,16 @@
188+// Copyright 2023-2024 HorrorTroll <https://github.com/HorrorTroll>
189+// Copyright 2023-2024 Zhaqian <https://github.com/zhaqian12>
190+// SPDX-License-Identifier: GPL-2.0-or-later
191+
192+#pragma once
193+
194+#include_next <mcuconf.h>
195+
196+#undef AT32_ADC_USE_ADC1
197+#define AT32_ADC_USE_ADC1 TRUE
198+
199+#undef AT32_I2C_USE_I2C1
200+#define AT32_I2C_USE_I2C1 TRUE
201+
202+#undef AT32_PWM_USE_TMR5
203+#define AT32_PWM_USE_TMR5 TRUE
204diff --git a/keyboards/handwired/onekey/at_start_f415/readme.md b/keyboards/handwired/onekey/at_start_f415/readme.md
205new file mode 100644
206index 0000000000000000000000000000000000000000..499ef5fb1695ccfb01452e95260fc85f8af8136f
207--- /dev/null
208+++ b/keyboards/handwired/onekey/at_start_f415/readme.md
209@@ -0,0 +1,3 @@
210+# Artery AT-START-F415 Board Onekey
211+
212+To trigger keypress, short together pins *B3* and *B4*.
213diff --git a/lib/python/qmk/constants.py b/lib/python/qmk/constants.py
214index b6f46180b29840180a698557c50d1d35a7955acb..e055d3fbc95e99a08a8761c53c0c32f8765856d6 100644
215--- a/lib/python/qmk/constants.py
216+++ b/lib/python/qmk/constants.py
217@@ -22,7 +22,7 @@ QMK_FIRMWARE_UPSTREAM = 'qmk/qmk_firmware'
218 MAX_KEYBOARD_SUBFOLDERS = 5
219
220 # Supported processor types
221diff --git a/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.c b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.c
222new file mode 100644
223index 0000000000000000000000000000000000000000..28cf7c18e0164bda5d5e00ee3369c907ee49cb9c
224--- /dev/null
225+++ b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.c
226@@ -0,0 +1,101 @@
227+/*
228+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
229+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
230+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
231+
232+ Licensed under the Apache License, Version 2.0 (the "License");
233+ you may not use this file except in compliance with the License.
234+ You may obtain a copy of the License at
235+
236+ http://www.apache.org/licenses/LICENSE-2.0
237+
238+ Unless required by applicable law or agreed to in writing, software
239+ distributed under the License is distributed on an "AS IS" BASIS,
240+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
241+ See the License for the specific language governing permissions and
242+ limitations under the License.
243+*/
244+
245+#include "hal.h"
246+
247+/*===========================================================================*/
248+/* Driver local definitions. */
249+/*===========================================================================*/
250+
251+/*===========================================================================*/
252+/* Driver exported variables. */
253+/*===========================================================================*/
254+
255+/*===========================================================================*/
256+/* Driver local variables and types. */
257+/*===========================================================================*/
258+
259+/**
260+ * @brief PAL setup.
261+ * @details Digital I/O ports static configuration as defined in @p board.h.
262+ * This variable is used by the HAL when initializing the PAL driver.
263+ */
264+#if HAL_USE_PAL || defined(__DOXYGEN__)
265+const PALConfig pal_default_config =
266+{
267+ {VAL_GPIOAODT, VAL_GPIOACFGLR, VAL_GPIOACFGHR},
268+ {VAL_GPIOBODT, VAL_GPIOBCFGLR, VAL_GPIOBCFGHR},
269+#if AT32_HAS_GPIOC
270+ {VAL_GPIOCODT, VAL_GPIOCCFGLR, VAL_GPIOCCFGHR},
271+#endif
272+ {VAL_GPIODODT, VAL_GPIODCFGLR, VAL_GPIODCFGHR},
273+#if AT32_HAS_GPIOF
274+ {VAL_GPIOFODT, VAL_GPIOFCFGLR, VAL_GPIOFCFGHR},
275+#endif
276+};
277+#endif
278+
279+/*===========================================================================*/
280+/* Driver local functions. */
281+/*===========================================================================*/
282+
283+/*===========================================================================*/
284+/* Driver interrupt handlers. */
285+/*===========================================================================*/
286+
287+/*===========================================================================*/
288+/* Driver exported functions. */
289+/*===========================================================================*/
290+
291+/**
292+ * @brief Early initialization code.
293+ * @details System clocks are initialized before everything else.
294+ */
295+void __early_init(void) {
296+ at32_clock_init();
297+}
298+
299+#if HAL_USE_SDC || defined(__DOXYGEN__)
300+/**
301+ * @brief SDC card detection.
302+ */
303+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
304+ static bool last_status = false;
305+
306+ if (blkIsTransferring(sdcp))
307+ return last_status;
308+ return last_status = (bool)palReadPad(GPIOC, GPIOC_PIN11);
309+}
310+
311+/**
312+ * @brief SDC card write protection detection.
313+ */
314+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
315+
316+ (void)sdcp;
317+ return false;
318+}
319+#endif /* HAL_USE_SDC */
320+
321+/**
322+ * @brief Board-specific initialization code.
323+ * @note You can add your board-specific code here.
324+ */
325+void boardInit(void) {
326diff --git a/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.h b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.h
327new file mode 100644
328index 0000000000000000000000000000000000000000..c3ade198bae5f7bc2b4040d0b10ec11736c37bd1
329--- /dev/null
330+++ b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.h
331@@ -0,0 +1,207 @@
332+/*
333+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
334+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
335+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
336+
337+ Licensed under the Apache License, Version 2.0 (the "License");
338+ you may not use this file except in compliance with the License.
339+ You may obtain a copy of the License at
340+
341+ http://www.apache.org/licenses/LICENSE-2.0
342+
343+ Unless required by applicable law or agreed to in writing, software
344+ distributed under the License is distributed on an "AS IS" BASIS,
345+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
346+ See the License for the specific language governing permissions and
347+ limitations under the License.
348+*/
349+
350+#ifndef _BOARD_H_
351+#define _BOARD_H_
352+
353+/*===========================================================================*/
354+/* Driver constants. */
355+/*===========================================================================*/
356+
357+/*
358+ * Setup for a Generic AT32F415 board.
359+ */
360+
361+/*
362+ * Board identifier.
363+ */
364+#define BOARD_GENERIC_AT32_F415XX
365+#define BOARD_NAME "GENERIC AT32F415 board"
366+
367+/*
368+ * Board oscillators-related settings.
369+ */
370+#if !defined(AT32_LEXTCLK)
371+#define AT32_LEXTCLK 32768
372+#endif
373+
374+#if !defined(AT32_HEXTCLK)
375+#define AT32_HEXTCLK 8000000
376+#endif
377+
378+/*
379+ * MCU type, supported types are defined in ./os/hal/platforms/hal_lld.h.
380+ */
381+#define AT32F415KB
382+
383+/*
384+ * IO pins assignments.
385+ */
386+#define GPIOA_PIN0 0U
387+#define GPIOA_PIN1 1U
388+#define GPIOA_PIN2 2U
389+#define GPIOA_PIN3 3U
390+#define GPIOA_PIN4 4U
391+#define GPIOA_PIN5 5U
392+#define GPIOA_PIN6 6U
393+#define GPIOA_PIN7 7U
394+#define GPIOA_PIN8 8U
395+#define GPIOA_PIN9 9U
396+#define GPIOA_PIN10 10U
397+#define GPIOA_PIN11 11U
398+#define GPIOA_PIN12 12U
399+#define GPIOA_SWDIO 13U
400+#define GPIOA_SWCLK 14U
401+#define GPIOA_PIN15 15U
402+
403+#define GPIOB_PIN0 0U
404+#define GPIOB_PIN1 1U
405+#define GPIOB_PIN2 2U
406+#define GPIOB_PIN3 3U
407+#define GPIOB_PIN4 4U
408+#define GPIOB_PIN5 5U
409+#define GPIOB_PIN6 6U
410+#define GPIOB_PIN7 7U
411+#define GPIOB_PIN8 8U
412+#define GPIOB_PIN9 9U
413+#define GPIOB_PIN10 10U
414+#define GPIOB_PIN11 11U
415+#define GPIOB_PIN12 12U
416+#define GPIOB_PIN13 13U
417+#define GPIOB_PIN14 14U
418+#define GPIOB_PIN15 15U
419+
420+#define GPIOC_PIN0 0U
421+#define GPIOC_PIN1 1U
422+#define GPIOC_PIN2 2U
423+#define GPIOC_PIN3 3U
424+#define GPIOC_PIN4 4U
425+#define GPIOC_PIN5 5U
426+#define GPIOC_PIN6 6U
427+#define GPIOC_PIN7 7U
428+#define GPIOC_PIN8 8U
429+#define GPIOC_PIN9 9U
430+#define GPIOC_PIN10 10U
431diff --git a/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.mk b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.mk
432new file mode 100644
433index 0000000000000000000000000000000000000000..842e33590594b7c78ccf1ef5205aec6860e4ea94
434--- /dev/null
435+++ b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.mk
436@@ -0,0 +1,9 @@
437+# List of all the board related files.
438+BOARDSRC = $(BOARD_PATH)/board/board.c
439+
440+# Required include directories
441+BOARDINC = $(BOARD_PATH)/board
442+
443+# Shared variables
444+ALLCSRC += $(BOARDSRC)
445+ALLINC += $(BOARDINC)
446diff --git a/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/config.h b/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/config.h
447new file mode 100644
448index 0000000000000000000000000000000000000000..da60447a0af0598685562bd0a4ae805ff8076d10
449--- /dev/null
450+++ b/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/config.h
451@@ -0,0 +1,13 @@
452+// Copyright 2023-2024 HorrorTroll <https://github.com/HorrorTroll>
453+// Copyright 2023-2024 Zhaqian <https://github.com/zhaqian12>
454+// SPDX-License-Identifier: GPL-2.0-or-later
455+
456+#pragma once
457+
458+#define BOARD_OTG_VBUSIG
459+
460+#define USB_ENDPOINTS_ARE_REORDERABLE
461+
462+#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
463+# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE
464+#endif
465diff --git a/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/mcuconf.h
466new file mode 100644
467index 0000000000000000000000000000000000000000..d148379fe1dbdc538607acf79a40ffa6efc0050b
468--- /dev/null
469+++ b/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/mcuconf.h
470@@ -0,0 +1,236 @@
471+/*
472+ ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
473+ ChibiOS - Copyright (C) 2023..2024 HorrorTroll
474+ ChibiOS - Copyright (C) 2023..2024 Zhaqian
475+
476+ Licensed under the Apache License, Version 2.0 (the "License");
477+ you may not use this file except in compliance with the License.
478+ You may obtain a copy of the License at
479+
480+ http://www.apache.org/licenses/LICENSE-2.0
481+
482+ Unless required by applicable law or agreed to in writing, software
483+ distributed under the License is distributed on an "AS IS" BASIS,
484+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
485+ See the License for the specific language governing permissions and
486+ limitations under the License.
487+*/
488+
489+#ifndef MCUCONF_H
490+#define MCUCONF_H
491+
492+/*
493+ * AT32F415 drivers configuration.
494+ * The following settings override the default settings present in
495+ * the various device driver implementation headers.
496+ * Note that the settings for each driver only have effect if the whole
497+ * driver is enabled in halconf.h.
498+ *
499+ * IRQ priorities:
500+ * 15...0 Lowest...Highest.
501+ *
502+ * DMA priorities:
503+ * 0...3 Lowest...Highest.
504+ */
505+
506+#define AT32F415_MCUCONF
507+
508+/*
509+ * General settings.
510+ */
511+#define AT32_NO_INIT FALSE
512+
513+/*
514+ * HAL driver system settings.
515+ */
516+#define AT32_HICK_ENABLED TRUE
517+#define AT32_LICK_ENABLED FALSE
518+#define AT32_HEXT_ENABLED TRUE
519+#define AT32_LEXT_ENABLED FALSE
520+#define AT32_SCLKSEL AT32_SCLKSEL_PLL
521+#define AT32_PLLRCS AT32_PLLRCS_HEXT
522+#define AT32_PLLHEXTDIV AT32_PLLHEXTDIV_DIV1
523+#define AT32_PLLCFGEN AT32_PLLCFGEN_SOLID
524+#define AT32_PLLMULT_VALUE 18
525+#define AT32_PLL_FR_VALUE 4
526+#define AT32_PLL_MS_VALUE 1
527+#define AT32_PLL_NS_VALUE 72
528+#define AT32_AHBDIV AT32_AHBDIV_DIV1
529+#define AT32_APB1DIV AT32_APB1DIV_DIV2
530+#define AT32_APB2DIV AT32_APB2DIV_DIV2
531+#define AT32_ADCDIV AT32_ADCDIV_DIV4
532+#define AT32_USB_CLOCK_REQUIRED TRUE
533+#define AT32_USBDIV AT32_USBDIV_DIV3
534+#define AT32_CLKOUT_SEL AT32_CLKOUT_SEL_NOCLOCK
535+#define AT32_CLKOUTDIV AT32_CLKOUTDIV_DIV1
536+#define AT32_ERTCSEL AT32_ERTCSEL_HEXTDIV
537+#define AT32_PVM_ENABLE FALSE
538+#define AT32_PVMSEL AT32_PVMSEL_LEV1
539+
540+/*
541+ * IRQ system settings.
542+ */
543+#define AT32_IRQ_EXINT0_PRIORITY 6
544+#define AT32_IRQ_EXINT1_PRIORITY 6
545+#define AT32_IRQ_EXINT2_PRIORITY 6
546+#define AT32_IRQ_EXINT3_PRIORITY 6
547+#define AT32_IRQ_EXINT4_PRIORITY 6
548+#define AT32_IRQ_EXINT5_9_PRIORITY 6
549+#define AT32_IRQ_EXINT10_15_PRIORITY 6
550+#define AT32_IRQ_EXINT16_PRIORITY 6
551+#define AT32_IRQ_EXINT17_PRIORITY 15
552+#define AT32_IRQ_EXINT18_PRIORITY 6
553+#define AT32_IRQ_EXINT19_PRIORITY 6
554+#define AT32_IRQ_EXINT20_PRIORITY 6
555+#define AT32_IRQ_EXINT21_PRIORITY 15
556+#define AT32_IRQ_EXINT22_PRIORITY 15
557+
558+#define AT32_IRQ_TMR1_BRK_TMR9_PRIORITY 7
559+#define AT32_IRQ_TMR1_OVF_TMR10_PRIORITY 7
560+#define AT32_IRQ_TMR1_HALL_TMR11_PRIORITY 7
561+#define AT32_IRQ_TMR1_CH_PRIORITY 7
562+#define AT32_IRQ_TMR2_PRIORITY 7
563+#define AT32_IRQ_TMR3_PRIORITY 7
564+#define AT32_IRQ_TMR4_PRIORITY 7
565+#define AT32_IRQ_TMR5_PRIORITY 7
566+
567+#define AT32_IRQ_USART1_PRIORITY 12
568+#define AT32_IRQ_USART2_PRIORITY 12
569+#define AT32_IRQ_USART3_PRIORITY 12
570diff --git a/platforms/chibios/bootloader.mk b/platforms/chibios/bootloader.mk
571index 5b6edd73ad343edc81522485b9e2aaf0ecffce82..e292e1e0b08b50ae66422992291990bf6b30fec2 100644
572--- a/platforms/chibios/bootloader.mk
573+++ b/platforms/chibios/bootloader.mk
574@@ -26,6 +26,7 @@
575 # stm32-dfu STM32 USB DFU in ROM
576 # apm32-dfu APM32 USB DFU in ROM
577 # wb32-dfu WB32 USB DFU in ROM
578+# at32-dfu AT32 USB DFU in ROM
579 # tinyuf2 TinyUF2
580 # rp2040 Raspberry Pi RP2040
581 # Current options for RISC-V:
582@@ -119,6 +120,14 @@ ifeq ($(strip $(BOOTLOADER)), wb32-dfu)
583 OPT_DEFS += -DBOOTLOADER_WB32_DFU
584 BOOTLOADER_TYPE = wb32_dfu
585 endif
586+ifeq ($(strip $(BOOTLOADER)), at32-dfu)
587+ OPT_DEFS += -DBOOTLOADER_AT32_DFU
588+ BOOTLOADER_TYPE = at32_dfu
589+
590+ # Options to pass to dfu-util when flashing
591+ DFU_ARGS ?= -d 2E3C:DF11 -a 0 -s 0x08000000:leave
592+ DFU_SUFFIX_ARGS ?= -v 2E3C -p DF11
593+endif
594
595 ifeq ($(strip $(BOOTLOADER_TYPE)),)
596 ifneq ($(strip $(BOOTLOADER)),)
597diff --git a/platforms/chibios/bootloaders/at32_dfu.c b/platforms/chibios/bootloaders/at32_dfu.c
598new file mode 100644
599index 0000000000000000000000000000000000000000..f3a453d0fce89d489a762121d46df3a37d70ddd5
600--- /dev/null
601+++ b/platforms/chibios/bootloaders/at32_dfu.c
602@@ -0,0 +1,83 @@
603+// Copyright 2021-2023 QMK
604+// Copyright 2023-2024 HorrorTroll <https://github.com/HorrorTroll>
605+// Copyright 2023-2024 Zhaqian <https://github.com/zhaqian12>
606+// SPDX-License-Identifier: GPL-2.0-or-later
607+
608+#include "bootloader.h"
609+#include "util.h"
610+
611+#include <ch.h>
612+#include <hal.h>
613+#include "wait.h"
614+
615+#ifndef AT32_BOOTLOADER_RAM_SYMBOL
616+# define AT32_BOOTLOADER_RAM_SYMBOL __ram0_end__
617+#endif
618+
619+extern uint32_t AT32_BOOTLOADER_RAM_SYMBOL;
620+
621+/* This code should be checked whether it runs correctly on platforms */
622+#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
623+#define BOOTLOADER_MAGIC 0xDEADBEEF
624+#define MAGIC_ADDR (unsigned long *)(SYMVAL(AT32_BOOTLOADER_RAM_SYMBOL) - 4)
625+
626+__attribute__((weak)) void bootloader_marker_enable(void) {
627+ uint32_t *marker = (uint32_t *)MAGIC_ADDR;
628+ *marker = BOOTLOADER_MAGIC; // set magic flag => reset handler will jump into boot loader
629+}
630+
631+__attribute__((weak)) bool bootloader_marker_active(void) {
632+ const uint32_t *marker = (const uint32_t *)MAGIC_ADDR;
633+ return (*marker == BOOTLOADER_MAGIC) ? true : false;
634+}
635+
636+__attribute__((weak)) void bootloader_marker_disable(void) {
637+ uint32_t *marker = (uint32_t *)MAGIC_ADDR;
638+ *marker = 0;
639+}
640+
641+__attribute__((weak)) void bootloader_jump(void) {
642+ bootloader_marker_enable();
643+ NVIC_SystemReset();
644+}
645+
646+__attribute__((weak)) void mcu_reset(void) {
647+ NVIC_SystemReset();
648+}
649+
650+void enter_bootloader_mode_if_requested(void) {
651+ if (bootloader_marker_active()) {
652+ bootloader_marker_disable();
653+
654+ struct system_memory_vector_t {
655+ uint32_t stack_top;
656+ void (*entrypoint)(void);
657+ };
658+ const struct system_memory_vector_t *bootloader = (const struct system_memory_vector_t *)(AT32_BOOTLOADER_ADDRESS);
659+
660+ __disable_irq();
661+
662+#if defined(__MPU_PRESENT) && (__MPU_PRESENT == 1U)
663+ ARM_MPU_Disable();
664+#endif
665+
666+ SysTick->CTRL = 0;
667+ SysTick->VAL = 0;
668+ SysTick->LOAD = 0;
669+
670+ // Clear interrupt enable and interrupt pending registers
671+ for (int i = 0; i < ARRAY_SIZE(NVIC->ICER); i++) {
672+ NVIC->ICER[i] = 0xFFFFFFFF;
673+ NVIC->ICPR[i] = 0xFFFFFFFF;
674+ }
675+
676+ __set_CONTROL(0);
677+ __set_MSP(bootloader->stack_top);
678+ __enable_irq();
679+
680+ // Jump to bootloader
681+ bootloader->entrypoint();
682+ while (true) {
683+ }
684+ }
685+}
686diff --git a/platforms/chibios/chibios_config.h b/platforms/chibios/chibios_config.h
687index 8f46fe0736080798e18e5186f06a759b8db56f71..95136baf30324dd2e9c697d1f39446434a1335e5 100644
688--- a/platforms/chibios/chibios_config.h
689+++ b/platforms/chibios/chibios_config.h
690@@ -142,6 +142,19 @@
691 # endif
692 #endif
693
694+// AT32 compatibility
695+#if defined(MCU_AT32)
696+# define CPU_CLOCK AT32_SYSCLK
697+
698+# if defined(AT32F415)
699+# define USE_GPIOV1
700+# define USE_I2CV1
701+# define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_AT32_ALTERNATE_OPENDRAIN
702+# define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_AT32_ALTERNATE_PUSHPULL
703+# define AUDIO_PWM_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
704+# endif
705+#endif
706+
707 #if defined(GD32VF103)
708 /* This chip has the same API as STM32F103, but uses different names for literally the same thing.
709 * As of 4.7.2021 QMK is tailored to use STM32 defines/names, for compatibility sake
710diff --git a/platforms/chibios/drivers/analog.c b/platforms/chibios/drivers/analog.c
711index fb146df9367a9e609d5e7c0c733d8ccbbbf4c0a3..7e1f87e6c95e3937bb6a5b66e7bd750a9bebb217 100644
712--- a/platforms/chibios/drivers/analog.c
713+++ b/platforms/chibios/drivers/analog.c
714@@ -22,7 +22,7 @@
715 # error "You need to set HAL_USE_ADC to TRUE in your halconf.h to use the ADC."
716 #endif
717
718-#if !RP_ADC_USE_ADC1 && !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3 && !STM32_ADC_USE_ADC4 && !WB32_ADC_USE_ADC1
719+#if !RP_ADC_USE_ADC1 && !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3 && !STM32_ADC_USE_ADC4 && !WB32_ADC_USE_ADC1 && !AT32_ADC_USE_ADC1
720 # error "You need to set one of the 'xxx_ADC_USE_ADCx' settings to TRUE in your mcuconf.h to use the ADC."
721 #endif
722
723@@ -45,7 +45,7 @@
724 // Otherwise assume V3
725 #if defined(STM32F0XX) || defined(STM32L0XX)
726 # define USE_ADCV1
727-#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx)
728+#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) || defined(AT32F415)
729 # define USE_ADCV2
730 #endif
731
732@@ -82,7 +82,7 @@
733
734 /* User configurable ADC options */
735 #ifndef ADC_COUNT
736-# if defined(RP2040) || defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx)
737+# if defined(RP2040) || defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) || defined(AT32F415)
738 # define ADC_COUNT 1
739 # elif defined(STM32F3XX) || defined(STM32G4XX)
740 # define ADC_COUNT 4
741@@ -142,11 +142,16 @@ static ADCConversionGroup adcConversionGroup = {
742 .cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION,
743 .smpr = ADC_SAMPLING_RATE,
744 #elif defined(USE_ADCV2)
745-# if !defined(STM32F1XX) && !defined(GD32VF103) && !defined(WB32F3G71xx) && !defined(WB32FQ95xx)
746- .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without...
747+# if !defined(STM32F1XX) && !defined(GD32VF103) && !defined(WB32F3G71xx) && !defined(WB32FQ95xx) && !defined(AT32F415)
748+ .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without...
749 # endif
750+# if defined(AT32F415)
751diff --git a/platforms/chibios/drivers/serial_usart.c b/platforms/chibios/drivers/serial_usart.c
752index 767ef8726fc3668a9a5eb9f95454f2a5a51d17ea..becf3afbce1ea7412dc413e8aca02622e2aaceef 100644
753--- a/platforms/chibios/drivers/serial_usart.c
754+++ b/platforms/chibios/drivers/serial_usart.c
755@@ -9,6 +9,17 @@
756
757 #if defined(SERIAL_USART_CONFIG)
758 static QMKSerialConfig serial_config = SERIAL_USART_CONFIG;
759+#elif defined(MCU_AT32) /* AT32 MCUs */
760+static QMKSerialConfig serial_config = {
761+ .speed = (SERIAL_USART_SPEED),
762+ .ctrl1 = (SERIAL_USART_CTRL1),
763+ .ctrl2 = (SERIAL_USART_CTRL2),
764+# if !defined(SERIAL_USART_FULL_DUPLEX)
765+ .ctrl3 = ((SERIAL_USART_CTRL3) | USART_CTRL3_SLBEN) /* activate half-duplex mode */
766+# else
767+ .ctrl3 = (SERIAL_USART_CTRL3)
768+# endif
769+};
770 #elif defined(MCU_STM32) /* STM32 MCUs */
771 static QMKSerialConfig serial_config = {
772 # if HAL_USE_SERIAL
773@@ -160,7 +171,7 @@ inline bool serial_transport_receive_blocking(uint8_t* destination, const size_t
774 * @brief Initiate pins for USART peripheral. Half-duplex configuration.
775 */
776 __attribute__((weak)) void usart_init(void) {
777-# if defined(MCU_STM32) /* STM32 MCUs */
778+# if defined(MCU_STM32) || defined(MCU_AT32) /* STM32 and AT32 MCUs */
779 # if defined(USE_GPIOV1)
780 palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE_OPENDRAIN);
781 # else
782@@ -183,7 +194,7 @@ __attribute__((weak)) void usart_init(void) {
783 * @brief Initiate pins for USART peripheral. Full-duplex configuration.
784 */
785 __attribute__((weak)) void usart_init(void) {
786-# if defined(MCU_STM32) /* STM32 MCUs */
787+# if defined(MCU_STM32) || defined(MCU_AT32) /* STM32 and AT32 MCUs */
788 # if defined(USE_GPIOV1)
789 palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE_PUSHPULL);
790 palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_INPUT);
791diff --git a/platforms/chibios/drivers/serial_usart.h b/platforms/chibios/drivers/serial_usart.h
792index dec8a292e98b707e8938fb8dcd77381a4df7c5c1..dbd7673273f0cff7902d1bbaae3dc4c7a586bedc 100644
793--- a/platforms/chibios/drivers/serial_usart.h
794+++ b/platforms/chibios/drivers/serial_usart.h
795@@ -74,40 +74,75 @@ typedef SIOConfig QMKSerialConfig;
796 # endif
797 #endif
798
799-#if !defined(USART_CR1_M0)
800-# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so
801-#endif
802+#if defined(MCU_STM32) /* STM32 MCUs */
803+# if !defined(USART_CR1_M0)
804+# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so
805+# endif
806
807-#if !defined(SERIAL_USART_CR1)
808-# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length
809-#endif
810+# if !defined(SERIAL_USART_CR1)
811+# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length
812+# endif
813
814-#if !defined(SERIAL_USART_CR2)
815-# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits
816-#endif
817+# if !defined(SERIAL_USART_CR2)
818+# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits
819+# endif
820
821-#if !defined(SERIAL_USART_CR3)
822-# define SERIAL_USART_CR3 0
823-#endif
824+# if !defined(SERIAL_USART_CR3)
825+# define SERIAL_USART_CR3 0
826+# endif
827+
828+# if defined(USART1_REMAP)
829+# define USART_REMAP \
830+ do { \
831+ (AFIO->MAPR |= AFIO_MAPR_USART1_REMAP); \
832+ } while (0)
833+# elif defined(USART2_REMAP)
834+# define USART_REMAP \
835+ do { \
836+ (AFIO->MAPR |= AFIO_MAPR_USART2_REMAP); \
837+ } while (0)
838+# elif defined(USART3_PARTIALREMAP)
839+# define USART_REMAP \
840+ do { \
841+ (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP); \
842+ } while (0)
843+# elif defined(USART3_FULLREMAP)
844+# define USART_REMAP \
845+ do { \
846+ (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); \
847+ } while (0)
848+# endif
849+#elif defined(MCU_AT32) /* AT32 MCUs */
850+# if !defined(USART_CTRL1_DBN0)
851+# define USART_CTRL1_DBN0 USART_CTRL1_DBN
852+# endif
853
854-#if defined(USART1_REMAP)
855-# define USART_REMAP \
856- do { \
857- (AFIO->MAPR |= AFIO_MAPR_USART1_REMAP); \
858- } while (0)
859-#elif defined(USART2_REMAP)
860-# define USART_REMAP \
861- do { \
862- (AFIO->MAPR |= AFIO_MAPR_USART2_REMAP); \
863- } while (0)
864-#elif defined(USART3_PARTIALREMAP)
865-# define USART_REMAP \
866- do { \
867- (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP); \
868- } while (0)
869-#elif defined(USART3_FULLREMAP)
870-# define USART_REMAP \
871- do { \
872- (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); \
873- } while (0)
874+# if !defined(SERIAL_USART_CTRL1)
875+# define SERIAL_USART_CTRL1 (USART_CTRL1_PEN | USART_CTRL1_PSEL | USART_CTRL1_DBN0) // parity enable, odd parity, 9 bit length
876+# endif
877+
878+# if !defined(SERIAL_USART_CTRL2)
879+# define SERIAL_USART_CTRL2 (USART_CTRL2_STOPBN_1) // 2 stop bits
880+# endif
881+
882+# if !defined(SERIAL_USART_CTRL3)
883+# define SERIAL_USART_CTRL3 0
884+# endif
885+
886+# if defined(USART1_REMAP)
887+# define USART_REMAP \
888+ do { \
889+ (IOMUX->REMAP |= IOMUX_REMAP_USART1_MUX); \
890+ } while (0)
891+# elif defined(USART3_PARTIALREMAP)
892+# define USART_REMAP \
893+ do { \
894+ (IOMUX->REMAP |= IOMUX_REMAP_USART3_MUX_MUX1); \
895diff --git a/platforms/chibios/drivers/spi_master.c b/platforms/chibios/drivers/spi_master.c
896index cbe765e233d767decd22239bd0fb5d176e108dac..6417b7077f540a246363ad36b4148ea137eed794 100644
897--- a/platforms/chibios/drivers/spi_master.c
898+++ b/platforms/chibios/drivers/spi_master.c
899@@ -103,9 +103,15 @@ bool spi_start_extended(spi_start_config_t *start_config) {
900 roundedDivisor <<= 1;
901 }
902
903+# if defined(AT32F415)
904+ if (roundedDivisor < 2 || roundedDivisor > 1024) {
905+ return false;
906+ }
907+# else
908 if (roundedDivisor < 2 || roundedDivisor > 256) {
909 return false;
910 }
911+# endif
912 #endif
913
914 #if defined(K20x) || defined(KL2x)
915@@ -240,6 +246,59 @@ bool spi_start_extended(spi_start_config_t *start_config) {
916 spiConfig.SSPCR0 |= SPI_SSPCR0_SPH; // Clock phase: sample on second edge transition
917 break;
918 }
919+#elif defined(AT32F415)
920+ spiConfig.ctrl1 = 0;
921+
922+ if (lsbFirst) {
923+ spiConfig.ctrl1 |= SPI_CTRL1_LTF;
924+ }
925+
926+ switch (mode) {
927+ case 0:
928+ break;
929+ case 1:
930+ spiConfig.ctrl1 |= SPI_CTRL1_CLKPHA;
931+ break;
932+ case 2:
933+ spiConfig.ctrl1 |= SPI_CTRL1_CLKPOL;
934+ break;
935+ case 3:
936+ spiConfig.ctrl1 |= SPI_CTRL1_CLKPHA | SPI_CTRL1_CLKPOL;
937+ break;
938+ }
939+
940+ switch (roundedDivisor) {
941+ case 2:
942+ break;
943+ case 4:
944+ spiConfig.ctrl1 |= SPI_CTRL1_MDIV_0;
945+ break;
946+ case 8:
947+ spiConfig.ctrl1 |= SPI_CTRL1_MDIV_1;
948+ break;
949+ case 16:
950+ spiConfig.ctrl1 |= SPI_CTRL1_MDIV_1 | SPI_CTRL1_MDIV_0;
951+ break;
952+ case 32:
953+ spiConfig.ctrl1 |= SPI_CTRL1_MDIV_2;
954+ break;
955+ case 64:
956+ spiConfig.ctrl1 |= SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_0;
957+ break;
958+ case 128:
959+ spiConfig.ctrl1 |= SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_1;
960+ break;
961+ case 256:
962+ spiConfig.ctrl1 |= SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_1 | SPI_CTRL1_MDIV_0;
963+ break;
964+ case 512:
965+ spiConfig.ctrl2 |= SPI_CTRL1_MDIV_3;
966+ break;
967+ case 1024:
968+ spiConfig.ctrl2 |= SPI_CTRL1_MDIV_3;
969+ spiConfig.ctrl1 |= SPI_CTRL1_MDIV_0;
970+ break;
971+ }
972 #else
973 spiConfig.cr1 = 0;
974
975diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c
976index f49c4a45b0bf9a45e09fd8644d2964f939563eca..fed16d20b1aa9e58f27bf0a578e3fcc0fef5f519 100644
977--- a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c
978+++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c
979@@ -33,7 +33,7 @@ static inline uint32_t detect_flash_size(void) {
980 #elif defined(FLASH_SIZE)
981 return FLASH_SIZE;
982 #elif defined(FLASHSIZE_BASE)
983diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h
984index 0f0fa694e9c5078f46d48ffe8ff6c50457626dbb..f09f824bd8bd796edcccfd9583cc25f3d59b7c10 100644
985--- a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h
986+++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h
987@@ -16,6 +16,8 @@
988 # define BACKING_STORE_WRITE_SIZE 4 // from hal_efl_lld.c
989 # elif defined(QMK_MCU_FAMILY_WB32)
990 # define BACKING_STORE_WRITE_SIZE 8 // from hal_efl_lld.c
991+# elif defined(QMK_MCU_FAMILY_AT32)
992+# define BACKING_STORE_WRITE_SIZE 2 // from hal_efl_lld.c
993 # elif defined(QMK_MCU_FAMILY_STM32)
994 # if defined(STM32_FLASH_LINE_SIZE) // from some family's stm32_registry.h file
995 # define BACKING_STORE_WRITE_SIZE (STM32_FLASH_LINE_SIZE)
996diff --git a/platforms/chibios/drivers/ws2812_bitbang.c b/platforms/chibios/drivers/ws2812_bitbang.c
997index fce1963d0ae1670849537945a1d684172aaa36e5..a88c5ff619d5a8ca57f8717c9d74d2cd5b9ecbd7 100644
998--- a/platforms/chibios/drivers/ws2812_bitbang.c
999+++ b/platforms/chibios/drivers/ws2812_bitbang.c
1000@@ -11,7 +11,7 @@
1001 /* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */
1002
1003 #ifndef WS2812_BITBANG_NOP_FUDGE
1004-# if defined(STM32F0XX) || defined(STM32F1XX) || defined(GD32VF103) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) || defined(WB32F3G71xx) || defined(WB32FQ95xx)
1005+# if defined(STM32F0XX) || defined(STM32F1XX) || defined(GD32VF103) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) || defined(WB32F3G71xx) || defined(WB32FQ95xx) || defined(AT32F415)
1006 # define WS2812_BITBANG_NOP_FUDGE 0.4
1007 # else
1008 # if defined(RP2040)
1009diff --git a/platforms/chibios/drivers/ws2812_pwm.c b/platforms/chibios/drivers/ws2812_pwm.c
1010index c46e9171ab87cce67494f2e0910fd71e0bbd0347..50927b849a41b8af47297473644ffcd8f3037933 100644
1011--- a/platforms/chibios/drivers/ws2812_pwm.c
1012+++ b/platforms/chibios/drivers/ws2812_pwm.c
1013@@ -40,6 +40,9 @@
1014 #if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && !defined(WS2812_PWM_DMAMUX_ID)
1015 # error "please consult your MCU's datasheet and specify in your config.h: #define WS2812_PWM_DMAMUX_ID STM32_DMAMUX1_TIM?_UP"
1016 #endif
1017+#if (AT32_DMA_SUPPORTS_DMAMUX == TRUE) && !defined(WS2812_PWM_DMAMUX_CHANNEL) && !defined(WS2812_PWM_DMAMUX_ID)
1018+# error "please consult your MCU's datasheet and specify in your config.h: #define WS2812_PWM_DMAMUX_CHANNEL 1, #define WS2812_PWM_DMAMUX_ID AT32_DMAMUX_TMR?_OVERFLOW"
1019+#endif
1020
1021 /* Summarize https://www.st.com/resource/en/application_note/an4013-stm32-crossseries-timer-overview-stmicroelectronics.pdf to
1022 * figure out if we are using a 32bit timer. This is needed to setup the DMA controller correctly.
1023@@ -269,6 +272,14 @@ typedef uint32_t ws2812_buffer_t;
1024 # define WS2812_PWM_DMA_PERIPHERAL_WIDTH STM32_DMA_CR_PSIZE_HWORD
1025 typedef uint16_t ws2812_buffer_t;
1026 # endif
1027+#elif defined(AT32F415)
1028+# define WS2812_PWM_DMA_MEMORY_WIDTH AT32_DMA_CCTRL_MWIDTH_BYTE
1029+# if defined(WS2812_PWM_TIMER_32BIT)
1030+# define WS2812_PWM_DMA_PERIPHERAL_WIDTH AT32_DMA_CCTRL_PWIDTH_WORD
1031+# else
1032+# define WS2812_PWM_DMA_PERIPHERAL_WIDTH AT32_DMA_CCTRL_PWIDTH_HWORD
1033+# endif
1034+typedef uint8_t ws2812_buffer_t;
1035 #else
1036 # define WS2812_PWM_DMA_MEMORY_WIDTH STM32_DMA_CR_MSIZE_BYTE
1037 # if defined(WS2812_PWM_TIMER_32BIT)
1038@@ -309,8 +320,13 @@ void ws2812_init(void) {
1039 [0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled
1040 [WS2812_PWM_CHANNEL - 1] = {.mode = WS2812_PWM_OUTPUT_MODE, .callback = NULL}, // Turn on the channel we care about
1041 },
1042+#if defined(AT32F415)
1043+ .ctrl2 = 0,
1044+ .iden = AT32_TMR_IDEN_OVFDEN, // DMA on update event for next period
1045+#else
1046 .cr2 = 0,
1047 .dier = TIM_DIER_UDE, // DMA on update event for next period
1048+#endif
1049 };
1050 //#pragma GCC diagnostic pop // Restore command-line warning options
1051
1052@@ -321,6 +337,11 @@ void ws2812_init(void) {
1053 dmaStreamSetSource(WS2812_PWM_DMA_STREAM, ws2812_frame_buffer);
1054 dmaStreamSetDestination(WS2812_PWM_DMA_STREAM, &(WS2812_PWM_DRIVER.tim->CCR[WS2812_PWM_CHANNEL - 1])); // Ziel ist der An-Zeit im Cap-Comp-Register
1055diff --git a/platforms/chibios/drivers/ws2812_spi.c b/platforms/chibios/drivers/ws2812_spi.c
1056index a1357edec57b3fae180bb77abd9510b950e51eb6..d1792b871bf0166330e1e6b41bb0d6863af98886 100644
1057--- a/platforms/chibios/drivers/ws2812_spi.c
1058+++ b/platforms/chibios/drivers/ws2812_spi.c
1059@@ -40,26 +40,53 @@
1060
1061 // Define SPI config speed
1062 // baudrate should target 3.2MHz
1063+#if defined(AT32F415)
1064+# if WS2812_SPI_DIVISOR == 2
1065+# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (0)
1066+# elif WS2812_SPI_DIVISOR == 4
1067+# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_0)
1068+# elif WS2812_SPI_DIVISOR == 8
1069+# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_1)
1070+# elif WS2812_SPI_DIVISOR == 16 // default
1071+# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_1 | SPI_CTRL1_MDIV_0)
1072+# elif WS2812_SPI_DIVISOR == 32
1073+# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_2)
1074+# elif WS2812_SPI_DIVISOR == 64
1075+# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_0)
1076+# elif WS2812_SPI_DIVISOR == 128
1077+# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_1)
1078+# elif WS2812_SPI_DIVISOR == 256
1079+# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_1 | SPI_CTRL1_MDIV_0)
1080+# elif WS2812_SPI_DIVISOR == 512
1081+# define WS2812_SPI_DIVISOR_CTRL2_MDIV_X (SPI_CTRL1_MDIV_3)
1082+# elif WS2812_SPI_DIVISOR == 1024
1083+# define WS2812_SPI_DIVISOR_CTRL2_MDIV_X (SPI_CTRL1_MDIV_3)
1084+# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_0)
1085+# else
1086+# error "Configured WS2812_SPI_DIVISOR value is not supported at this time."
1087+# endif
1088+#else
1089 // F072 fpclk = 48MHz
1090 // 48/16 = 3Mhz
1091-#if WS2812_SPI_DIVISOR == 2
1092-# define WS2812_SPI_DIVISOR_CR1_BR_X (0)
1093-#elif WS2812_SPI_DIVISOR == 4
1094-# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_0)
1095-#elif WS2812_SPI_DIVISOR == 8
1096-# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1)
1097-#elif WS2812_SPI_DIVISOR == 16 // default
1098-# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1 | SPI_CR1_BR_0)
1099-#elif WS2812_SPI_DIVISOR == 32
1100-# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2)
1101-#elif WS2812_SPI_DIVISOR == 64
1102-# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_0)
1103-#elif WS2812_SPI_DIVISOR == 128
1104-# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_1)
1105-#elif WS2812_SPI_DIVISOR == 256
1106-# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0)
1107-#else
1108-# error "Configured WS2812_SPI_DIVISOR value is not supported at this time."
1109+# if WS2812_SPI_DIVISOR == 2
1110+# define WS2812_SPI_DIVISOR_CR1_BR_X (0)
1111+# elif WS2812_SPI_DIVISOR == 4
1112+# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_0)
1113+# elif WS2812_SPI_DIVISOR == 8
1114+# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1)
1115+# elif WS2812_SPI_DIVISOR == 16 // default
1116+# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1 | SPI_CR1_BR_0)
1117+# elif WS2812_SPI_DIVISOR == 32
1118+# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2)
1119+# elif WS2812_SPI_DIVISOR == 64
1120+# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_0)
1121+# elif WS2812_SPI_DIVISOR == 128
1122+# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_1)
1123+# elif WS2812_SPI_DIVISOR == 256
1124+# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0)
1125+# else
1126+# error "Configured WS2812_SPI_DIVISOR value is not supported at this time."
1127+# endif
1128 #endif
1129
1130 // Use SPI circular buffer
1131@@ -176,8 +203,16 @@ void ws2812_init(void) {
1132 NULL, // error_cb
1133 PAL_PORT(WS2812_DI_PIN),
1134 PAL_PAD(WS2812_DI_PIN),
1135+# if defined(AT32F415)
1136+ WS2812_SPI_DIVISOR_CTRL1_MDIV_X,
1137+# if (WS2812_SPI_DIVISOR == 512 || WS2812_SPI_DIVISOR == 1024)
1138+ WS2812_SPI_DIVISOR_CTRL2_MDIV_X,
1139+# endif
1140+ 0
1141+# else
1142 WS2812_SPI_DIVISOR_CR1_BR_X,
1143 0
1144+# endif
1145 #endif
1146 };
1147
1148diff --git a/platforms/chibios/flash.mk b/platforms/chibios/flash.mk
1149index 525f177f9ebb943729641456374719c83131d1c2..f4db17a58bf9d7a23ac9f12875b61d9a456840dc 100644
1150--- a/platforms/chibios/flash.mk
1151+++ b/platforms/chibios/flash.mk
1152@@ -113,6 +113,8 @@ else ifeq ($(strip $(MCU_FAMILY)),STM32)
1153 $(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL)
1154 else ifeq ($(strip $(MCU_FAMILY)),WB32)
1155 $(UNSYNC_OUTPUT_CMD) && $(call EXEC_WB32_DFU_UPDATER)
1156+else ifeq ($(strip $(MCU_FAMILY)),AT32)
1157+ $(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL)
1158 else ifeq ($(strip $(MCU_FAMILY)),GD32V)
1159 $(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL)
1160 else
1161diff --git a/platforms/chibios/mcu_selection.mk b/platforms/chibios/mcu_selection.mk
1162index a1597fa1e91236b05b1892437427d6c09944d073..086a2b31c60b66ad17c22cf0ccfb6ff6ef8ee4ae 100644
1163--- a/platforms/chibios/mcu_selection.mk
1164+++ b/platforms/chibios/mcu_selection.mk
1165@@ -809,6 +809,40 @@ ifneq ($(findstring WB32FQ95, $(MCU)),)
1166 WB32_BOOTLOADER_ADDRESS ?= 0x1FFFE000
1167 endif
1168
1169+ifneq ($(findstring AT32F415, $(MCU)),)
1170+ # Cortex version
1171+ MCU = cortex-m4
1172+
1173+ # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
1174+ ARMV = 7
1175+
1176+ ## chip/board settings
1177+ # - the next two should match the directories in
1178+ # <chibios[-contrib]>/os/hal/ports/$(MCU_PORT_NAME)/$(MCU_SERIES)
1179+ # OR
1180+ # <chibios[-contrib]>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
1181+ MCU_FAMILY = AT32
1182+ MCU_SERIES = AT32F415
1183+
1184+ # Linker script to use
1185+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
1186+ # or <keyboard_dir>/ld/
1187+ MCU_LDSCRIPT ?= AT32F415xB
1188+
1189+ # Startup code to use
1190+ # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
1191+ MCU_STARTUP ?= at32f415
1192+
1193+ # Board: it should exist either in <chibios>/os/hal/boards/,
1194+ # <keyboard_dir>/boards/, or drivers/boards/
1195+ BOARD ?= GENERIC_AT32_F415XX
1196+
1197+ USE_FPU ?= no
1198+
1199+ # Bootloader address for AT32 DFU
1200+ AT32_BOOTLOADER_ADDRESS ?= 0x1FFFAC00
1201+endif
1202+
1203 ifneq ($(findstring GD32VF103, $(MCU)),)
1204 # RISC-V
1205 MCU = risc-v
1206diff --git a/platforms/chibios/platform.mk b/platforms/chibios/platform.mk
1207index 169707966ff84f305a8dffb65f34dccb5a08d4ed..cf9fac251e459377ed7bbef15c6b35dfffbf67e9 100644
1208--- a/platforms/chibios/platform.mk
1209+++ b/platforms/chibios/platform.mk
1210@@ -155,6 +155,10 @@ ifdef WB32_BOOTLOADER_ADDRESS
1211 OPT_DEFS += -DWB32_BOOTLOADER_ADDRESS=$(WB32_BOOTLOADER_ADDRESS)
1212 endif
1213
1214+ifdef AT32_BOOTLOADER_ADDRESS
1215+ OPT_DEFS += -DAT32_BOOTLOADER_ADDRESS=$(AT32_BOOTLOADER_ADDRESS)
1216+endif
1217+
1218 # Work out if we need to set up the include for the bootloader definitions
1219 ifneq ("$(wildcard $(KEYBOARD_PATH_5)/bootloader_defs.h)","")
1220 OPT_DEFS += -include $(KEYBOARD_PATH_5)/bootloader_defs.h