summaryrefslogtreecommitdiff
path: root/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'platforms')
-rw-r--r--platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.c101
-rw-r--r--platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.h207
-rw-r--r--platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.mk9
-rw-r--r--platforms/chibios/boards/GENERIC_AT32_F415XX/configs/config.h13
-rw-r--r--platforms/chibios/boards/GENERIC_AT32_F415XX/configs/mcuconf.h236
-rw-r--r--platforms/chibios/bootloader.mk9
-rw-r--r--platforms/chibios/bootloaders/at32_dfu.c83
-rw-r--r--platforms/chibios/chibios_config.h13
-rw-r--r--platforms/chibios/drivers/analog.c23
-rw-r--r--platforms/chibios/drivers/serial_usart.c15
-rw-r--r--platforms/chibios/drivers/serial_usart.h99
-rw-r--r--platforms/chibios/drivers/spi_master.c59
-rw-r--r--platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c2
-rw-r--r--platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h2
-rw-r--r--platforms/chibios/drivers/ws2812_bitbang.c2
-rw-r--r--platforms/chibios/drivers/ws2812_pwm.c26
-rw-r--r--platforms/chibios/drivers/ws2812_spi.c71
-rw-r--r--platforms/chibios/flash.mk2
-rw-r--r--platforms/chibios/mcu_selection.mk34
-rw-r--r--platforms/chibios/platform.mk4
20 files changed, 949 insertions, 61 deletions
diff --git a/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.c b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.c
new file mode 100644
index 0000000000..28cf7c18e0
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.c
@@ -0,0 +1,101 @@
1/*
2 ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3 ChibiOS - Copyright (C) 2023..2024 HorrorTroll
4 ChibiOS - Copyright (C) 2023..2024 Zhaqian
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17*/
18
19#include "hal.h"
20
21/*===========================================================================*/
22/* Driver local definitions. */
23/*===========================================================================*/
24
25/*===========================================================================*/
26/* Driver exported variables. */
27/*===========================================================================*/
28
29/*===========================================================================*/
30/* Driver local variables and types. */
31/*===========================================================================*/
32
33/**
34 * @brief PAL setup.
35 * @details Digital I/O ports static configuration as defined in @p board.h.
36 * This variable is used by the HAL when initializing the PAL driver.
37 */
38#if HAL_USE_PAL || defined(__DOXYGEN__)
39const PALConfig pal_default_config =
40{
41 {VAL_GPIOAODT, VAL_GPIOACFGLR, VAL_GPIOACFGHR},
42 {VAL_GPIOBODT, VAL_GPIOBCFGLR, VAL_GPIOBCFGHR},
43#if AT32_HAS_GPIOC
44 {VAL_GPIOCODT, VAL_GPIOCCFGLR, VAL_GPIOCCFGHR},
45#endif
46 {VAL_GPIODODT, VAL_GPIODCFGLR, VAL_GPIODCFGHR},
47#if AT32_HAS_GPIOF
48 {VAL_GPIOFODT, VAL_GPIOFCFGLR, VAL_GPIOFCFGHR},
49#endif
50};
51#endif
52
53/*===========================================================================*/
54/* Driver local functions. */
55/*===========================================================================*/
56
57/*===========================================================================*/
58/* Driver interrupt handlers. */
59/*===========================================================================*/
60
61/*===========================================================================*/
62/* Driver exported functions. */
63/*===========================================================================*/
64
65/**
66 * @brief Early initialization code.
67 * @details System clocks are initialized before everything else.
68 */
69void __early_init(void) {
70 at32_clock_init();
71}
72
73#if HAL_USE_SDC || defined(__DOXYGEN__)
74/**
75 * @brief SDC card detection.
76 */
77bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
78 static bool last_status = false;
79
80 if (blkIsTransferring(sdcp))
81 return last_status;
82 return last_status = (bool)palReadPad(GPIOC, GPIOC_PIN11);
83}
84
85/**
86 * @brief SDC card write protection detection.
87 */
88bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
89
90 (void)sdcp;
91 return false;
92}
93#endif /* HAL_USE_SDC */
94
95/**
96 * @brief Board-specific initialization code.
97 * @note You can add your board-specific code here.
98 */
99void boardInit(void) {
100 IOMUX->REMAP |= IOMUX_REMAP_SWJTAG_MUX_JTAGDIS;
101}
diff --git a/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.h b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.h
new file mode 100644
index 0000000000..c3ade198ba
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.h
@@ -0,0 +1,207 @@
1/*
2 ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3 ChibiOS - Copyright (C) 2023..2024 HorrorTroll
4 ChibiOS - Copyright (C) 2023..2024 Zhaqian
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17*/
18
19#ifndef _BOARD_H_
20#define _BOARD_H_
21
22/*===========================================================================*/
23/* Driver constants. */
24/*===========================================================================*/
25
26/*
27 * Setup for a Generic AT32F415 board.
28 */
29
30/*
31 * Board identifier.
32 */
33#define BOARD_GENERIC_AT32_F415XX
34#define BOARD_NAME "GENERIC AT32F415 board"
35
36/*
37 * Board oscillators-related settings.
38 */
39#if !defined(AT32_LEXTCLK)
40#define AT32_LEXTCLK 32768
41#endif
42
43#if !defined(AT32_HEXTCLK)
44#define AT32_HEXTCLK 8000000
45#endif
46
47/*
48 * MCU type, supported types are defined in ./os/hal/platforms/hal_lld.h.
49 */
50#define AT32F415KB
51
52/*
53 * IO pins assignments.
54 */
55#define GPIOA_PIN0 0U
56#define GPIOA_PIN1 1U
57#define GPIOA_PIN2 2U
58#define GPIOA_PIN3 3U
59#define GPIOA_PIN4 4U
60#define GPIOA_PIN5 5U
61#define GPIOA_PIN6 6U
62#define GPIOA_PIN7 7U
63#define GPIOA_PIN8 8U
64#define GPIOA_PIN9 9U
65#define GPIOA_PIN10 10U
66#define GPIOA_PIN11 11U
67#define GPIOA_PIN12 12U
68#define GPIOA_SWDIO 13U
69#define GPIOA_SWCLK 14U
70#define GPIOA_PIN15 15U
71
72#define GPIOB_PIN0 0U
73#define GPIOB_PIN1 1U
74#define GPIOB_PIN2 2U
75#define GPIOB_PIN3 3U
76#define GPIOB_PIN4 4U
77#define GPIOB_PIN5 5U
78#define GPIOB_PIN6 6U
79#define GPIOB_PIN7 7U
80#define GPIOB_PIN8 8U
81#define GPIOB_PIN9 9U
82#define GPIOB_PIN10 10U
83#define GPIOB_PIN11 11U
84#define GPIOB_PIN12 12U
85#define GPIOB_PIN13 13U
86#define GPIOB_PIN14 14U
87#define GPIOB_PIN15 15U
88
89#define GPIOC_PIN0 0U
90#define GPIOC_PIN1 1U
91#define GPIOC_PIN2 2U
92#define GPIOC_PIN3 3U
93#define GPIOC_PIN4 4U
94#define GPIOC_PIN5 5U
95#define GPIOC_PIN6 6U
96#define GPIOC_PIN7 7U
97#define GPIOC_PIN8 8U
98#define GPIOC_PIN9 9U
99#define GPIOC_PIN10 10U
100#define GPIOC_PIN11 11U
101#define GPIOC_PIN12 12U
102#define GPIOC_PIN13 13U
103#define GPIOC_PIN14 14U
104#define GPIOC_PIN15 15U
105
106#define GPIOD_HEXT_IN 0U
107#define GPIOD_HEXT_OUT 1U
108#define GPIOD_PIN2 2U
109
110#define GPIOF_PIN4 4U
111#define GPIOF_PIN5 5U
112#define GPIOF_PIN6 6U
113#define GPIOF_PIN7 7U
114
115/*===========================================================================*/
116/* Driver pre-compile time settings. */
117/*===========================================================================*/
118
119/*===========================================================================*/
120/* Derived constants and error checks. */
121/*===========================================================================*/
122
123/*===========================================================================*/
124/* Driver data structures and types. */
125/*===========================================================================*/
126
127/*===========================================================================*/
128/* Driver macros. */
129/*===========================================================================*/
130
131/*
132 * I/O ports initial setup, this configuration is established soon after reset
133 * in the initialization code.
134 *
135 * The digits have the following meaning:
136 * 0 - Analog input.
137 * 1 - Push Pull output 10MHz.
138 * 2 - Push Pull output 2MHz.
139 * 3 - Push Pull output 50MHz.
140 * 4 - Digital input.
141 * 5 - Open Drain output 10MHz.
142 * 6 - Open Drain output 2MHz.
143 * 7 - Open Drain output 50MHz.
144 * 8 - Digital input with Pull-Up or Pull-Down resistor depending on ODT.
145 * 9 - Alternate Push Pull output 10MHz.
146 * A - Alternate Push Pull output 2MHz.
147 * B - Alternate Push Pull output 50MHz.
148 * C - Reserved.
149 * D - Alternate Open Drain output 10MHz.
150 * E - Alternate Open Drain output 2MHz.
151 * F - Alternate Open Drain output 50MHz.
152 * Please refer to the AT32 Reference Manual for details.
153 */
154
155/*
156 * Port A setup.
157 */
158#define VAL_GPIOACFGLR 0x88888B88 /* PA7...PA0 */
159#define VAL_GPIOACFGHR 0x888888B8 /* PA15...PA8 */
160#define VAL_GPIOAODT 0xFFFFFFFF
161
162/*
163 * Port B setup.
164 */
165#define VAL_GPIOBCFGLR 0x88888888 /* PB7...PB0 */
166#define VAL_GPIOBCFGHR 0x88888888 /* PB15...PB8 */
167#define VAL_GPIOBODT 0xFFFFFFFF
168
169/*
170 * Port C setup.
171 */
172#define VAL_GPIOCCFGLR 0x88888888 /* PC7...PC0 */
173#define VAL_GPIOCCFGHR 0x88888888 /* PC15...PC8 */
174#define VAL_GPIOCODT 0xFFFFFFFF
175
176/*
177 * Port D setup.
178 * Everything input with pull-up except:
179 * PD0 - Normal input (GPIOD_HEXT_IN).
180 * PD1 - Normal input (GPIOD_HEXT_OUT).
181 */
182#define VAL_GPIODCFGLR 0x88888844 /* PD7...PD0 */
183#define VAL_GPIODCFGHR 0x88888888 /* PD15...PD8 */
184#define VAL_GPIODODT 0xFFFFFFFF
185
186/*
187 * Port F setup.
188 */
189#define VAL_GPIOFCFGLR 0x88888888 /* PF7...PF0 */
190#define VAL_GPIOFCFGHR 0x88888888 /* PF15...PF8 */
191#define VAL_GPIOFODT 0xFFFFFFFF
192
193/*===========================================================================*/
194/* External declarations. */
195/*===========================================================================*/
196
197#if !defined(_FROM_ASM_)
198#ifdef __cplusplus
199extern "C" {
200#endif
201 void boardInit(void);
202#ifdef __cplusplus
203}
204#endif
205#endif /* _FROM_ASM_ */
206
207#endif /* _BOARD_H_ */
diff --git a/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.mk b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.mk
new file mode 100644
index 0000000000..842e335905
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_AT32_F415XX/board/board.mk
@@ -0,0 +1,9 @@
1# List of all the board related files.
2BOARDSRC = $(BOARD_PATH)/board/board.c
3
4# Required include directories
5BOARDINC = $(BOARD_PATH)/board
6
7# Shared variables
8ALLCSRC += $(BOARDSRC)
9ALLINC += $(BOARDINC)
diff --git a/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/config.h b/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/config.h
new file mode 100644
index 0000000000..da60447a0a
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/config.h
@@ -0,0 +1,13 @@
1// Copyright 2023-2024 HorrorTroll <https://github.com/HorrorTroll>
2// Copyright 2023-2024 Zhaqian <https://github.com/zhaqian12>
3// SPDX-License-Identifier: GPL-2.0-or-later
4
5#pragma once
6
7#define BOARD_OTG_VBUSIG
8
9#define USB_ENDPOINTS_ARE_REORDERABLE
10
11#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
12# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE
13#endif
diff --git a/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/mcuconf.h
new file mode 100644
index 0000000000..d148379fe1
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_AT32_F415XX/configs/mcuconf.h
@@ -0,0 +1,236 @@
1/*
2 ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
3 ChibiOS - Copyright (C) 2023..2024 HorrorTroll
4 ChibiOS - Copyright (C) 2023..2024 Zhaqian
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17*/
18
19#ifndef MCUCONF_H
20#define MCUCONF_H
21
22/*
23 * AT32F415 drivers configuration.
24 * The following settings override the default settings present in
25 * the various device driver implementation headers.
26 * Note that the settings for each driver only have effect if the whole
27 * driver is enabled in halconf.h.
28 *
29 * IRQ priorities:
30 * 15...0 Lowest...Highest.
31 *
32 * DMA priorities:
33 * 0...3 Lowest...Highest.
34 */
35
36#define AT32F415_MCUCONF
37
38/*
39 * General settings.
40 */
41#define AT32_NO_INIT FALSE
42
43/*
44 * HAL driver system settings.
45 */
46#define AT32_HICK_ENABLED TRUE
47#define AT32_LICK_ENABLED FALSE
48#define AT32_HEXT_ENABLED TRUE
49#define AT32_LEXT_ENABLED FALSE
50#define AT32_SCLKSEL AT32_SCLKSEL_PLL
51#define AT32_PLLRCS AT32_PLLRCS_HEXT
52#define AT32_PLLHEXTDIV AT32_PLLHEXTDIV_DIV1
53#define AT32_PLLCFGEN AT32_PLLCFGEN_SOLID
54#define AT32_PLLMULT_VALUE 18
55#define AT32_PLL_FR_VALUE 4
56#define AT32_PLL_MS_VALUE 1
57#define AT32_PLL_NS_VALUE 72
58#define AT32_AHBDIV AT32_AHBDIV_DIV1
59#define AT32_APB1DIV AT32_APB1DIV_DIV2
60#define AT32_APB2DIV AT32_APB2DIV_DIV2
61#define AT32_ADCDIV AT32_ADCDIV_DIV4
62#define AT32_USB_CLOCK_REQUIRED TRUE
63#define AT32_USBDIV AT32_USBDIV_DIV3
64#define AT32_CLKOUT_SEL AT32_CLKOUT_SEL_NOCLOCK
65#define AT32_CLKOUTDIV AT32_CLKOUTDIV_DIV1
66#define AT32_ERTCSEL AT32_ERTCSEL_HEXTDIV
67#define AT32_PVM_ENABLE FALSE
68#define AT32_PVMSEL AT32_PVMSEL_LEV1
69
70/*
71 * IRQ system settings.
72 */
73#define AT32_IRQ_EXINT0_PRIORITY 6
74#define AT32_IRQ_EXINT1_PRIORITY 6
75#define AT32_IRQ_EXINT2_PRIORITY 6
76#define AT32_IRQ_EXINT3_PRIORITY 6
77#define AT32_IRQ_EXINT4_PRIORITY 6
78#define AT32_IRQ_EXINT5_9_PRIORITY 6
79#define AT32_IRQ_EXINT10_15_PRIORITY 6
80#define AT32_IRQ_EXINT16_PRIORITY 6
81#define AT32_IRQ_EXINT17_PRIORITY 15
82#define AT32_IRQ_EXINT18_PRIORITY 6
83#define AT32_IRQ_EXINT19_PRIORITY 6
84#define AT32_IRQ_EXINT20_PRIORITY 6
85#define AT32_IRQ_EXINT21_PRIORITY 15
86#define AT32_IRQ_EXINT22_PRIORITY 15
87
88#define AT32_IRQ_TMR1_BRK_TMR9_PRIORITY 7
89#define AT32_IRQ_TMR1_OVF_TMR10_PRIORITY 7
90#define AT32_IRQ_TMR1_HALL_TMR11_PRIORITY 7
91#define AT32_IRQ_TMR1_CH_PRIORITY 7
92#define AT32_IRQ_TMR2_PRIORITY 7
93#define AT32_IRQ_TMR3_PRIORITY 7
94#define AT32_IRQ_TMR4_PRIORITY 7
95#define AT32_IRQ_TMR5_PRIORITY 7
96
97#define AT32_IRQ_USART1_PRIORITY 12
98#define AT32_IRQ_USART2_PRIORITY 12
99#define AT32_IRQ_USART3_PRIORITY 12
100#define AT32_IRQ_UART4_PRIORITY 12
101#define AT32_IRQ_UART5_PRIORITY 12
102
103/*
104 * ADC driver system settings.
105 */
106#define AT32_ADC_USE_ADC1 FALSE
107#define AT32_ADC_ADC1_DMA_PRIORITY 2
108#define AT32_ADC_ADC1_IRQ_PRIORITY 6
109
110/*
111 * CAN driver system settings.
112 */
113#define AT32_CAN_USE_CAN1 FALSE
114#define AT32_CAN_CAN1_IRQ_PRIORITY 11
115
116/*
117 * DMA driver system settings.
118 */
119#define AT32_DMA_USE_DMAMUX TRUE
120
121/*
122 * GPT driver system settings.
123 */
124#define AT32_GPT_USE_TMR1 FALSE
125#define AT32_GPT_USE_TMR2 FALSE
126#define AT32_GPT_USE_TMR3 FALSE
127#define AT32_GPT_USE_TMR4 FALSE
128#define AT32_GPT_USE_TMR5 FALSE
129#define AT32_GPT_USE_TMR9 FALSE
130#define AT32_GPT_USE_TMR10 FALSE
131#define AT32_GPT_USE_TMR11 FALSE
132
133/*
134 * I2C driver system settings.
135 */
136#define AT32_I2C_USE_I2C1 FALSE
137#define AT32_I2C_USE_I2C2 FALSE
138#define AT32_I2C_BUSY_TIMEOUT 50
139#define AT32_I2C_I2C1_IRQ_PRIORITY 5
140#define AT32_I2C_I2C2_IRQ_PRIORITY 5
141#define AT32_I2C_I2C1_DMA_PRIORITY 3
142#define AT32_I2C_I2C2_DMA_PRIORITY 3
143#define AT32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
144
145/*
146 * ICU driver system settings.
147 */
148#define AT32_ICU_USE_TMR1 FALSE
149#define AT32_ICU_USE_TMR2 FALSE
150#define AT32_ICU_USE_TMR3 FALSE
151#define AT32_ICU_USE_TMR4 FALSE
152#define AT32_ICU_USE_TMR5 FALSE
153#define AT32_ICU_USE_TMR9 FALSE
154#define AT32_ICU_USE_TMR10 FALSE
155#define AT32_ICU_USE_TMR11 FALSE
156
157/*
158 * PWM driver system settings.
159 */
160#define AT32_PWM_USE_TMR1 FALSE
161#define AT32_PWM_USE_TMR2 FALSE
162#define AT32_PWM_USE_TMR3 FALSE
163#define AT32_PWM_USE_TMR4 FALSE
164#define AT32_PWM_USE_TMR5 FALSE
165#define AT32_PWM_USE_TMR9 FALSE
166#define AT32_PWM_USE_TMR10 FALSE
167#define AT32_PWM_USE_TMR11 FALSE
168
169/*
170 * RTC driver system settings.
171 */
172#define AT32_ERTC_DIVA_VALUE 32
173#define AT32_ERTC_DIVB_VALUE 1024
174#define AT32_ERTC_CTRL_INIT 0
175#define AT32_ERTC_TAMP_INIT 0
176
177/*
178 * SDC driver system settings.
179 */
180#define AT32_SDC_SDIO_DMA_PRIORITY 3
181#define AT32_SDC_SDIO_IRQ_PRIORITY 9
182#define AT32_SDC_WRITE_TIMEOUT_MS 1000
183#define AT32_SDC_READ_TIMEOUT_MS 1000
184#define AT32_SDC_CLOCK_ACTIVATION_DELAY 10
185#define AT32_SDC_SDIO_UNALIGNED_SUPPORT TRUE
186
187/*
188 * SERIAL driver system settings.
189 */
190#define AT32_SERIAL_USE_USART1 FALSE
191#define AT32_SERIAL_USE_USART2 FALSE
192#define AT32_SERIAL_USE_USART3 FALSE
193#define AT32_SERIAL_USE_UART4 FALSE
194#define AT32_SERIAL_USE_UART5 FALSE
195
196/*
197 * SPI driver system settings.
198 */
199#define AT32_SPI_USE_SPI1 FALSE
200#define AT32_SPI_USE_SPI2 FALSE
201#define AT32_SPI_SPI1_DMA_PRIORITY 1
202#define AT32_SPI_SPI2_DMA_PRIORITY 1
203#define AT32_SPI_SPI1_IRQ_PRIORITY 10
204#define AT32_SPI_SPI2_IRQ_PRIORITY 10
205#define AT32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
206
207/*
208 * ST driver system settings.
209 */
210#define AT32_ST_IRQ_PRIORITY 8
211#define AT32_ST_USE_TIMER 2
212
213/*
214 * UART driver system settings.
215 */
216#define AT32_UART_USE_USART1 FALSE
217#define AT32_UART_USE_USART2 FALSE
218#define AT32_UART_USE_USART3 FALSE
219#define AT32_UART_USART1_DMA_PRIORITY 0
220#define AT32_UART_USART2_DMA_PRIORITY 0
221#define AT32_UART_USART3_DMA_PRIORITY 0
222#define AT32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
223
224/*
225 * USB driver system settings.
226 */
227#define AT32_USB_USE_OTG1 TRUE
228#define AT32_USB_OTG1_IRQ_PRIORITY 14
229#define AT32_USB_OTG1_RX_FIFO_SIZE 512
230
231/*
232 * WDG driver system settings.
233 */
234#define AT32_WDG_USE_WDT FALSE
235
236#endif /* MCUCONF_H */
diff --git a/platforms/chibios/bootloader.mk b/platforms/chibios/bootloader.mk
index 5b6edd73ad..e292e1e0b0 100644
--- a/platforms/chibios/bootloader.mk
+++ b/platforms/chibios/bootloader.mk
@@ -26,6 +26,7 @@
26# stm32-dfu STM32 USB DFU in ROM 26# stm32-dfu STM32 USB DFU in ROM
27# apm32-dfu APM32 USB DFU in ROM 27# apm32-dfu APM32 USB DFU in ROM
28# wb32-dfu WB32 USB DFU in ROM 28# wb32-dfu WB32 USB DFU in ROM
29# at32-dfu AT32 USB DFU in ROM
29# tinyuf2 TinyUF2 30# tinyuf2 TinyUF2
30# rp2040 Raspberry Pi RP2040 31# rp2040 Raspberry Pi RP2040
31# Current options for RISC-V: 32# Current options for RISC-V:
@@ -119,6 +120,14 @@ ifeq ($(strip $(BOOTLOADER)), wb32-dfu)
119 OPT_DEFS += -DBOOTLOADER_WB32_DFU 120 OPT_DEFS += -DBOOTLOADER_WB32_DFU
120 BOOTLOADER_TYPE = wb32_dfu 121 BOOTLOADER_TYPE = wb32_dfu
121endif 122endif
123ifeq ($(strip $(BOOTLOADER)), at32-dfu)
124 OPT_DEFS += -DBOOTLOADER_AT32_DFU
125 BOOTLOADER_TYPE = at32_dfu
126
127 # Options to pass to dfu-util when flashing
128 DFU_ARGS ?= -d 2E3C:DF11 -a 0 -s 0x08000000:leave
129 DFU_SUFFIX_ARGS ?= -v 2E3C -p DF11
130endif
122 131
123ifeq ($(strip $(BOOTLOADER_TYPE)),) 132ifeq ($(strip $(BOOTLOADER_TYPE)),)
124 ifneq ($(strip $(BOOTLOADER)),) 133 ifneq ($(strip $(BOOTLOADER)),)
diff --git a/platforms/chibios/bootloaders/at32_dfu.c b/platforms/chibios/bootloaders/at32_dfu.c
new file mode 100644
index 0000000000..f3a453d0fc
--- /dev/null
+++ b/platforms/chibios/bootloaders/at32_dfu.c
@@ -0,0 +1,83 @@
1// Copyright 2021-2023 QMK
2// Copyright 2023-2024 HorrorTroll <https://github.com/HorrorTroll>
3// Copyright 2023-2024 Zhaqian <https://github.com/zhaqian12>
4// SPDX-License-Identifier: GPL-2.0-or-later
5
6#include "bootloader.h"
7#include "util.h"
8
9#include <ch.h>
10#include <hal.h>
11#include "wait.h"
12
13#ifndef AT32_BOOTLOADER_RAM_SYMBOL
14# define AT32_BOOTLOADER_RAM_SYMBOL __ram0_end__
15#endif
16
17extern uint32_t AT32_BOOTLOADER_RAM_SYMBOL;
18
19/* This code should be checked whether it runs correctly on platforms */
20#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
21#define BOOTLOADER_MAGIC 0xDEADBEEF
22#define MAGIC_ADDR (unsigned long *)(SYMVAL(AT32_BOOTLOADER_RAM_SYMBOL) - 4)
23
24__attribute__((weak)) void bootloader_marker_enable(void) {
25 uint32_t *marker = (uint32_t *)MAGIC_ADDR;
26 *marker = BOOTLOADER_MAGIC; // set magic flag => reset handler will jump into boot loader
27}
28
29__attribute__((weak)) bool bootloader_marker_active(void) {
30 const uint32_t *marker = (const uint32_t *)MAGIC_ADDR;
31 return (*marker == BOOTLOADER_MAGIC) ? true : false;
32}
33
34__attribute__((weak)) void bootloader_marker_disable(void) {
35 uint32_t *marker = (uint32_t *)MAGIC_ADDR;
36 *marker = 0;
37}
38
39__attribute__((weak)) void bootloader_jump(void) {
40 bootloader_marker_enable();
41 NVIC_SystemReset();
42}
43
44__attribute__((weak)) void mcu_reset(void) {
45 NVIC_SystemReset();
46}
47
48void enter_bootloader_mode_if_requested(void) {
49 if (bootloader_marker_active()) {
50 bootloader_marker_disable();
51
52 struct system_memory_vector_t {
53 uint32_t stack_top;
54 void (*entrypoint)(void);
55 };
56 const struct system_memory_vector_t *bootloader = (const struct system_memory_vector_t *)(AT32_BOOTLOADER_ADDRESS);
57
58 __disable_irq();
59
60#if defined(__MPU_PRESENT) && (__MPU_PRESENT == 1U)
61 ARM_MPU_Disable();
62#endif
63
64 SysTick->CTRL = 0;
65 SysTick->VAL = 0;
66 SysTick->LOAD = 0;
67
68 // Clear interrupt enable and interrupt pending registers
69 for (int i = 0; i < ARRAY_SIZE(NVIC->ICER); i++) {
70 NVIC->ICER[i] = 0xFFFFFFFF;
71 NVIC->ICPR[i] = 0xFFFFFFFF;
72 }
73
74 __set_CONTROL(0);
75 __set_MSP(bootloader->stack_top);
76 __enable_irq();
77
78 // Jump to bootloader
79 bootloader->entrypoint();
80 while (true) {
81 }
82 }
83}
diff --git a/platforms/chibios/chibios_config.h b/platforms/chibios/chibios_config.h
index 8f46fe0736..95136baf30 100644
--- a/platforms/chibios/chibios_config.h
+++ b/platforms/chibios/chibios_config.h
@@ -142,6 +142,19 @@
142# endif 142# endif
143#endif 143#endif
144 144
145// AT32 compatibility
146#if defined(MCU_AT32)
147# define CPU_CLOCK AT32_SYSCLK
148
149# if defined(AT32F415)
150# define USE_GPIOV1
151# define USE_I2CV1
152# define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_AT32_ALTERNATE_OPENDRAIN
153# define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_AT32_ALTERNATE_PUSHPULL
154# define AUDIO_PWM_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
155# endif
156#endif
157
145#if defined(GD32VF103) 158#if defined(GD32VF103)
146/* This chip has the same API as STM32F103, but uses different names for literally the same thing. 159/* This chip has the same API as STM32F103, but uses different names for literally the same thing.
147 * As of 4.7.2021 QMK is tailored to use STM32 defines/names, for compatibility sake 160 * As of 4.7.2021 QMK is tailored to use STM32 defines/names, for compatibility sake
diff --git a/platforms/chibios/drivers/analog.c b/platforms/chibios/drivers/analog.c
index fb146df936..7e1f87e6c9 100644
--- a/platforms/chibios/drivers/analog.c
+++ b/platforms/chibios/drivers/analog.c
@@ -22,7 +22,7 @@
22# error "You need to set HAL_USE_ADC to TRUE in your halconf.h to use the ADC." 22# error "You need to set HAL_USE_ADC to TRUE in your halconf.h to use the ADC."
23#endif 23#endif
24 24
25#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 25#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
26# error "You need to set one of the 'xxx_ADC_USE_ADCx' settings to TRUE in your mcuconf.h to use the ADC." 26# error "You need to set one of the 'xxx_ADC_USE_ADCx' settings to TRUE in your mcuconf.h to use the ADC."
27#endif 27#endif
28 28
@@ -45,7 +45,7 @@
45// Otherwise assume V3 45// Otherwise assume V3
46#if defined(STM32F0XX) || defined(STM32L0XX) 46#if defined(STM32F0XX) || defined(STM32L0XX)
47# define USE_ADCV1 47# define USE_ADCV1
48#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) 48#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) || defined(AT32F415)
49# define USE_ADCV2 49# define USE_ADCV2
50#endif 50#endif
51 51
@@ -82,7 +82,7 @@
82 82
83/* User configurable ADC options */ 83/* User configurable ADC options */
84#ifndef ADC_COUNT 84#ifndef ADC_COUNT
85# if defined(RP2040) || defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) 85# if defined(RP2040) || defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) || defined(AT32F415)
86# define ADC_COUNT 1 86# define ADC_COUNT 1
87# elif defined(STM32F3XX) || defined(STM32G4XX) 87# elif defined(STM32F3XX) || defined(STM32G4XX)
88# define ADC_COUNT 4 88# define ADC_COUNT 4
@@ -142,11 +142,16 @@ static ADCConversionGroup adcConversionGroup = {
142 .cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION, 142 .cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION,
143 .smpr = ADC_SAMPLING_RATE, 143 .smpr = ADC_SAMPLING_RATE,
144#elif defined(USE_ADCV2) 144#elif defined(USE_ADCV2)
145# if !defined(STM32F1XX) && !defined(GD32VF103) && !defined(WB32F3G71xx) && !defined(WB32FQ95xx) 145# if !defined(STM32F1XX) && !defined(GD32VF103) && !defined(WB32F3G71xx) && !defined(WB32FQ95xx) && !defined(AT32F415)
146 .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without... 146 .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without...
147# endif 147# endif
148# if defined(AT32F415)
149 .spt2 = ADC_SPT2_CSPT_AN0(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN1(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN2(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN3(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN4(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN5(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN6(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN7(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN8(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN9(ADC_SAMPLING_RATE),
150 .spt1 = ADC_SPT1_CSPT_AN10(ADC_SAMPLING_RATE) | ADC_SPT1_CSPT_AN11(ADC_SAMPLING_RATE) | ADC_SPT1_CSPT_AN12(ADC_SAMPLING_RATE) | ADC_SPT1_CSPT_AN13(ADC_SAMPLING_RATE) | ADC_SPT1_CSPT_AN14(ADC_SAMPLING_RATE) | ADC_SPT1_CSPT_AN15(ADC_SAMPLING_RATE),
151# else
148 .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), 152 .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),
149 .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), 153 .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),
154# endif
150#elif defined(RP2040) 155#elif defined(RP2040)
151// RP2040 does not have any extra config here 156// RP2040 does not have any extra config here
152#else 157#else
@@ -242,7 +247,7 @@ __attribute__((weak)) adc_mux pinToMux(pin_t pin) {
242 case F9: return TO_MUX( ADC_CHANNEL_IN7, 2 ); 247 case F9: return TO_MUX( ADC_CHANNEL_IN7, 2 );
243 case F10: return TO_MUX( ADC_CHANNEL_IN8, 2 ); 248 case F10: return TO_MUX( ADC_CHANNEL_IN8, 2 );
244# endif 249# endif
245#elif defined(STM32F1XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) 250#elif defined(STM32F1XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) || defined(AT32F415)
246 case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 ); 251 case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 );
247 case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 ); 252 case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 );
248 case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 ); 253 case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 );
@@ -344,7 +349,7 @@ __attribute__((weak)) adc_mux pinToMux(pin_t pin) {
344 349
345static inline ADCDriver* intToADCDriver(uint8_t adcInt) { 350static inline ADCDriver* intToADCDriver(uint8_t adcInt) {
346 switch (adcInt) { 351 switch (adcInt) {
347#if RP_ADC_USE_ADC1 || STM32_ADC_USE_ADC1 || WB32_ADC_USE_ADC1 352#if RP_ADC_USE_ADC1 || STM32_ADC_USE_ADC1 || WB32_ADC_USE_ADC1 || AT32_ADC_USE_ADC1
348 case 0: 353 case 0:
349 return &ADCD1; 354 return &ADCD1;
350#endif 355#endif
@@ -391,7 +396,11 @@ int16_t adc_read(adc_mux mux) {
391 // TODO: fix previous assumption of only 1 input... 396 // TODO: fix previous assumption of only 1 input...
392 adcConversionGroup.chselr = 1 << mux.input; /*no macro to convert N to ADC_CHSELR_CHSEL1*/ 397 adcConversionGroup.chselr = 1 << mux.input; /*no macro to convert N to ADC_CHSELR_CHSEL1*/
393#elif defined(USE_ADCV2) 398#elif defined(USE_ADCV2)
399# if defined(AT32F415)
400 adcConversionGroup.osq3 = ADC_OSQ3_OSN1_N(mux.input);
401# else
394 adcConversionGroup.sqr3 = ADC_SQR3_SQ1_N(mux.input); 402 adcConversionGroup.sqr3 = ADC_SQR3_SQ1_N(mux.input);
403# endif
395#elif defined(RP2040) 404#elif defined(RP2040)
396 adcConversionGroup.channel_mask = 1 << mux.input; 405 adcConversionGroup.channel_mask = 1 << mux.input;
397#else 406#else
diff --git a/platforms/chibios/drivers/serial_usart.c b/platforms/chibios/drivers/serial_usart.c
index 767ef8726f..becf3afbce 100644
--- a/platforms/chibios/drivers/serial_usart.c
+++ b/platforms/chibios/drivers/serial_usart.c
@@ -9,6 +9,17 @@
9 9
10#if defined(SERIAL_USART_CONFIG) 10#if defined(SERIAL_USART_CONFIG)
11static QMKSerialConfig serial_config = SERIAL_USART_CONFIG; 11static QMKSerialConfig serial_config = SERIAL_USART_CONFIG;
12#elif defined(MCU_AT32) /* AT32 MCUs */
13static QMKSerialConfig serial_config = {
14 .speed = (SERIAL_USART_SPEED),
15 .ctrl1 = (SERIAL_USART_CTRL1),
16 .ctrl2 = (SERIAL_USART_CTRL2),
17# if !defined(SERIAL_USART_FULL_DUPLEX)
18 .ctrl3 = ((SERIAL_USART_CTRL3) | USART_CTRL3_SLBEN) /* activate half-duplex mode */
19# else
20 .ctrl3 = (SERIAL_USART_CTRL3)
21# endif
22};
12#elif defined(MCU_STM32) /* STM32 MCUs */ 23#elif defined(MCU_STM32) /* STM32 MCUs */
13static QMKSerialConfig serial_config = { 24static QMKSerialConfig serial_config = {
14# if HAL_USE_SERIAL 25# if HAL_USE_SERIAL
@@ -160,7 +171,7 @@ inline bool serial_transport_receive_blocking(uint8_t* destination, const size_t
160 * @brief Initiate pins for USART peripheral. Half-duplex configuration. 171 * @brief Initiate pins for USART peripheral. Half-duplex configuration.
161 */ 172 */
162__attribute__((weak)) void usart_init(void) { 173__attribute__((weak)) void usart_init(void) {
163# if defined(MCU_STM32) /* STM32 MCUs */ 174# if defined(MCU_STM32) || defined(MCU_AT32) /* STM32 and AT32 MCUs */
164# if defined(USE_GPIOV1) 175# if defined(USE_GPIOV1)
165 palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE_OPENDRAIN); 176 palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE_OPENDRAIN);
166# else 177# else
@@ -183,7 +194,7 @@ __attribute__((weak)) void usart_init(void) {
183 * @brief Initiate pins for USART peripheral. Full-duplex configuration. 194 * @brief Initiate pins for USART peripheral. Full-duplex configuration.
184 */ 195 */
185__attribute__((weak)) void usart_init(void) { 196__attribute__((weak)) void usart_init(void) {
186# if defined(MCU_STM32) /* STM32 MCUs */ 197# if defined(MCU_STM32) || defined(MCU_AT32) /* STM32 and AT32 MCUs */
187# if defined(USE_GPIOV1) 198# if defined(USE_GPIOV1)
188 palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE_PUSHPULL); 199 palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE_PUSHPULL);
189 palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_INPUT); 200 palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_INPUT);
diff --git a/platforms/chibios/drivers/serial_usart.h b/platforms/chibios/drivers/serial_usart.h
index dec8a292e9..dbd7673273 100644
--- a/platforms/chibios/drivers/serial_usart.h
+++ b/platforms/chibios/drivers/serial_usart.h
@@ -74,40 +74,75 @@ typedef SIOConfig QMKSerialConfig;
74# endif 74# endif
75#endif 75#endif
76 76
77#if !defined(USART_CR1_M0) 77#if defined(MCU_STM32) /* STM32 MCUs */
78# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so 78# if !defined(USART_CR1_M0)
79#endif 79# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so
80# endif
80 81
81#if !defined(SERIAL_USART_CR1) 82# if !defined(SERIAL_USART_CR1)
82# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length 83# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length
83#endif 84# endif
84 85
85#if !defined(SERIAL_USART_CR2) 86# if !defined(SERIAL_USART_CR2)
86# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits 87# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits
87#endif 88# endif
88 89
89#if !defined(SERIAL_USART_CR3) 90# if !defined(SERIAL_USART_CR3)
90# define SERIAL_USART_CR3 0 91# define SERIAL_USART_CR3 0
91#endif 92# endif
93
94# if defined(USART1_REMAP)
95# define USART_REMAP \
96 do { \
97 (AFIO->MAPR |= AFIO_MAPR_USART1_REMAP); \
98 } while (0)
99# elif defined(USART2_REMAP)
100# define USART_REMAP \
101 do { \
102 (AFIO->MAPR |= AFIO_MAPR_USART2_REMAP); \
103 } while (0)
104# elif defined(USART3_PARTIALREMAP)
105# define USART_REMAP \
106 do { \
107 (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP); \
108 } while (0)
109# elif defined(USART3_FULLREMAP)
110# define USART_REMAP \
111 do { \
112 (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); \
113 } while (0)
114# endif
115#elif defined(MCU_AT32) /* AT32 MCUs */
116# if !defined(USART_CTRL1_DBN0)
117# define USART_CTRL1_DBN0 USART_CTRL1_DBN
118# endif
92 119
93#if defined(USART1_REMAP) 120# if !defined(SERIAL_USART_CTRL1)
94# define USART_REMAP \ 121# define SERIAL_USART_CTRL1 (USART_CTRL1_PEN | USART_CTRL1_PSEL | USART_CTRL1_DBN0) // parity enable, odd parity, 9 bit length
95 do { \ 122# endif
96 (AFIO->MAPR |= AFIO_MAPR_USART1_REMAP); \ 123
97 } while (0) 124# if !defined(SERIAL_USART_CTRL2)
98#elif defined(USART2_REMAP) 125# define SERIAL_USART_CTRL2 (USART_CTRL2_STOPBN_1) // 2 stop bits
99# define USART_REMAP \ 126# endif
100 do { \ 127
101 (AFIO->MAPR |= AFIO_MAPR_USART2_REMAP); \ 128# if !defined(SERIAL_USART_CTRL3)
102 } while (0) 129# define SERIAL_USART_CTRL3 0
103#elif defined(USART3_PARTIALREMAP) 130# endif
104# define USART_REMAP \ 131
105 do { \ 132# if defined(USART1_REMAP)
106 (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP); \ 133# define USART_REMAP \
107 } while (0) 134 do { \
108#elif defined(USART3_FULLREMAP) 135 (IOMUX->REMAP |= IOMUX_REMAP_USART1_MUX); \
109# define USART_REMAP \ 136 } while (0)
110 do { \ 137# elif defined(USART3_PARTIALREMAP)
111 (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); \ 138# define USART_REMAP \
112 } while (0) 139 do { \
140 (IOMUX->REMAP |= IOMUX_REMAP_USART3_MUX_MUX1); \
141 } while (0)
142# elif defined(USART3_FULLREMAP)
143# define USART_REMAP \
144 do { \
145 (IOMUX->REMAP |= IOMUX_REMAP_USART3_MUX_MUX2); \
146 } while (0)
147# endif
113#endif 148#endif
diff --git a/platforms/chibios/drivers/spi_master.c b/platforms/chibios/drivers/spi_master.c
index cbe765e233..6417b7077f 100644
--- a/platforms/chibios/drivers/spi_master.c
+++ b/platforms/chibios/drivers/spi_master.c
@@ -103,9 +103,15 @@ bool spi_start_extended(spi_start_config_t *start_config) {
103 roundedDivisor <<= 1; 103 roundedDivisor <<= 1;
104 } 104 }
105 105
106# if defined(AT32F415)
107 if (roundedDivisor < 2 || roundedDivisor > 1024) {
108 return false;
109 }
110# else
106 if (roundedDivisor < 2 || roundedDivisor > 256) { 111 if (roundedDivisor < 2 || roundedDivisor > 256) {
107 return false; 112 return false;
108 } 113 }
114# endif
109#endif 115#endif
110 116
111#if defined(K20x) || defined(KL2x) 117#if defined(K20x) || defined(KL2x)
@@ -240,6 +246,59 @@ bool spi_start_extended(spi_start_config_t *start_config) {
240 spiConfig.SSPCR0 |= SPI_SSPCR0_SPH; // Clock phase: sample on second edge transition 246 spiConfig.SSPCR0 |= SPI_SSPCR0_SPH; // Clock phase: sample on second edge transition
241 break; 247 break;
242 } 248 }
249#elif defined(AT32F415)
250 spiConfig.ctrl1 = 0;
251
252 if (lsbFirst) {
253 spiConfig.ctrl1 |= SPI_CTRL1_LTF;
254 }
255
256 switch (mode) {
257 case 0:
258 break;
259 case 1:
260 spiConfig.ctrl1 |= SPI_CTRL1_CLKPHA;
261 break;
262 case 2:
263 spiConfig.ctrl1 |= SPI_CTRL1_CLKPOL;
264 break;
265 case 3:
266 spiConfig.ctrl1 |= SPI_CTRL1_CLKPHA | SPI_CTRL1_CLKPOL;
267 break;
268 }
269
270 switch (roundedDivisor) {
271 case 2:
272 break;
273 case 4:
274 spiConfig.ctrl1 |= SPI_CTRL1_MDIV_0;
275 break;
276 case 8:
277 spiConfig.ctrl1 |= SPI_CTRL1_MDIV_1;
278 break;
279 case 16:
280 spiConfig.ctrl1 |= SPI_CTRL1_MDIV_1 | SPI_CTRL1_MDIV_0;
281 break;
282 case 32:
283 spiConfig.ctrl1 |= SPI_CTRL1_MDIV_2;
284 break;
285 case 64:
286 spiConfig.ctrl1 |= SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_0;
287 break;
288 case 128:
289 spiConfig.ctrl1 |= SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_1;
290 break;
291 case 256:
292 spiConfig.ctrl1 |= SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_1 | SPI_CTRL1_MDIV_0;
293 break;
294 case 512:
295 spiConfig.ctrl2 |= SPI_CTRL1_MDIV_3;
296 break;
297 case 1024:
298 spiConfig.ctrl2 |= SPI_CTRL1_MDIV_3;
299 spiConfig.ctrl1 |= SPI_CTRL1_MDIV_0;
300 break;
301 }
243#else 302#else
244 spiConfig.cr1 = 0; 303 spiConfig.cr1 = 0;
245 304
diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c
index f49c4a45b0..fed16d20b1 100644
--- a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c
+++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c
@@ -33,7 +33,7 @@ static inline uint32_t detect_flash_size(void) {
33#elif defined(FLASH_SIZE) 33#elif defined(FLASH_SIZE)
34 return FLASH_SIZE; 34 return FLASH_SIZE;
35#elif defined(FLASHSIZE_BASE) 35#elif defined(FLASHSIZE_BASE)
36# if defined(QMK_MCU_SERIES_STM32F0XX) || defined(QMK_MCU_SERIES_STM32F1XX) || defined(QMK_MCU_SERIES_STM32F3XX) || defined(QMK_MCU_SERIES_STM32F4XX) || defined(QMK_MCU_SERIES_STM32G4XX) || defined(QMK_MCU_SERIES_STM32L0XX) || defined(QMK_MCU_SERIES_STM32L4XX) || defined(QMK_MCU_SERIES_GD32VF103) 36# if defined(QMK_MCU_SERIES_STM32F0XX) || defined(QMK_MCU_SERIES_STM32F1XX) || defined(QMK_MCU_SERIES_STM32F3XX) || defined(QMK_MCU_SERIES_STM32F4XX) || defined(QMK_MCU_SERIES_STM32G4XX) || defined(QMK_MCU_SERIES_STM32L0XX) || defined(QMK_MCU_SERIES_STM32L4XX) || defined(QMK_MCU_SERIES_AT32F415) || defined(QMK_MCU_SERIES_GD32VF103)
37 return ((*(uint32_t *)FLASHSIZE_BASE) & 0xFFFFU) << 10U; // this register has the flash size in kB, so we convert it to bytes 37 return ((*(uint32_t *)FLASHSIZE_BASE) & 0xFFFFU) << 10U; // this register has the flash size in kB, so we convert it to bytes
38# elif defined(QMK_MCU_SERIES_STM32L1XX) 38# elif defined(QMK_MCU_SERIES_STM32L1XX)
39# error This MCU family has an uncommon flash size register definition and has not been implemented. Perhaps try using the true EEPROM on the MCU instead? 39# error This MCU family has an uncommon flash size register definition and has not been implemented. Perhaps try using the true EEPROM on the MCU instead?
diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h
index 0f0fa694e9..f09f824bd8 100644
--- a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h
+++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h
@@ -16,6 +16,8 @@
16# define BACKING_STORE_WRITE_SIZE 4 // from hal_efl_lld.c 16# define BACKING_STORE_WRITE_SIZE 4 // from hal_efl_lld.c
17# elif defined(QMK_MCU_FAMILY_WB32) 17# elif defined(QMK_MCU_FAMILY_WB32)
18# define BACKING_STORE_WRITE_SIZE 8 // from hal_efl_lld.c 18# define BACKING_STORE_WRITE_SIZE 8 // from hal_efl_lld.c
19# elif defined(QMK_MCU_FAMILY_AT32)
20# define BACKING_STORE_WRITE_SIZE 2 // from hal_efl_lld.c
19# elif defined(QMK_MCU_FAMILY_STM32) 21# elif defined(QMK_MCU_FAMILY_STM32)
20# if defined(STM32_FLASH_LINE_SIZE) // from some family's stm32_registry.h file 22# if defined(STM32_FLASH_LINE_SIZE) // from some family's stm32_registry.h file
21# define BACKING_STORE_WRITE_SIZE (STM32_FLASH_LINE_SIZE) 23# define BACKING_STORE_WRITE_SIZE (STM32_FLASH_LINE_SIZE)
diff --git a/platforms/chibios/drivers/ws2812_bitbang.c b/platforms/chibios/drivers/ws2812_bitbang.c
index fce1963d0a..a88c5ff619 100644
--- a/platforms/chibios/drivers/ws2812_bitbang.c
+++ b/platforms/chibios/drivers/ws2812_bitbang.c
@@ -11,7 +11,7 @@
11/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */ 11/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */
12 12
13#ifndef WS2812_BITBANG_NOP_FUDGE 13#ifndef WS2812_BITBANG_NOP_FUDGE
14# if defined(STM32F0XX) || defined(STM32F1XX) || defined(GD32VF103) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) || defined(WB32F3G71xx) || defined(WB32FQ95xx) 14# if defined(STM32F0XX) || defined(STM32F1XX) || defined(GD32VF103) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) || defined(WB32F3G71xx) || defined(WB32FQ95xx) || defined(AT32F415)
15# define WS2812_BITBANG_NOP_FUDGE 0.4 15# define WS2812_BITBANG_NOP_FUDGE 0.4
16# else 16# else
17# if defined(RP2040) 17# if defined(RP2040)
diff --git a/platforms/chibios/drivers/ws2812_pwm.c b/platforms/chibios/drivers/ws2812_pwm.c
index c46e9171ab..50927b849a 100644
--- a/platforms/chibios/drivers/ws2812_pwm.c
+++ b/platforms/chibios/drivers/ws2812_pwm.c
@@ -40,6 +40,9 @@
40#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && !defined(WS2812_PWM_DMAMUX_ID) 40#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && !defined(WS2812_PWM_DMAMUX_ID)
41# error "please consult your MCU's datasheet and specify in your config.h: #define WS2812_PWM_DMAMUX_ID STM32_DMAMUX1_TIM?_UP" 41# error "please consult your MCU's datasheet and specify in your config.h: #define WS2812_PWM_DMAMUX_ID STM32_DMAMUX1_TIM?_UP"
42#endif 42#endif
43#if (AT32_DMA_SUPPORTS_DMAMUX == TRUE) && !defined(WS2812_PWM_DMAMUX_CHANNEL) && !defined(WS2812_PWM_DMAMUX_ID)
44# 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"
45#endif
43 46
44/* Summarize https://www.st.com/resource/en/application_note/an4013-stm32-crossseries-timer-overview-stmicroelectronics.pdf to 47/* Summarize https://www.st.com/resource/en/application_note/an4013-stm32-crossseries-timer-overview-stmicroelectronics.pdf to
45 * figure out if we are using a 32bit timer. This is needed to setup the DMA controller correctly. 48 * figure out if we are using a 32bit timer. This is needed to setup the DMA controller correctly.
@@ -269,6 +272,14 @@ typedef uint32_t ws2812_buffer_t;
269# define WS2812_PWM_DMA_PERIPHERAL_WIDTH STM32_DMA_CR_PSIZE_HWORD 272# define WS2812_PWM_DMA_PERIPHERAL_WIDTH STM32_DMA_CR_PSIZE_HWORD
270typedef uint16_t ws2812_buffer_t; 273typedef uint16_t ws2812_buffer_t;
271# endif 274# endif
275#elif defined(AT32F415)
276# define WS2812_PWM_DMA_MEMORY_WIDTH AT32_DMA_CCTRL_MWIDTH_BYTE
277# if defined(WS2812_PWM_TIMER_32BIT)
278# define WS2812_PWM_DMA_PERIPHERAL_WIDTH AT32_DMA_CCTRL_PWIDTH_WORD
279# else
280# define WS2812_PWM_DMA_PERIPHERAL_WIDTH AT32_DMA_CCTRL_PWIDTH_HWORD
281# endif
282typedef uint8_t ws2812_buffer_t;
272#else 283#else
273# define WS2812_PWM_DMA_MEMORY_WIDTH STM32_DMA_CR_MSIZE_BYTE 284# define WS2812_PWM_DMA_MEMORY_WIDTH STM32_DMA_CR_MSIZE_BYTE
274# if defined(WS2812_PWM_TIMER_32BIT) 285# if defined(WS2812_PWM_TIMER_32BIT)
@@ -309,8 +320,13 @@ void ws2812_init(void) {
309 [0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled 320 [0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled
310 [WS2812_PWM_CHANNEL - 1] = {.mode = WS2812_PWM_OUTPUT_MODE, .callback = NULL}, // Turn on the channel we care about 321 [WS2812_PWM_CHANNEL - 1] = {.mode = WS2812_PWM_OUTPUT_MODE, .callback = NULL}, // Turn on the channel we care about
311 }, 322 },
323#if defined(AT32F415)
324 .ctrl2 = 0,
325 .iden = AT32_TMR_IDEN_OVFDEN, // DMA on update event for next period
326#else
312 .cr2 = 0, 327 .cr2 = 0,
313 .dier = TIM_DIER_UDE, // DMA on update event for next period 328 .dier = TIM_DIER_UDE, // DMA on update event for next period
329#endif
314 }; 330 };
315 //#pragma GCC diagnostic pop // Restore command-line warning options 331 //#pragma GCC diagnostic pop // Restore command-line warning options
316 332
@@ -321,6 +337,11 @@ void ws2812_init(void) {
321 dmaStreamSetSource(WS2812_PWM_DMA_STREAM, ws2812_frame_buffer); 337 dmaStreamSetSource(WS2812_PWM_DMA_STREAM, ws2812_frame_buffer);
322 dmaStreamSetDestination(WS2812_PWM_DMA_STREAM, &(WS2812_PWM_DRIVER.tim->CCR[WS2812_PWM_CHANNEL - 1])); // Ziel ist der An-Zeit im Cap-Comp-Register 338 dmaStreamSetDestination(WS2812_PWM_DMA_STREAM, &(WS2812_PWM_DRIVER.tim->CCR[WS2812_PWM_CHANNEL - 1])); // Ziel ist der An-Zeit im Cap-Comp-Register
323 dmaStreamSetMode(WS2812_PWM_DMA_STREAM, WB32_DMA_CHCFG_HWHIF(WS2812_PWM_DMA_CHANNEL) | WB32_DMA_CHCFG_DIR_M2P | WB32_DMA_CHCFG_PSIZE_WORD | WB32_DMA_CHCFG_MSIZE_WORD | WB32_DMA_CHCFG_MINC | WB32_DMA_CHCFG_CIRC | WB32_DMA_CHCFG_TCIE | WB32_DMA_CHCFG_PL(3)); 339 dmaStreamSetMode(WS2812_PWM_DMA_STREAM, WB32_DMA_CHCFG_HWHIF(WS2812_PWM_DMA_CHANNEL) | WB32_DMA_CHCFG_DIR_M2P | WB32_DMA_CHCFG_PSIZE_WORD | WB32_DMA_CHCFG_MSIZE_WORD | WB32_DMA_CHCFG_MINC | WB32_DMA_CHCFG_CIRC | WB32_DMA_CHCFG_TCIE | WB32_DMA_CHCFG_PL(3));
340#elif defined(AT32F415)
341 dmaStreamAlloc(WS2812_PWM_DMA_STREAM - AT32_DMA_STREAM(0), 10, NULL, NULL);
342 dmaStreamSetPeripheral(WS2812_PWM_DMA_STREAM, &(WS2812_PWM_DRIVER.tmr->CDT[WS2812_PWM_CHANNEL - 1])); // Ziel ist der An-Zeit im Cap-Comp-Register
343 dmaStreamSetMemory0(WS2812_PWM_DMA_STREAM, ws2812_frame_buffer);
344 dmaStreamSetMode(WS2812_PWM_DMA_STREAM, AT32_DMA_CCTRL_DTD_M2P | WS2812_PWM_DMA_PERIPHERAL_WIDTH | WS2812_PWM_DMA_MEMORY_WIDTH | AT32_DMA_CCTRL_MINCM | AT32_DMA_CCTRL_LM | AT32_DMA_CCTRL_CHPL(3));
324#else 345#else
325 dmaStreamAlloc(WS2812_PWM_DMA_STREAM - STM32_DMA_STREAM(0), 10, NULL, NULL); 346 dmaStreamAlloc(WS2812_PWM_DMA_STREAM - STM32_DMA_STREAM(0), 10, NULL, NULL);
326 dmaStreamSetPeripheral(WS2812_PWM_DMA_STREAM, &(WS2812_PWM_DRIVER.tim->CCR[WS2812_PWM_CHANNEL - 1])); // Ziel ist der An-Zeit im Cap-Comp-Register 347 dmaStreamSetPeripheral(WS2812_PWM_DMA_STREAM, &(WS2812_PWM_DRIVER.tim->CCR[WS2812_PWM_CHANNEL - 1])); // Ziel ist der An-Zeit im Cap-Comp-Register
@@ -335,6 +356,11 @@ void ws2812_init(void) {
335 dmaSetRequestSource(WS2812_PWM_DMA_STREAM, WS2812_PWM_DMAMUX_ID); 356 dmaSetRequestSource(WS2812_PWM_DMA_STREAM, WS2812_PWM_DMAMUX_ID);
336#endif 357#endif
337 358
359#if (AT32_DMA_SUPPORTS_DMAMUX == TRUE)
360 // If the MCU has a DMAMUX we need to assign the correct resource
361 dmaSetRequestSource(WS2812_PWM_DMA_STREAM, WS2812_PWM_DMAMUX_CHANNEL, WS2812_PWM_DMAMUX_ID);
362#endif
363
338 // Start DMA 364 // Start DMA
339 dmaStreamEnable(WS2812_PWM_DMA_STREAM); 365 dmaStreamEnable(WS2812_PWM_DMA_STREAM);
340 366
diff --git a/platforms/chibios/drivers/ws2812_spi.c b/platforms/chibios/drivers/ws2812_spi.c
index a1357edec5..d1792b871b 100644
--- a/platforms/chibios/drivers/ws2812_spi.c
+++ b/platforms/chibios/drivers/ws2812_spi.c
@@ -40,26 +40,53 @@
40 40
41// Define SPI config speed 41// Define SPI config speed
42// baudrate should target 3.2MHz 42// baudrate should target 3.2MHz
43#if defined(AT32F415)
44# if WS2812_SPI_DIVISOR == 2
45# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (0)
46# elif WS2812_SPI_DIVISOR == 4
47# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_0)
48# elif WS2812_SPI_DIVISOR == 8
49# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_1)
50# elif WS2812_SPI_DIVISOR == 16 // default
51# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_1 | SPI_CTRL1_MDIV_0)
52# elif WS2812_SPI_DIVISOR == 32
53# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_2)
54# elif WS2812_SPI_DIVISOR == 64
55# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_0)
56# elif WS2812_SPI_DIVISOR == 128
57# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_1)
58# elif WS2812_SPI_DIVISOR == 256
59# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_2 | SPI_CTRL1_MDIV_1 | SPI_CTRL1_MDIV_0)
60# elif WS2812_SPI_DIVISOR == 512
61# define WS2812_SPI_DIVISOR_CTRL2_MDIV_X (SPI_CTRL1_MDIV_3)
62# elif WS2812_SPI_DIVISOR == 1024
63# define WS2812_SPI_DIVISOR_CTRL2_MDIV_X (SPI_CTRL1_MDIV_3)
64# define WS2812_SPI_DIVISOR_CTRL1_MDIV_X (SPI_CTRL1_MDIV_0)
65# else
66# error "Configured WS2812_SPI_DIVISOR value is not supported at this time."
67# endif
68#else
43// F072 fpclk = 48MHz 69// F072 fpclk = 48MHz
44// 48/16 = 3Mhz 70// 48/16 = 3Mhz
45#if WS2812_SPI_DIVISOR == 2 71# if WS2812_SPI_DIVISOR == 2
46# define WS2812_SPI_DIVISOR_CR1_BR_X (0) 72# define WS2812_SPI_DIVISOR_CR1_BR_X (0)
47#elif WS2812_SPI_DIVISOR == 4 73# elif WS2812_SPI_DIVISOR == 4
48# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_0) 74# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_0)
49#elif WS2812_SPI_DIVISOR == 8 75# elif WS2812_SPI_DIVISOR == 8
50# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1) 76# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1)
51#elif WS2812_SPI_DIVISOR == 16 // default 77# elif WS2812_SPI_DIVISOR == 16 // default
52# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1 | SPI_CR1_BR_0) 78# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1 | SPI_CR1_BR_0)
53#elif WS2812_SPI_DIVISOR == 32 79# elif WS2812_SPI_DIVISOR == 32
54# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2) 80# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2)
55#elif WS2812_SPI_DIVISOR == 64 81# elif WS2812_SPI_DIVISOR == 64
56# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_0) 82# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_0)
57#elif WS2812_SPI_DIVISOR == 128 83# elif WS2812_SPI_DIVISOR == 128
58# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_1) 84# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_1)
59#elif WS2812_SPI_DIVISOR == 256 85# elif WS2812_SPI_DIVISOR == 256
60# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) 86# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0)
61#else 87# else
62# error "Configured WS2812_SPI_DIVISOR value is not supported at this time." 88# error "Configured WS2812_SPI_DIVISOR value is not supported at this time."
89# endif
63#endif 90#endif
64 91
65// Use SPI circular buffer 92// Use SPI circular buffer
@@ -176,8 +203,16 @@ void ws2812_init(void) {
176 NULL, // error_cb 203 NULL, // error_cb
177 PAL_PORT(WS2812_DI_PIN), 204 PAL_PORT(WS2812_DI_PIN),
178 PAL_PAD(WS2812_DI_PIN), 205 PAL_PAD(WS2812_DI_PIN),
206# if defined(AT32F415)
207 WS2812_SPI_DIVISOR_CTRL1_MDIV_X,
208# if (WS2812_SPI_DIVISOR == 512 || WS2812_SPI_DIVISOR == 1024)
209 WS2812_SPI_DIVISOR_CTRL2_MDIV_X,
210# endif
211 0
212# else
179 WS2812_SPI_DIVISOR_CR1_BR_X, 213 WS2812_SPI_DIVISOR_CR1_BR_X,
180 0 214 0
215# endif
181#endif 216#endif
182 }; 217 };
183 218
diff --git a/platforms/chibios/flash.mk b/platforms/chibios/flash.mk
index 525f177f9e..f4db17a58b 100644
--- a/platforms/chibios/flash.mk
+++ b/platforms/chibios/flash.mk
@@ -113,6 +113,8 @@ else ifeq ($(strip $(MCU_FAMILY)),STM32)
113 $(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL) 113 $(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL)
114else ifeq ($(strip $(MCU_FAMILY)),WB32) 114else ifeq ($(strip $(MCU_FAMILY)),WB32)
115 $(UNSYNC_OUTPUT_CMD) && $(call EXEC_WB32_DFU_UPDATER) 115 $(UNSYNC_OUTPUT_CMD) && $(call EXEC_WB32_DFU_UPDATER)
116else ifeq ($(strip $(MCU_FAMILY)),AT32)
117 $(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL)
116else ifeq ($(strip $(MCU_FAMILY)),GD32V) 118else ifeq ($(strip $(MCU_FAMILY)),GD32V)
117 $(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL) 119 $(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL)
118else 120else
diff --git a/platforms/chibios/mcu_selection.mk b/platforms/chibios/mcu_selection.mk
index a1597fa1e9..086a2b31c6 100644
--- a/platforms/chibios/mcu_selection.mk
+++ b/platforms/chibios/mcu_selection.mk
@@ -809,6 +809,40 @@ ifneq ($(findstring WB32FQ95, $(MCU)),)
809 WB32_BOOTLOADER_ADDRESS ?= 0x1FFFE000 809 WB32_BOOTLOADER_ADDRESS ?= 0x1FFFE000
810endif 810endif
811 811
812ifneq ($(findstring AT32F415, $(MCU)),)
813 # Cortex version
814 MCU = cortex-m4
815
816 # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
817 ARMV = 7
818
819 ## chip/board settings
820 # - the next two should match the directories in
821 # <chibios[-contrib]>/os/hal/ports/$(MCU_PORT_NAME)/$(MCU_SERIES)
822 # OR
823 # <chibios[-contrib]>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
824 MCU_FAMILY = AT32
825 MCU_SERIES = AT32F415
826
827 # Linker script to use
828 # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
829 # or <keyboard_dir>/ld/
830 MCU_LDSCRIPT ?= AT32F415xB
831
832 # Startup code to use
833 # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
834 MCU_STARTUP ?= at32f415
835
836 # Board: it should exist either in <chibios>/os/hal/boards/,
837 # <keyboard_dir>/boards/, or drivers/boards/
838 BOARD ?= GENERIC_AT32_F415XX
839
840 USE_FPU ?= no
841
842 # Bootloader address for AT32 DFU
843 AT32_BOOTLOADER_ADDRESS ?= 0x1FFFAC00
844endif
845
812ifneq ($(findstring GD32VF103, $(MCU)),) 846ifneq ($(findstring GD32VF103, $(MCU)),)
813 # RISC-V 847 # RISC-V
814 MCU = risc-v 848 MCU = risc-v
diff --git a/platforms/chibios/platform.mk b/platforms/chibios/platform.mk
index 169707966f..cf9fac251e 100644
--- a/platforms/chibios/platform.mk
+++ b/platforms/chibios/platform.mk
@@ -155,6 +155,10 @@ ifdef WB32_BOOTLOADER_ADDRESS
155 OPT_DEFS += -DWB32_BOOTLOADER_ADDRESS=$(WB32_BOOTLOADER_ADDRESS) 155 OPT_DEFS += -DWB32_BOOTLOADER_ADDRESS=$(WB32_BOOTLOADER_ADDRESS)
156endif 156endif
157 157
158ifdef AT32_BOOTLOADER_ADDRESS
159 OPT_DEFS += -DAT32_BOOTLOADER_ADDRESS=$(AT32_BOOTLOADER_ADDRESS)
160endif
161
158# Work out if we need to set up the include for the bootloader definitions 162# Work out if we need to set up the include for the bootloader definitions
159ifneq ("$(wildcard $(KEYBOARD_PATH_5)/bootloader_defs.h)","") 163ifneq ("$(wildcard $(KEYBOARD_PATH_5)/bootloader_defs.h)","")
160 OPT_DEFS += -include $(KEYBOARD_PATH_5)/bootloader_defs.h 164 OPT_DEFS += -include $(KEYBOARD_PATH_5)/bootloader_defs.h