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