1 /*!
2  * @file        system_apm32f4xx.c
3  *
4  * @brief       CMSIS Cortex-M4 Device Peripheral Access Layer System Source File
5  *
6  * @version     V1.0.2
7  *
8  * @date        2022-06-23
9  *
10  * @attention
11  *
12  *  Copyright (C) 2021-2022 Geehy Semiconductor
13  *
14  *  You may not use this file except in compliance with the
15  *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
16  *
17  *  The program is only for reference, which is distributed in the hope
18  *  that it will be usefull and instructional for customers to develop
19  *  their software. Unless required by applicable law or agreed to in
20  *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
21  *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
23  *  and limitations under the License.
24  */
25 
26 #include "apm32f4xx.h"
27 #include "system_apm32f4xx.h"
28 
29 /** @addtogroup CMSIS
30   @{
31 */
32 
33 /** @addtogroup APM32F4xx_System
34   * @brief APM32F4xx system configuration
35   @{
36 */
37 
38 /** @defgroup System_Macros
39   @{
40 */
41 
42 /* Uncomment the following line if you need to use external SRAM as data memory  */
43 /* #define DATA_IN_ExtSRAM */
44 
45 /* Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */
46 /* #define VECT_TAB_SRAM */
47 
48 /* Vector Table base offset field. This value must be a multiple of 0x200. */
49 #define VECT_TAB_OFFSET  0x00
50 
51 /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_B) * PLL_A */
52 #define PLL_B      8
53 
54 /* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLL_D */
55 #define PLL_D      7
56 
57 #define PLL_A      336
58 /* SYSCLK = PLL_VCO / PLL_C */
59 #define PLL_C      2
60 
61 /**@} end of group System_Macros*/
62 
63 /** @defgroup System_Variables
64   @{
65 */
66 
67 /**
68  * @brief    APM32F4xx_System_Private_Variables
69  */
70 
71 uint32_t SystemCoreClock = 168000000;
72 
73 __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
74 
75 /**@} end of group System_Variables */
76 
77 /** @defgroup System_Functions
78   @{
79 */
80 
81 /**
82  * @brief    APM32F4xx_System_Private_FunctionPrototypes
83  */
84 
85 static void SystemClockConfig(void);
86 
87 #if defined(DATA_IN_ExtSRAM)
88     static void SystemInit_ExtSRAM(void);
89 #endif /* DATA_IN_ExtSRAM */
90 
91 /*!
92  * @brief       Setup the microcontroller system
93  *
94  * @param       None
95  *
96  * @retval      None
97  */
SystemInit(void)98 void SystemInit(void)
99 {
100     /* FPU settings */
101 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
102     SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); //!< set CP10 and CP11 Full Access
103 #endif
104     /* Reset the RCM clock configuration to the default reset state */
105     /* Set HSIEN bit */
106     RCM->CTRL_B.HSIEN = BIT_SET;
107 
108     /* Reset CFG register */
109     RCM->CFG = 0x00000000;
110 
111     /* Reset HSEEN, CSSEN and PLL1EN bits */
112     RCM->CTRL &= (uint32_t)0xFEF6FFFF;
113 
114     /* Reset PLL1CFG register */
115     RCM->PLL1CFG = 0x24003010;
116 
117     /* Reset HSEBCFG bit */
118     RCM->CTRL &= (uint32_t)0xFFFBFFFF;
119 
120     /* Disable all interrupts */
121     RCM->INT = 0x00000000;
122 
123 #if defined(DATA_IN_ExtSRAM)
124     SystemInit_ExtSRAM();
125 #endif /* DATA_IN_ExtSRAM */
126 
127     SystemClockConfig();
128 
129     /* Configure the Vector Table location add offset address */
130 #ifdef VECT_TAB_SRAM
131     SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
132 #else
133     SCB->VTOR = FMC_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
134 #endif
135 }
136 
137 /*!
138  * @brief       Update SystemCoreClock variable according to Clock Register Values
139  *              The SystemCoreClock variable contains the core clock (HCLK)
140  *
141  * @param       None
142  *
143  * @retval      None
144  */
SystemCoreClockUpdate(void)145 void SystemCoreClockUpdate(void)
146 {
147     uint32_t sysClock, pllvco, pllc, pllClock, pllb;
148 
149     /* Get SYSCLK source */
150     sysClock = RCM->CFG_B.SCLKSWSTS;
151 
152     switch (sysClock)
153     {
154     case 0:
155         SystemCoreClock = HSI_VALUE;
156         break;
157 
158     case 1:
159         SystemCoreClock = HSE_VALUE;
160         break;
161 
162     case 2:
163         pllClock = RCM->PLL1CFG_B.PLL1CLKS;
164         pllb = RCM->PLL1CFG_B.PLLB;
165 
166         if (pllClock == 0)
167         {
168             /* HSI used as PLL clock source */
169             pllvco = (HSI_VALUE / pllb) * (RCM->PLL1CFG_B.PLL1A); //!< PLL_VCO = (HSI_VALUE / PLL_B) * PLL_A */
170         }
171         else
172         {
173             /* HSE used as PLL clock source */
174             pllvco = (HSE_VALUE / pllb) * (RCM->PLL1CFG_B.PLL1A); //!< PLL_VCO = (HSE_VALUE / PLL_B) * PLL_A */
175         }
176 
177         pllc = ((RCM->PLL1CFG_B.PLL1C) + 1) * 2;
178         SystemCoreClock = pllvco / pllc;
179         break;
180 
181     default:
182         SystemCoreClock = HSI_VALUE;
183         break;
184     }
185 
186     /* Compute HCLK frequency */
187     /* Get HCLK prescaler */
188     sysClock = AHBPrescTable[(RCM->CFG_B.AHBPSC)];
189     /* HCLK frequency */
190     SystemCoreClock >>= sysClock;
191 }
192 
193 /*!
194  * @brief     Configures the System clock source, PLL Multiplier and Divider factors,
195  *            AHB/APBx prescalers and Flash settings
196  *
197  * @param     None
198  *
199  * @retval    None
200  */
SystemClockConfig(void)201 static void SystemClockConfig(void)
202 {
203     __IO uint32_t i;
204 
205     RCM->CTRL_B.HSEEN = BIT_SET;
206 
207     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
208     {
209         if (RCM->CTRL_B.HSERDYFLG)
210         {
211             break;
212         }
213     }
214 
215     if (RCM->CTRL_B.HSERDYFLG)
216     {
217         /* Select regulator voltage output Scale 1 mode */
218         RCM->APB1CLKEN_B.PMUEN = BIT_SET;
219         PMU->CTRL_B.VOSSEL = BIT_SET;
220 
221         /* HCLK = SYSCLK / 1*/
222         RCM->CFG_B.AHBPSC = 0x0000;
223 
224         /* PCLK2 = HCLK / 2*/
225         RCM->CFG_B.APB2PSC = 0x04;
226 
227         /* PCLK1 = HCLK / 4*/
228         RCM->CFG_B.APB1PSC = 0x05;
229 
230         /* Configure the main PLL */
231         RCM->PLL1CFG = PLL_B | (PLL_A << 6) | (((PLL_C >> 1) - 1) << 16) | (PLL_D << 24);
232         RCM->PLL1CFG_B.PLL1CLKS = 0x01;
233 
234         /* Enable the main PLL */
235         RCM->CTRL_B.PLL1EN = BIT_SET;
236 
237         /* Wait till the main PLL is ready */
238         while (RCM->CTRL_B.PLL1RDYFLG == 0)
239         {
240         }
241 
242         /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
243         FMC->ACCTRL = 0x05 | BIT8 | BIT9 | BIT10;
244 
245         /* Select the main PLL as system clock source */
246         RCM->CFG_B.SCLKSEL = RESET;
247         RCM->CFG_B.SCLKSEL = 0x02;
248 
249         /* Wait till the main PLL is used as system clock source */
250         while ((RCM->CFG_B.SCLKSWSTS) != 0x02)
251         {
252         }
253     }
254     else
255     {
256         /* If HSE fails to start-up, the application will have wrong clock configuration. */
257     }
258 }
259 
260 #if defined (DATA_IN_ExtSRAM)
261 
262 /*!
263  * @brief     Setup the external memory controller. Called in startup_apm32f4xx.s before jump to main.
264  *            This function configures the external SRAM
265  *            This SRAM will be used as program data memory (including heap and stack).
266  *
267  * @param     None
268  *
269  * @retval    None
270  */
SystemInit_ExtSRAM(void)271 void SystemInit_ExtSRAM(void)
272 {
273     /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
274     RCM->AHB1CLKEN |= 0x00000078;
275 
276     /* Connect PDx pins to FMC Alternate function */
277     GPIOD->ALFL  = 0x00cc00cc;
278     GPIOD->ALFH  = 0xcccccccc;
279     /* Configure PDx pins in Alternate function mode */
280     GPIOD->MODE  = 0xaaaa0a0a;
281     /* Configure PDx pins speed to 100 MHz */
282     GPIOD->OSSEL = 0xffff0f0f;
283     /* Configure PDx pins Output type to push-pull */
284     GPIOD->OMODE = 0x00000000;
285     /* No pull-up, pull-down for PDx pins */
286     GPIOD->PUPD  = 0x00000000;
287 
288     /* Connect PEx pins to FMC Alternate function */
289     GPIOE->ALFL  = 0xcccccccc;
290     GPIOE->ALFH  = 0xcccccccc;
291     /* Configure PEx pins in Alternate function mode */
292     GPIOE->MODE  = 0xaaaaaaaa;
293     /* Configure PEx pins speed to 100 MHz */
294     GPIOE->OSSEL = 0xffffffff;
295     /* Configure PEx pins Output type to push-pull */
296     GPIOE->OMODE = 0x00000000;
297     /* No pull-up, pull-down for PEx pins */
298     GPIOE->PUPD  = 0x00000000;
299 
300     /* Connect PFx pins to FMC Alternate function */
301     GPIOF->ALFL  = 0x00cccccc;
302     GPIOF->ALFH  = 0xcccc0000;
303     /* Configure PFx pins in Alternate function mode */
304     GPIOF->MODE  = 0xaa000aaa;
305     /* Configure PFx pins speed to 100 MHz */
306     GPIOF->OSSEL = 0xff000fff;
307     /* Configure PFx pins Output type to push-pull */
308     GPIOF->OMODE = 0x00000000;
309     /* No pull-up, pull-down for PFx pins */
310     GPIOF->PUPD  = 0x00000000;
311 
312     /* Connect PGx pins to FMC Alternate function */
313     GPIOG->ALFL  = 0x00cccccc;
314     GPIOG->ALFH  = 0x000000c0;
315     /* Configure PGx pins in Alternate function mode */
316     GPIOG->MODE  = 0x00080aaa;
317     /* Configure PGx pins speed to 100 MHz */
318     GPIOG->OSSEL = 0x000c0fff;
319     /* Configure PGx pins Output type to push-pull */
320     GPIOG->OMODE = 0x00000000;
321     /* No pull-up, pull-down for PGx pins */
322     GPIOG->PUPD  = 0x00000000;
323 
324     /* FMC Configuration */
325     /* Enable the FMC/SMC interface clock */
326     RCM->AHB3CLKEN |= 0x00000001;
327 
328     /* Configure and enable Bank1_SRAM2 */
329     SMC_Bank1->CSCTRL2  = 0x00001011;
330     SMC_Bank1->CSTIM2   = 0x00000201;
331     SMC_Bank1E->WRTTIM2 = 0x0fffffff;
332 }
333 #endif /* DATA_IN_ExtSRAM */
334 
335 /**@} end of group System_Functions */
336 /**@} end of group APM32F4xx_System */
337 /**@} end of group CMSIS */
338