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;