File : s-stm32-f7x.adb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME COMPONENTS --
4 -- --
5 -- Copyright (C) 2012-2016, Free Software Foundation, Inc. --
6 -- --
7 -- GNAT is free software; you can redistribute it and/or modify it under --
8 -- terms of the GNU General Public License as published by the Free Soft- --
9 -- ware Foundation; either version 3, or (at your option) any later ver- --
10 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
11 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
12 -- or FITNESS FOR A PARTICULAR PURPOSE. --
13 -- --
14 -- --
15 -- --
16 -- --
17 -- --
18 -- You should have received a copy of the GNU General Public License and --
19 -- a copy of the GCC Runtime Library Exception along with this program; --
20 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
21 -- <http://www.gnu.org/licenses/>. --
22 -- --
23 -- GNAT was originally developed by the GNAT team at New York University. --
24 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 -- --
26 ------------------------------------------------------------------------------
27
28 with Ada.Unchecked_Conversion;
29
30 with System.BB.Parameters;
31
32 with Interfaces; use Interfaces;
33 with Interfaces.Bit_Types; use Interfaces.Bit_Types;
34 with Interfaces.STM32.RCC; use Interfaces.STM32.RCC;
35
36 package body System.STM32 is
37
38 package Param renames System.BB.Parameters;
39
40 HPRE_Presc_Table : constant array (AHB_Prescaler_Enum) of Word :=
41 (2, 4, 8, 16, 64, 128, 256, 512);
42
43 PPRE_Presc_Table : constant array (APB_Prescaler_Enum) of Word :=
44 (2, 4, 8, 16);
45
46 -------------------
47 -- System_Clocks --
48 -------------------
49
50 function System_Clocks return RCC_System_Clocks
51 is
52 Source : constant SYSCLK_Source :=
53 SYSCLK_Source'Val (RCC_Periph.CFGR.SWS);
54 Result : RCC_System_Clocks;
55
56 begin
57 case Source is
58
59 -- HSI as source
60
61 when SYSCLK_SRC_HSI =>
62 Result.SYSCLK := Param.HSI_Clock;
63
64 -- HSE as source
65
66 when SYSCLK_SRC_HSE =>
67 Result.SYSCLK := Param.HSE_Clock;
68
69 -- PLL as source
70
71 when SYSCLK_SRC_PLL =>
72 declare
73 Pllm : constant Word := Word (RCC_Periph.PLLCFGR.PLLM);
74 Plln : constant Word := Word (RCC_Periph.PLLCFGR.PLLN);
75 Pllp : constant Word := Word (RCC_Periph.PLLCFGR.PLLP);
76 Pllvco : Word;
77
78 begin
79 case PLL_Source'Val (RCC_Periph.PLLCFGR.PLLSRC) is
80 when PLL_SRC_HSE =>
81 Pllvco := (Param.HSE_Clock / Pllm) * Plln;
82 when PLL_SRC_HSI =>
83 Pllvco := (Param.HSI_Clock / Pllm) * Plln;
84 end case;
85
86 Result.SYSCLK := Pllvco / ((Pllp + 1) * 2);
87 end;
88 end case;
89
90 declare
91 function To_AHBP is new Ada.Unchecked_Conversion
92 (CFGR_HPRE_Field, AHB_Prescaler);
93 function To_APBP is new Ada.Unchecked_Conversion
94 (CFGR_PPRE_Element, APB_Prescaler);
95
96 HPRE : constant AHB_Prescaler := To_AHBP (RCC_Periph.CFGR.HPRE);
97 HPRE_Div : constant Word := (if HPRE.Enabled
98 then HPRE_Presc_Table (HPRE.Value)
99 else 1);
100 PPRE1 : constant APB_Prescaler :=
101 To_APBP (RCC_Periph.CFGR.PPRE.Arr (1));
102 PPRE1_Div : constant Word := (if PPRE1.Enabled
103 then PPRE_Presc_Table (PPRE1.Value)
104 else 1);
105 PPRE2 : constant APB_Prescaler :=
106 To_APBP (RCC_Periph.CFGR.PPRE.Arr (2));
107 PPRE2_Div : constant Word := (if PPRE2.Enabled
108 then PPRE_Presc_Table (PPRE2.Value)
109 else 1);
110
111 begin
112 Result.HCLK := Result.SYSCLK / HPRE_Div;
113 Result.PCLK1 := Result.HCLK / PPRE1_Div;
114 Result.PCLK2 := Result.HCLK / PPRE2_Div;
115
116 -- Timer clocks
117 -- See Dedicated clock cfg register documentation.
118 if RCC_Periph.DKCFGR1.TIMPRE = 0 then
119 -- Mode 0:
120 -- If the APB prescaler (PPRE1, PPRE2 in the RCC_CFGR register)
121 -- is configured to a division factor of 1, TIMxCLK = PCLKx.
122 -- Otherwise, the timer clock frequencies are set to twice to the
123 -- frequency of the APB domain to which the timers are connected :
124 -- TIMxCLK = 2xPCLKx.
125 if not PPRE1.Enabled then
126 Result.TIMCLK1 := Result.PCLK1;
127 else
128 Result.TIMCLK1 := Result.PCLK1 * 2;
129 end if;
130
131 if not PPRE2.Enabled then
132 Result.TIMCLK2 := Result.PCLK2;
133 else
134 Result.TIMCLK2 := Result.PCLK2 * 2;
135 end if;
136
137 else
138 -- Mode 1:
139 -- If the APB prescaler (PPRE1, PPRE2 in the RCC_CFGR register) is
140 -- configured to a division factor of 1, 2 or 4, TIMxCLK = HCLK.
141 -- Otherwise, the timer clock frequencies are set to four times
142 -- to the frequency of the APB domain to which the timers are
143 -- connected : TIMxCLK = 4xPCLKx.
144 if PPRE1_Div in 1 .. 4 then
145 Result.TIMCLK1 := Result.HCLK;
146 else
147 Result.TIMCLK1 := Result.PCLK1 * 4;
148 end if;
149 if PPRE2_Div in 1 .. 4 then
150 Result.TIMCLK2 := Result.HCLK;
151 else
152 Result.TIMCLK2 := Result.PCLK1 * 4;
153 end if;
154 end if;
155 end;
156
157 return Result;
158 end System_Clocks;
159
160 end System.STM32;