Proposed register definition file format

Moderators: dhowells, RobertKleczek, Lucretia

Proposed register definition file format

Postby RobertKleczek » Mon Nov 17, 2014 10:18 pm

Here comes description of proposed register definition file with an example of RCC_F40XXX :

Header:

Code: Select all
--------------------------------------------------------------------------------
--                                                                            --
--                       A R M   A D A   L I B R A R Y                        --
--                                                                            --
--                 A R M . R e g i s t e r . R C C _ F 4 0 X X X              --
--                                   S p e c                                  --
--                                                                            --
--    Copyright (C) 2014  Robert Kleczek                                      --
--                                                                            --
--    This program is free software: you can redistribute it and/or modify    --
--    it under the terms of the GNU General Public License as published by    --
--    the Free Software Foundation, either version 3 of the License, or       --
--    (at your option) any later version.                                     --
--                                                                            --
--    This program is distributed in the hope that it will be useful,         --
--    but WITHOUT ANY WARRANTY; without even the implied warranty of          --
--    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           --
--    GNU General Public License for more details.                            --
--                                                                            --
--    You should have received a copy of the GNU General Public License       --
--    along with this program.  If not, see <http://www.gnu.org/licenses/>.   --
--                                                                            --
--------------------------------------------------------------------------------


Short explanation of file:

Code: Select all
--  Package defines STM32 F40XXX family reset & clock related registers


Importing needed packages (common part):

Code: Select all
-------------------------
--  Imported packages  --
-------------------------

with ARM.Register;
use  ARM.Register;

with ARM.Register.Types;
with ARM.Register.Bitfield;
with ARM.Register.Register;



Start of subsystem definition with file name, package name <model & family pattern>:

Code: Select all
--------------------------------------------------------------------------------
--                            ARM.Register.RCC_F40XXX                         --
--------------------------------------------------------------------------------

package ARM.Register.RCC_F40XXX is

   pragma Preelaborate;

   --------------------------------------------------------------------------
   --                    Reset and Clock Control                           --
   --------------------------------------------------------------------------


Start of register definition <short name>:

Code: Select all
   ----------------------
   --  CR  Register --
   ----------------------


Register package name in format <subsystem>_<register>:

Code: Select all
  package RCC_CR is


Definition of register size (use one of R8, R16, R32).
Respectively up to 8, 16, 32 pools definitions.

Code: Select all
      package Tp is new Types (R32);


Here comes definitions of register pools from highest to lowest bits in format:
package <pool name> is new Bitfield (Tp, <first pool bit position>, [<optional bits pool lenght, if not given => 1>]);

Code: Select all
      package PLLI2SRDY is new Bitfield (Tp, 27);
      package PLLI2SON  is new Bitfield (Tp, 26);
      package PLLRDY    is new Bitfield (Tp, 25);
      package PLLON     is new Bitfield (Tp, 24);
      package CSSON     is new Bitfield (Tp, 19);
      package HSEBYP    is new Bitfield (Tp, 18);
      package HSERDY    is new Bitfield (Tp, 17);
      package HSEON     is new Bitfield (Tp, 16);
      package HSICAL    is new Bitfield (Tp, 8, 8);
      package HSITRIM   is new Bitfield (Tp, 3, 5);
      package HSIRDY    is new Bitfield (Tp, 1);
      package HSION     is new Bitfield (Tp, 0);


Register type definition based on previous pools defs.
See common schema of this:

Code: Select all
      type T is
         record
            PLLI2SRDY : RCC_CR.PLLI2SRDY.T;
            PLLI2SON  : RCC_CR.PLLI2SON .T;
            PLLRDY    : RCC_CR.PLLRDY   .T;
            PLLON     : RCC_CR.PLLON    .T;
            CSSON     : RCC_CR.CSSON    .T;
            HSEBYP    : RCC_CR.HSEBYP   .T;
            HSERDY    : RCC_CR.HSERDY   .T;
            HSEON     : RCC_CR.HSEON    .T;
            HSICAL    : RCC_CR.HSICAL   .T;
            HSITRIM   : RCC_CR.HSITRIM  .T;
            HSIRDY    : RCC_CR.HSIRDY   .T;
            HSION     : RCC_CR.HSION    .T;
         end record;

      for T use
         record
            PLLI2SRDY at 0 range PLLI2SRDY.F .. PLLI2SRDY.L;
            PLLI2SON  at 0 range PLLI2SON .F .. PLLI2SON .L;
            PLLRDY    at 0 range PLLRDY   .F .. PLLRDY   .L;
            PLLON     at 0 range PLLON    .F .. PLLON    .L;
            CSSON     at 0 range CSSON    .F .. CSSON    .L;
            HSEBYP    at 0 range HSEBYP   .F .. HSEBYP   .L;
            HSERDY    at 0 range HSERDY   .F .. HSERDY   .L;
            HSEON     at 0 range HSEON    .F .. HSEON    .L;
            HSICAL    at 0 range HSICAL   .F .. HSICAL   .L;
            HSITRIM   at 0 range HSITRIM  .F .. HSITRIM  .L;
            HSIRDY    at 0 range HSIRDY   .F .. HSIRDY   .L;
            HSION     at 0 range HSION    .F .. HSION    .L;
         end record;


Some declarations at the end of register definition:

Code: Select all
      for T'Size use Tp.Reg'Size;
      pragma Suppress_Initialization (T);

   end RCC_CR;


Package defining HW register in format:
package <register name> is new Register (<subsystem_register>.T, <subsytem_register>.Tp, <address of register>, <initial value of register>);

Code: Select all
   package CR is new Register (RCC_CR.T, RCC_CR.Tp, 16#4002_3800#, 16#0000_0083#);


Some type redefinition for easier manipulations:

Code: Select all
   subtype CR_T  is CR.T;
   subtype CR_F  is CR.F;


Fields definitions (as functions, so names could be oveloaded accross the definition file !!!).
Do it for every pool bit.
Format: function <pool> is new CR.B (<subsystem_register>.<pool>) with Inline_Always;

Code: Select all
   --  Field definitions

   function PLLI2SRDY is new CR.B (RCC_CR.PLLI2SRDY) with Inline_Always;
   function PLLI2SON  is new CR.B (RCC_CR.PLLI2SON ) with Inline_Always;
   function PLLRDY    is new CR.B (RCC_CR.PLLRDY   ) with Inline_Always;
   function PLLON     is new CR.B (RCC_CR.PLLON    ) with Inline_Always;
   function CSSON     is new CR.B (RCC_CR.CSSON    ) with Inline_Always;
   function HSEBYP    is new CR.B (RCC_CR.HSEBYP   ) with Inline_Always;
   function HSERDY    is new CR.B (RCC_CR.HSERDY   ) with Inline_Always;
   function HSEON     is new CR.B (RCC_CR.HSEON    ) with Inline_Always;
   function HSICAL    is new CR.B (RCC_CR.HSICAL   ) with Inline_Always;
   function HSITRIM   is new CR.B (RCC_CR.HSITRIM  ) with Inline_Always;
   function HSIRDY    is new CR.B (RCC_CR.HSIRDY   ) with Inline_Always;
   function HSION     is new CR.B (RCC_CR.HSION    ) with Inline_Always;


Common manipulation functions declarations.

Code: Select all
   --  Functions

   function "+"  is new CR.Add      with Inline_Always;
   function "+"  is new CR.Add_F    with Inline_Always;
   function "+"  is new CR.Add_FF   with Inline_Always;
   function "-"  is new CR.Clear    with Inline_Always;
   function "-"  is new CR.Clear_FF with Inline_Always;
   function "="  is new CR.Equal    with Inline_Always;
   function Init is new CR.Init     with Inline_Always;


Constants for bit pools (also as functions to allow name reuse).
Format: function <constant name> is new <register>.C (<subsystem_register>.<pool>, <value>) with Inline_Always;

Code: Select all
   --  Constant definitions

   function PLLI2S_Unlocked is new CR.C (RCC_CR.PLLI2SRDY, 2#0#) with Inline_Always;
   function PLLI2S_Locked   is new CR.C (RCC_CR.PLLI2SRDY, 2#1#) with Inline_Always;

   function PLLI2S_Off is new CR.C (RCC_CR.PLLI2SON, 2#0#) with Inline_Always;
   function PLLI2S_On  is new CR.C (RCC_CR.PLLI2SON, 2#1#) with Inline_Always;

   function PLL_Unlocked is new CR.C (RCC_CR.PLLRDY, 2#0#) with Inline_Always;
   function PLL_Locked   is new CR.C (RCC_CR.PLLRDY, 2#1#) with Inline_Always;

   function PLL_Off is new CR.C (RCC_CR.PLLON, 2#0#) with Inline_Always;
   function PLL_On  is new CR.C (RCC_CR.PLLON, 2#1#) with Inline_Always;

   function Clock_Security_System_Off is new CR.C (RCC_CR.CSSON, 2#0#) with Inline_Always;
   function Clock_Security_System_On  is new CR.C (RCC_CR.CSSON, 2#1#) with Inline_Always;

   function Oscillator_Not_Bypassed is new CR.C (RCC_CR.HSEBYP, 2#0#) with Inline_Always;
   function Oscillator_Bypassed     is new CR.C (RCC_CR.HSEBYP, 2#1#) with Inline_Always;

   function Oscillator_Not_Ready is new CR.C (RCC_CR.HSERDY, 2#0#) with Inline_Always;
   function Oscillator_Ready     is new CR.C (RCC_CR.HSERDY, 2#1#) with Inline_Always;

   function Oscillator_Off is new CR.C (RCC_CR.HSEON, 2#0#) with Inline_Always;
   function Oscillator_On  is new CR.C (RCC_CR.HSEON, 2#1#) with Inline_Always;

   function Oscillator_Not_Ready is new CR.C (RCC_CR.HSIRDY, 2#0#) with Inline_Always;
   function Oscillator_Ready     is new CR.C (RCC_CR.HSIRDY, 2#1#) with Inline_Always;

   function Oscillator_Off is new CR.C (RCC_CR.HSION, 2#0#) with Inline_Always;
   function Oscillator_On  is new CR.C (RCC_CR.HSION, 2#1#) with Inline_Always;


and do it for all registers in subsystem.

End file with:

Code: Select all
end ARM.Register.RCC_F40XXX;


Than you can use that definitions in the ways like these:

Code: Select all
RCC.CR.Register.HSION := Oscillator_Off;

RCC.CR := RCC.CR + HSION;

RCC.CR := RCC.CR + HSION + HSEON - PLLON;

RCC.CR := RCC.CR + HSION (Oscillator_On);

RCC.CR := PLLON (PLL_Off);

RCC.CR.Reset_Register;  --  reset to default value

RCC.CR.Init (16#0000_000#);  --  Init with value


and so on ..

That approach prevents strong Ada typing (the most Ada benefit) prevents same register treating in different compilers (eg. I found some errors in some gcc versions with volatile record pools manipulation) and then results in code that could be really good optimized. This framework enable easy way to convert "some registers definition files" too.

For more look at the implementation on https://github.com/rowsail/AdaForMicroc ... ek/arm/src

Robert Kłeczek.
RobertKleczek
 
Posts: 10
Joined: Tue Sep 02, 2014 7:28 pm

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 2 guests

cron