]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A2F200_IAR_and_Keil/MicroSemi_Code/CMSIS/system_a2fxxxm3.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / CORTEX_A2F200_IAR_and_Keil / MicroSemi_Code / CMSIS / system_a2fxxxm3.c
1 /*******************************************************************************\r
2  * (c) Copyright 2009 Actel Corporation.  All rights reserved.\r
3  * \r
4  *  SmartFusion A2FxxxM3 CMSIS system initialization.\r
5  *\r
6  * SVN $Revision: 2069 $\r
7  * SVN $Date: 2010-01-28 00:23:48 +0000 (Thu, 28 Jan 2010) $\r
8  */\r
9 #include "a2fxxxm3.h"\r
10 #include "mss_assert.h"\r
11 \r
12 /* System frequency (FCLK) coming out of reset is 25MHz. */\r
13 #define RESET_SYSCLCK_FREQ      25000000uL\r
14 \r
15 /*\r
16  * SmartFusion Microcontroller Subsystem FLCK frequency.\r
17  * The value of SMARTFUSION_FCLK_FREQ is used to report the system's clock\r
18  * frequency in system's which either do not use the Actel System Boot or\r
19  * a version of the Actel System Boot older than 1.3.1. In eitehr of these cases\r
20  * SMARTFUSION_FCLK_FREQ should be defined in the projects settings to reflect\r
21  * the FCLK frequency selected in the Libero MSS configurator.\r
22  * Systems using the Actel System Boot version 1.3.1 or later do not require this\r
23  * define since the system's frequency is retrieved from eNVM spare pages where\r
24  * the MSS Configurator stored the frequency selected during hardware design/configuration.\r
25  */\r
26 #ifdef SMARTFUSION_FCLK_FREQ\r
27 #define SMARTFUSION_FCLK_FREQ_DEFINED   1\r
28 #else\r
29 #define SMARTFUSION_FCLK_FREQ_DEFINED   0\r
30 #define SMARTFUSION_FCLK_FREQ    RESET_SYSCLCK_FREQ\r
31 #endif\r
32 \r
33 /* Divider values for APB0, APB1 and ACE clocks. */\r
34 #define RESET_PCLK0_DIV         4uL\r
35 #define RESET_PCLK1_DIV         4uL\r
36 #define RESET_ACE_DIV           4uL\r
37 #define RESET_FPGA_CLK_DIV      4uL\r
38 \r
39 /* System register clock control mask and shift for PCLK dividers. */\r
40 #define PCLK_DIV_MASK       0x00000003uL\r
41 #define PCLK0_DIV_SHIFT     2uL\r
42 #define PCLK1_DIV_SHIFT     4uL\r
43 #define ACE_DIV_SHIFT       6uL\r
44 \r
45 /* System register MSS_CCC_DIV_CR mask and shift for GLB (FPGA fabric clock). */\r
46 #define OBDIV_SHIFT         8uL\r
47 #define OBDIV_MASK          0x0000001FuL\r
48 #define OBDIVHALF_SHIFT     13uL\r
49 #define OBDIVHALF_MASK      0x00000001uL\r
50 \r
51 /*\r
52  * Actel system boot version defines used to extract the system clock from eNVM\r
53  * spare pages.\r
54  * These defines allow detecting the presence of Actel system boot in eNVM spare\r
55  * pages and the version of that system boot executable and associated\r
56  * configuration data.\r
57  */\r
58 #define SYSBOOT_KEY_ADDR        (uint32_t *)0x6008081C\r
59 #define SYSBOOT_KEY_VALUE       0x4C544341uL\r
60 #define SYSBOOT_VERSION_ADDR    (uint32_t *)0x60080840\r
61 #define SYSBOOT_1_3_FCLK_ADDR   (uint32_t *)0x6008162C\r
62 #define SYSBOOT_2_x_FCLK_ADDR   (uint32_t *)0x60081EAC\r
63 \r
64 /*\r
65  * The system boot version is stored in the least significant 24 bits of a word.\r
66  * The FCLK is stored in eNVM from version 1.3.1 of the system boot. We expect\r
67  * that the major version number of the system boot version will change if the\r
68  * system boot configuration data layout needs to change. \r
69  */\r
70 #define SYSBOOT_VERSION_MASK    0x00FFFFFFuL\r
71 #define MIN_SYSBOOT_VERSION     0x00010301uL\r
72 #define SYSBOOT_VERSION_2_X     0x00020000uL\r
73 #define MAX_SYSBOOT_VERSION     0x00030000uL\r
74 \r
75 /* Standard CMSIS global variables. */\r
76 uint32_t SystemFrequency = SMARTFUSION_FCLK_FREQ;          /*!< System Clock Frequency (Core Clock) */\r
77 uint32_t SystemCoreClock = SMARTFUSION_FCLK_FREQ;          /*!< System Clock Frequency (Core Clock) */\r
78 \r
79 /* SmartFusion specific clocks. */\r
80 uint32_t g_FrequencyPCLK0 = (SMARTFUSION_FCLK_FREQ / RESET_PCLK0_DIV);      /*!< Clock frequency of APB bus 0. */  \r
81 uint32_t g_FrequencyPCLK1 = (SMARTFUSION_FCLK_FREQ / RESET_PCLK1_DIV);      /*!< Clock frequency of APB bus 1. */\r
82 uint32_t g_FrequencyACE = (SMARTFUSION_FCLK_FREQ / RESET_ACE_DIV);          /*!< Clock frequency of Analog Compute Engine. */\r
83 uint32_t g_FrequencyFPGA = (SMARTFUSION_FCLK_FREQ / RESET_FPGA_CLK_DIV);    /*!< Clock frequecny of FPGA fabric */\r
84 \r
85 /* Local functions */\r
86 static uint32_t GetSystemClock( void );\r
87 \r
88 /***************************************************************************//**\r
89  * See system_a2fm3fxxx.h for details.\r
90  */\r
91 void SystemInit(void)\r
92 {\r
93 }\r
94 \r
95 /***************************************************************************//**\r
96  *\r
97  */\r
98 void SystemCoreClockUpdate (void)\r
99 {\r
100     uint32_t PclkDiv0;\r
101     uint32_t PclkDiv1;\r
102     uint32_t AceDiv;\r
103     uint32_t FabDiv;\r
104 \r
105     const uint32_t pclk_div_lut[4] = { 1uL, 2uL, 4uL, 1uL };\r
106 \r
107     /* Read PCLK dividers from system registers. Multiply the value read from\r
108      * system register by two to get actual divider value. */\r
109     PclkDiv0 = pclk_div_lut[((SYSREG->MSS_CLK_CR >> PCLK0_DIV_SHIFT) & PCLK_DIV_MASK)];\r
110     PclkDiv1 = pclk_div_lut[((SYSREG->MSS_CLK_CR >> PCLK1_DIV_SHIFT) & PCLK_DIV_MASK)];\r
111     AceDiv = pclk_div_lut[((SYSREG->MSS_CLK_CR >> ACE_DIV_SHIFT) & PCLK_DIV_MASK)];\r
112     {\r
113         /* Compute the FPGA fabric frequency divider. */\r
114         uint32_t obdiv;\r
115         uint32_t obdivhalf;\r
116         \r
117         obdiv = (SYSREG->MSS_CCC_DIV_CR >> OBDIV_SHIFT) & OBDIV_MASK;\r
118         obdivhalf = (SYSREG->MSS_CCC_DIV_CR >> OBDIVHALF_SHIFT) & OBDIVHALF_MASK;\r
119         FabDiv = obdiv + 1uL;\r
120         if ( obdivhalf != 0uL )\r
121         {\r
122             FabDiv = FabDiv * 2uL;\r
123         }\r
124     }\r
125     \r
126     /* Retrieve FCLK from eNVM spare pages if Actel system boot programmed as part of the system. */\r
127     \r
128     /* Read system clock from eNVM spare pages. */\r
129     SystemCoreClock = GetSystemClock();\r
130     g_FrequencyPCLK0 = SystemCoreClock / PclkDiv0;\r
131     g_FrequencyPCLK1 = SystemCoreClock / PclkDiv1;\r
132     g_FrequencyACE = SystemCoreClock / AceDiv;\r
133     g_FrequencyFPGA = SystemCoreClock / FabDiv;\r
134     \r
135     /* Keep SystemFrequency as well as SystemCoreClock for legacy reasons. */\r
136     SystemFrequency = SystemCoreClock;\r
137 }\r
138 \r
139 /***************************************************************************//**\r
140  * Retrieve the system clock frequency from eNVM spare page if available.\r
141  * Returns the frequency defined through SMARTFUSION_FCLK_FREQ if FCLK cannot be\r
142  * retrieved from eNVM spare pages.\r
143  * The FCLK frequency value selected in the MSS Configurator software tool is\r
144  * stored in eNVM spare pages as part of the Actel system boot configuration data.\r
145  */\r
146 uint32_t GetSystemClock( void )\r
147 {\r
148     uint32_t fclk = 0uL;\r
149     \r
150     uint32_t * p_sysboot_key = SYSBOOT_KEY_ADDR;\r
151     \r
152     if ( SYSBOOT_KEY_VALUE == *p_sysboot_key )\r
153     {\r
154         /* Actel system boot programmed, check if it has the FCLK value stored. */\r
155         uint32_t *p_sysboot_version = SYSBOOT_VERSION_ADDR;\r
156         uint32_t sysboot_version = *p_sysboot_version;\r
157         \r
158         sysboot_version &= SYSBOOT_VERSION_MASK;\r
159         \r
160         if ( sysboot_version >= MIN_SYSBOOT_VERSION )\r
161         {\r
162             /* Handle change of eNVM location of FCLK between 1.3.x and 2.x.x versions of the system boot. */\r
163             if ( sysboot_version < SYSBOOT_VERSION_2_X )\r
164             {\r
165                 /* Read FCLK value from MSS configurator generated configuration\r
166                  * data stored in eNVM spare pages as part of system boot version 1.3.x\r
167                  * configuration tables. */\r
168                 uint32_t *p_fclk = SYSBOOT_1_3_FCLK_ADDR;\r
169                 fclk = *p_fclk;\r
170             }\r
171             else if ( sysboot_version < MAX_SYSBOOT_VERSION )\r
172             {\r
173                 /* Read FCLK value from MSS configurator generated configuration\r
174                  * data stored in eNVM spare pages as part of system boot version 2.x.x\r
175                  * configuration tables. */\r
176                 uint32_t *p_fclk = SYSBOOT_2_x_FCLK_ADDR;\r
177                 fclk = *p_fclk;\r
178             }\r
179             else\r
180             {\r
181                 fclk = 0uL;\r
182             }\r
183         }\r
184     }\r
185     \r
186     if ( 0uL == fclk )\r
187     {\r
188         /* \r
189          * Could not retrieve FCLK from system boot configuration data. Fall back\r
190          * to using SMARTFUSION_FCLK_FREQ which must then be defined as part of\r
191          * project settings.\r
192          */\r
193         ASSERT( SMARTFUSION_FCLK_FREQ_DEFINED );\r
194         fclk = SMARTFUSION_FCLK_FREQ;\r
195     }\r
196     \r
197     return fclk;\r
198 }\r
199 \r