1 /*!
2 \file gd32a50x_syscfg.c
3 \brief SYSCFG driver
4
5 \version 2022-01-30, V1.0.0, firmware for GD32A50x
6 */
7
8 /*
9 Copyright (c) 2022, GigaDevice Semiconductor Inc.
10
11 Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13
14 1. Redistributions of source code must retain the above copyright notice, this
15 list of conditions and the following disclaimer.
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 3. Neither the name of the copyright holder nor the names of its contributors
20 may be used to endorse or promote products derived from this software without
21 specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 OF SUCH DAMAGE.
33 */
34
35 #include "gd32a50x_syscfg.h"
36
37 /* SYSCFG parameter mask */
38 #define SYSCFG_TIMER0_ETI_SEL_MASK (uint32_t)0x3FFFFFFFU /*!< mask value of SYSCFG_TIMER0_ETI_SEL bits */
39 #define SYSCFG_TIMER7_ETI_SEL_MASK (uint32_t)0xCFFFFFFFU /*!< mask value of SYSCFG_TIMER7_ETI_SEL bits */
40 #define SYSCFG_TIMER19_ETI_SEL_MASK (uint32_t)0xFCFFFFFFU /*!< mask value of SYSCFG_TIMER19_ETI_SEL bits */
41 #define SYSCFG_TIMER20_ETI_SEL_MASK (uint32_t)0xFF3FFFFFU /*!< mask value of SYSCFG_TIMER20_ETI_SEL bits */
42 #define SYSCFG_CFG0_BOOTMODE_MASK (uint8_t)0x03U /*!< mask value of SYSCFG_CFG0_BOOT_MODE bits */
43
44 /* SYSCFG parameter offset */
45 #define SYSCFG_TIMER0_ETI_SEL_OFFSET (uint32_t)30U /*!< offset value of SYSCFG_TIMER0_ETI_SEL bits */
46 #define SYSCFG_TIMER7_ETI_SEL_OFFSET (uint32_t)28U /*!< offset value of SYSCFG_TIMER7_ETI_SEL bits */
47 #define SYSCFG_TIMER19_ETI_SEL_OFFSET (uint32_t)24U /*!< offset value of SYSCFG_TIMER19_ETI_SEL bits */
48 #define SYSCFG_TIMER20_ETI_SEL_OFFSET (uint32_t)22U /*!< offset value of SYSCFG_TIMER20_ETI_SEL bits */
49 #define SYSCFG_CFG3_SRAMECCEADDR_OFFSET (uint8_t)18U /*!< offset value of SYSCFG_CFG3_SRAMECCEADDR bits */
50 #define SYSCFG_CFG3_SRAMECCSERRBIT_OFFSET (uint8_t)12U /*!< offset value of SYSCFG_CFG3_SRAMECCSERRBITS bits */
51
52 /*!
53 \brief reset the SYSCFG registers
54 \param[in] none
55 \param[out] none
56 \retval none
57 */
syscfg_deinit(void)58 void syscfg_deinit(void)
59 {
60 rcu_periph_reset_enable(RCU_SYSCFGRST);
61 rcu_periph_reset_disable(RCU_SYSCFGRST);
62 }
63
64 /*!
65 \brief configure the GPIO pin as EXTI Line
66 \param[in] exti_port: specify the gpio port used in EXTI
67 only one parameter can be selected which is shown as below:
68 \arg EXTI_SOURCE_GPIOx(x = A,B,C,D,E,F): EXTI gpio port
69 \param[in] exti_pin: specify the EXTI line
70 only one parameter can be selected which is shown as below:
71 \arg EXTI_SOURCE_PINx(for GPIOA\GPIOB\GPIOC\GPIOD\GPIOE, x = 0..15, for GPIOF, x = 0..7): EXTI GPIO pin
72 \param[out] none
73 \retval none
74 */
syscfg_exti_line_config(uint8_t exti_port,uint8_t exti_pin)75 void syscfg_exti_line_config(uint8_t exti_port, uint8_t exti_pin)
76 {
77 uint32_t clear_exti_mask = ~((uint32_t)EXTI_SS_MASK << (EXTI_SS_MSTEP(exti_pin)));
78 uint32_t config_exti_mask = ((uint32_t)exti_port) << (EXTI_SS_MSTEP(exti_pin));
79
80 switch(exti_pin / EXTI_SS_JSTEP) {
81 case EXTISS0:
82 /* clear EXTI source line(0..3) */
83 SYSCFG_EXTISS0 &= clear_exti_mask;
84 /* configure EXTI soure line(0..3) */
85 SYSCFG_EXTISS0 |= config_exti_mask;
86 break;
87 case EXTISS1:
88 /* clear EXTI soure line(4..7) */
89 SYSCFG_EXTISS1 &= clear_exti_mask;
90 /* configure EXTI soure line(4..7) */
91 SYSCFG_EXTISS1 |= config_exti_mask;
92 break;
93 case EXTISS2:
94 /* clear EXTI soure line(8..11) */
95 SYSCFG_EXTISS2 &= clear_exti_mask;
96 /* configure EXTI soure line(8..11) */
97 SYSCFG_EXTISS2 |= config_exti_mask;
98 break;
99 case EXTISS3:
100 /* clear EXTI soure line(12..15) */
101 SYSCFG_EXTISS3 &= clear_exti_mask;
102 /* configure EXTI soure line(12..15) */
103 SYSCFG_EXTISS3 |= config_exti_mask;
104 break;
105 default:
106 break;
107 }
108 }
109
110 /*!
111 \brief enable remap pin function
112 \param[in] remap_pin: specify pin
113 only one parameter can be selected which are shown as below:
114 \arg SYSCFG_PA9_PA12_REMAP: PA9/PA12 pins are mapping on PA10/PA11 pins
115 \arg SYSCFG_BOOT0_REMAP_PF0: PF0 pin is mapping on the BOOT0 pin
116 \param[out] none
117 \retval none
118 */
syscfg_pin_remap_enable(uint32_t remap_pin)119 void syscfg_pin_remap_enable(uint32_t remap_pin)
120 {
121 SYSCFG_CFG0 |= remap_pin;
122 }
123
124 /*!
125 \brief disable remap pin function
126 \param[in] remap_pin: specify pin
127 only one parameter can be selected which are shown as below:
128 \arg SYSCFG_PA9_PA12_REMAP: PA9/PA12 pins are mapping on PA10/PA11 pins
129 \arg SYSCFG_BOOT0_REMAP_PF0: PF0 pin is mapping on the BOOT0 pin
130 \param[out] none
131 \retval none
132 */
syscfg_pin_remap_disable(uint32_t remap_pin)133 void syscfg_pin_remap_disable(uint32_t remap_pin)
134 {
135 SYSCFG_CFG0 &= ~remap_pin;
136 }
137
138 /*!
139 \brief configure ADC channel GPIO pin remap function
140 \param[in] adcx_iny_remap: specify ADC channel
141 only one parameter can be returned which is shown as below:
142 \arg ADC1_IN14_REMAP: ADC1 channel 14 GPIO pin remap
143 \arg ADC1_IN15_REMAP: ADC1 channel 15 GPIO pin remap
144 \arg ADC0_IN8_REMAP: ADC0 channel 8 GPIO pin remap
145 \arg ADC0_IN9_REMAP: ADC0 channel 9 GPIO pin remap
146 \param[in] newvalue: ENABLE or DISABLE
147 \param[out] none
148 \retval none
149 */
syscfg_adc_ch_remap_config(syscfg_adcx_chy_enum adcx_iny_remap,ControlStatus newvalue)150 void syscfg_adc_ch_remap_config(syscfg_adcx_chy_enum adcx_iny_remap, ControlStatus newvalue)
151 {
152 switch(adcx_iny_remap) {
153 case ADC1_IN14_REMAP:
154 /* configure ADC1 channel 14 pin remap function */
155 if(ENABLE == newvalue) {
156 SYSCFG_CFG1 |= SYSCFG_CFG1_ADC1CH14RMP;
157 } else {
158 SYSCFG_CFG1 &= (~SYSCFG_CFG1_ADC1CH14RMP);
159 }
160 break;
161 case ADC1_IN15_REMAP:
162 /* configure ADC1 channel 15 pin remap function */
163 if(ENABLE == newvalue) {
164 SYSCFG_CFG1 |= SYSCFG_CFG1_ADC1CH15RMP;
165 } else {
166 SYSCFG_CFG1 &= (~SYSCFG_CFG1_ADC1CH15RMP);
167 }
168 break;
169 case ADC0_IN8_REMAP:
170 /* configure ADC0 channel 8 pin remap function */
171 if(ENABLE == newvalue) {
172 SYSCFG_CFG1 |= SYSCFG_CFG1_ADC0CH8RMP;
173 } else {
174 SYSCFG_CFG1 &= (~SYSCFG_CFG1_ADC0CH8RMP);
175 }
176 break;
177 case ADC0_IN9_REMAP:
178 /* configure ADC0 channel 9 pin remap function */
179 if(ENABLE == newvalue) {
180 SYSCFG_CFG1 |= SYSCFG_CFG1_ADC0CH9RMP;
181 } else {
182 SYSCFG_CFG1 &= (~SYSCFG_CFG1_ADC0CH9RMP);
183 }
184 break;
185 default:
186 break;
187 }
188 }
189
190 /*!
191 \brief select TIMER external trigger source
192 \param[in] timer_num: specify TIMER
193 only one parameter can be returned which is shown as below:
194 \arg TIMER0SEL: select TIMER0
195 \arg TIMER7SEL: select TIMER7
196 \arg TIMER19SEL: select TIMER19
197 \arg TIMER20SEL: select TIMER20
198 \param[in] etr_num: specify external trigger source
199 only one parameter can be returned which is shown as below:
200 \arg TIMER_ETI_TRGx (x = 0,1,2,3): TIMER external trigger source x
201 \arg TIMER_ETI_TRG_NONE: do not seclet TIMER external trigger source
202 \param[out] none
203 \retval none
204 */
syscfg_timer_eti_sel(syscfg_timersel_enum timer_num,uint32_t eti_num)205 void syscfg_timer_eti_sel(syscfg_timersel_enum timer_num, uint32_t eti_num)
206 {
207 switch(timer_num) {
208 case TIMER0SEL:
209 /* select TIMER0 external trigger source */
210 SYSCFG_TIMERINSEL &= SYSCFG_TIMER0_ETI_SEL_MASK;
211 SYSCFG_TIMERINSEL |= (eti_num << SYSCFG_TIMER0_ETI_SEL_OFFSET);
212 break;
213 case TIMER7SEL:
214 /* select TIMER7 external trigger source */
215 SYSCFG_TIMERINSEL &= SYSCFG_TIMER7_ETI_SEL_MASK;
216 SYSCFG_TIMERINSEL |= (eti_num << SYSCFG_TIMER7_ETI_SEL_OFFSET);
217 break;
218 case TIMER19SEL:
219 /* select TIMER19 external trigger source */
220 SYSCFG_TIMERINSEL &= SYSCFG_TIMER19_ETI_SEL_MASK;
221 SYSCFG_TIMERINSEL |= (eti_num << SYSCFG_TIMER19_ETI_SEL_OFFSET);
222 break;
223 case TIMER20SEL:
224 /* select TIMER20 external trigger source */
225 SYSCFG_TIMERINSEL &= SYSCFG_TIMER20_ETI_SEL_MASK;
226 SYSCFG_TIMERINSEL |= (eti_num << SYSCFG_TIMER20_ETI_SEL_OFFSET);
227 break;
228 default:
229 break;
230 }
231 }
232
233 /*!
234 \brief select TRIGSEL as TIMER break input source
235 \param[in] bkin_source: specify TIMER break input source
236 only one parameter can be selected which are shown as below:
237 \arg TIMERx_BKINy_TRIG (x=0,7,19,20 y=0,1,2,3):TIMERx break input y source select from TRIGSEL
238 \param[out] none
239 \retval none
240 */
syscfg_timer_bkin_select_trigsel(uint32_t bkin_source)241 void syscfg_timer_bkin_select_trigsel(uint32_t bkin_source)
242 {
243 SYSCFG_TIMERINSEL |= (uint32_t)bkin_source;
244 }
245
246 /*!
247 \brief select GPIO as TIMER break input source
248 \param[in] bkin_source: specify TIMER break input source
249 only one parameter can be selected which are shown as below:
250 \arg TIMERx_BKINy_TRIG (x=0,7,19,,20 y=0,1,2,3): TIMERx break input y source select from TRIGSEL
251 \param[out] none
252 \retval none
253 */
syscfg_timer_bkin_select_gpio(uint32_t bkin_source)254 void syscfg_timer_bkin_select_gpio(uint32_t bkin_source)
255 {
256 SYSCFG_TIMERINSEL &= ~(uint32_t)bkin_source;
257 }
258
259 /*!
260 \brief select TIMER7 channel0 complementary input source
261 \param[in] timer7_ch0n_in: specify TIMER7 channel0 complementary input source
262 only one parameter can be returned which is shown as below:
263 \arg TIMER7CH0N_TIMER7CH0_TIMER0CH0_IN : select exclusive or of TIMER7_CH0_IN, TIMER7_CH0N_IN, and TIMER0_CH0_IN
264 \arg TIMER7_CH0N_IN : select TIMER7_CH0N_IN
265 \param[out] none
266 \retval none
267 */
syscfg_timer7_ch0n_select(uint32_t timer7_ch0n_in)268 void syscfg_timer7_ch0n_select(uint32_t timer7_ch0n_in)
269 {
270 if(TIMER7CH0N_TIMER7CH0_TIMER0CH0_IN == timer7_ch0n_in) {
271 /* select exclusive or of TIMER7_CH0_IN, TIMER7_CH0N_IN, and TIMER0_CH0_IN */
272 SYSCFG_TIMERINSEL |= SYSCFG_TIMERINSEL_TIMER7_CH0N_SEL;
273 } else {
274 /* select TIMER7_CH0N_IN */
275 SYSCFG_TIMERINSEL &= TIMER7_CH0N_IN;
276 }
277 }
278
279 /*!
280 \brief configure TIMER0/7/19/20 break input to the selected parameter connection
281 \param[in] syscfg_lock: specify the parameter to be connected
282 only one parameter can be selected which is shown as below:
283 \arg SYSCFG_LOCK_LOCKUP: Cortex-M33 lockup output connected to the break input
284 \arg SYSCFG_LOCK_SRAM_ECC_ERROR: SRAM ECC check error connected to the break input
285 \arg SYSCFG_LOCK_LVD: LVD interrupt connected to the break input
286 \param[out] none
287 \retval none
288 */
syscfg_lock_config(uint32_t syscfg_lock)289 void syscfg_lock_config(uint32_t syscfg_lock)
290 {
291 SYSCFG_CFG2 |= syscfg_lock;
292 }
293
294 /*!
295 \brief get SYSCFG flags
296 \param[in] syscfg_flag: specify the flag in SYSCFG_STAT to check
297 only one parameter can be selected which is shown as below:
298 \arg SYSCFG_FLAG_SRAMECCMERR: SRAM multi-bits non-correction ECC error flag
299 \arg SYSCFG_FLAG_SRAMECCSERR: SRAM single bit correction ECC error flag
300 \arg SYSCFG_FLAG_FLASHECCERR: FLASH ECC NMI error flag
301 \arg SYSCFG_FLAG_CKMNMIERR: HXTAL clock monitor NMI error flag
302 \arg SYSCFG_FLAG_NMIPINERR: NMI pin error flag
303 \param[out] none
304 \retval the syscfg_flag state returned (SET or RESET)
305 */
syscfg_flag_get(uint32_t syscfg_flag)306 FlagStatus syscfg_flag_get(uint32_t syscfg_flag)
307 {
308 if(SYSCFG_STAT & syscfg_flag) {
309 return SET;
310 } else {
311 return RESET;
312 }
313 }
314
315 /*!
316 \brief clear SYSCFG flags
317 \param[in] syscfg_flag: specify the flag in SYSCFG_STAT to check
318 only one parameter can be selected which is shown as below:
319 \arg SYSCFG_FLAG_SRAMECCMERR: SRAM multi-bits non-correction ECC error flag
320 \arg SYSCFG_FLAG_SRAMECCSERR: SRAM single bit correction ECC error flag
321 \arg SYSCFG_FLAG_FLASHECCERR: FLASH ECC NMI error flag
322 \arg SYSCFG_FLAG_CKMNMIERR: HXTAL clock monitor NMI error flag
323 \param[out] none
324 \retval none
325 */
syscfg_flag_clear(uint32_t syscfg_flag)326 void syscfg_flag_clear(uint32_t syscfg_flag)
327 {
328 SYSCFG_STAT |= (uint32_t) syscfg_flag;
329 }
330
331 /*!
332 \brief enable SYSCFG interrupts
333 \param[in] interrupt: specify the interrupt in SYSCFG_CFG3
334 only one parameter can be selected which is shown as below:
335 \arg SYSCFG_INT_SRAMECCME: SRAM multi-bits non-correction ECC error interrupt
336 \arg SYSCFG_INT_SRAMECCSE: SRAM single bit correction ECC error interrupt
337 \arg SYSCFG_INT_FLASHECCE: FLASH ECC NMI error interrupt
338 \arg SYSCFG_INT_CKMNMI: HXTAL clock monitor NMI error interrupt
339 \arg SYSCFG_INT_NMIPIN: NMI pin error interrupt
340 \param[out] none
341 \retval none
342 */
syscfg_interrupt_enable(uint32_t interrupt)343 void syscfg_interrupt_enable(uint32_t interrupt)
344 {
345 SYSCFG_CFG3 |= (uint32_t)interrupt;
346 }
347
348 /*!
349 \brief disable SYSCFG interrupts
350 \param[in] interrupt: specify the interrupt in SYSCFG_CFG3
351 only one parameter can be selected which is shown as below:
352 \arg SYSCFG_INT_SRAMECCME: SRAM multi-bits non-correction ECC error interrupt
353 \arg SYSCFG_INT_SRAMECCSE: SRAM single bit correction ECC error interrupt
354 \arg SYSCFG_INT_FLASHECCE: FLASH ECC NMI error interrupt
355 \arg SYSCFG_INT_CKMNMI: HXTAL clock monitor NMI error interrupt
356 \arg SYSCFG_INT_NMIPIN: NMI pin error interrupt
357 \param[out] none
358 \retval none
359 */
syscfg_interrupt_disable(uint32_t interrupt)360 void syscfg_interrupt_disable(uint32_t interrupt)
361 {
362 SYSCFG_CFG3 &= (uint32_t)(~interrupt);
363 }
364
365 /*!
366 \brief get SYSCFG interrupt flag status
367 \param[in] interrupt: specify the interrupt flag status
368 only one parameter can be selected which is shown as below:
369 \arg SYSCFG_INT_FLAG_SRAMECCMERR: SRAM multi-bits non-correction ECC error interrupt flag
370 \arg SYSCFG_INT_FLAG_SRAMECCSERR: SRAM single bit correction ECC error interrupt flag
371 \arg SYSCFG_INT_FLAG_FLASHECCERR: FLASH ECC NMI error interrupt flag
372 \arg SYSCFG_INT_FLAG_CKMNMIERR: HXTAL clock monitor NMI error interrupt flag
373 \arg SYSCFG_INT_FLAG_NMIPINERR: NMI pin error interrupt flag
374 \param[out] none
375 \retval FlagStatus: SET or RESET
376 */
syscfg_interrupt_flag_get(uint32_t interrupt)377 FlagStatus syscfg_interrupt_flag_get(uint32_t interrupt)
378 {
379 uint32_t reg1 = SYSCFG_STAT;
380 uint32_t reg2 = SYSCFG_CFG3;
381
382 switch(interrupt) {
383 /* SRAM multi-bits non-correction ECC error interrupt */
384 case SYSCFG_INT_FLAG_SRAMECCMERR:
385 reg1 = reg1 & SYSCFG_STAT_SRAMECCMEIF;
386 reg2 = reg2 & SYSCFG_CFG3_SRAMECCMEIE;
387 break;
388 /* SRAM single bit correction ECC error interrupt */
389 case SYSCFG_INT_FLAG_SRAMECCSERR:
390 reg1 = reg1 & SYSCFG_STAT_SRAMECCSEIF;
391 reg2 = reg2 & SYSCFG_CFG3_SRAMECCSEIE;
392 break;
393 /* FLASH ECC NMI error interrupt */
394 case SYSCFG_INT_FLAG_FLASHECCERR:
395 reg1 = reg1 & SYSCFG_STAT_FLASHECCIF;
396 reg2 = reg2 & SYSCFG_CFG3_FLASHECCIE;
397 break;
398 /* HXTAL clock monitor NMI error interrupt */
399 case SYSCFG_INT_FLAG_CKMNMIERR:
400 reg1 = reg1 & SYSCFG_STAT_CKMNMIIF;
401 reg2 = reg2 & SYSCFG_CFG3_CKMNMIIE;
402 break;
403 /* NMI pin error interrupt */
404 case SYSCFG_INT_FLAG_NMIPINERR:
405 reg1 = reg1 & SYSCFG_STAT_NMIPINIF;
406 reg2 = reg2 & SYSCFG_CFG3_NMIPINIE;
407 break;
408 default :
409 break;
410 }
411 /*get SYSCFG interrupt flag status */
412 if(reg1 && reg2) {
413 return SET;
414 } else {
415 return RESET;
416 }
417 }
418
419 /*!
420 \brief get the current boot mode
421 \param[in] none
422 \param[out] none
423 \retval the boot mode
424 \arg SYSCFG_BOOTMODE_FLASH: boot from the main flash
425 \arg SYSCFG_BOOTMODE_SYSTEM: boot from the system flash memory
426 \arg SYSCFG_BOOTMODE_SRAM: boot from the embedded SRAM
427 */
syscfg_bootmode_get(void)428 uint8_t syscfg_bootmode_get(void)
429 {
430 return (uint8_t)(SYSCFG_CFG0 & SYSCFG_CFG0_BOOTMODE_MASK);
431 }
432
433 /*!
434 \brief get the address where SRAM ECC error occur on
435 \param[in] none
436 \param[out] none
437 \retval uint16_t: the address where SRAM ECC error occur on
438 */
syscfg_sram_ecc_address_get(void)439 uint16_t syscfg_sram_ecc_address_get(void)
440 {
441 return (uint16_t)(SYSCFG_CFG3 >> SYSCFG_CFG3_SRAMECCEADDR_OFFSET);
442 }
443
444 /*!
445 \brief get the bit which has SRAM ECC signle error
446 \param[in] none
447 \param[out] none
448 \retval uint8_t: which bit has SRAM ECC signle error
449 */
syscfg_sram_ecc_bit_get(void)450 uint8_t syscfg_sram_ecc_bit_get(void)
451 {
452 return (uint8_t)((SYSCFG_CFG3 & SYSCFG_CFG3_SRAMECCSERRBITS) >> SYSCFG_CFG3_SRAMECCSERRBIT_OFFSET);
453 }
454