1    /*
     2     * Copyright (c) 2014-2017, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     */
    32    /*
    33     *  ======== Timer.xdc ========
    34     *
    35     */
    36    
    37    package ti.sysbios.family.arm.msp432;
    38    
    39    import xdc.rov.ViewInfo;
    40    
    41    import xdc.runtime.Types;
    42    import xdc.runtime.Error;
    43    
    44    import ti.sysbios.interfaces.ITimer;
    45    import ti.sysbios.family.arm.m3.Hwi;
    46    
    47    /*!
    48     *  ======== Timer ========
    49     *  Timer Peripherals Manager
    50     *
    51     *  This module manages the timer peripherals available on MSP432 devices.
    52     *
    53     *  The Timer module supports the timer in 'one shot', 'continuous', and
    54     *  'dynamic' modes.
    55     *
    56     *  In 'one shot' mode, a timer function will "fire" (run) when the timer
    57     *  period expires. In 'one shot' mode this will only happen once.
    58     *
    59     *  In 'continuous' mode, the specified timer function will "fire" every
    60     *  time the period expires, throughout the lifetime of the program.
    61     *
    62     *  In 'dynamic' mode, the specified timer function will "fire" every
    63     *  time the period expires.  But the period of the timer can be changed
    64     *  dynamically, to correspond to the next tick interrupt needed from the
    65     *  timer.  This mode is used by the SYS/BIOS
    66     *  {@link ti.sysbios.knl.Clock Clock} module for implementing
    67     *  dynamic tick suppression, to reduce the number of interrupts from the
    68     *  timer to the minimum required for currently scheduled timeouts.
    69     *
    70     *  @p(html)
    71     *  <h3> Calling Context </h3>
    72     *  <table border="1" cellpadding="3">
    73     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
    74     *  </colgroup>
    75     *
    76     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th>
    77     *  <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    78     *    <!--                                                          -->
    79     *    <tr><td> {@link #getAvailMask}            </td><td>   Y    </td>
    80     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    81     *    <tr><td> {@link #getNumTimers}            </td><td>   Y    </td>
    82     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    83     *    <tr><td> {@link #getStatus}               </td><td>   Y    </td>
    84     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    85     *    <tr><td> {@link #Params_init}             </td><td>   N    </td>
    86     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
    87     *    <tr><td> {@link #construct}               </td><td>   N    </td>
    88     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
    89     *    <tr><td> {@link #create}                  </td><td>   N    </td>
    90     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
    91     *    <tr><td> {@link #delete}                  </td><td>   N    </td>
    92     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
    93     *    <tr><td> {@link #destruct}                </td><td>   N    </td>
    94     *  <td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
    95     *    <tr><td> {@link #getCount}                </td><td>   Y    </td>
    96     *  <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    97     *    <tr><td> {@link #getFreq}                 </td><td>   Y    </td>
    98     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    99     *    <tr><td> {@link #getFunc}                 </td><td>   Y    </td>
   100     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   101     *    <tr><td> {@link #getPeriod}               </td><td>   Y    </td>
   102     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   103     *    <tr><td> {@link #reconfig}                </td><td>   Y    </td>
   104     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   105     *    <tr><td> {@link #setAvailMask}            </td><td>   Y    </td>
   106     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   107     *    <tr><td> {@link #setFunc}                 </td><td>   Y    </td>
   108     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   109     *    <tr><td> {@link #setPeriod}               </td><td>   Y    </td>
   110     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   111     *    <tr><td> {@link #setPeriodMicroSecs}      </td><td>   Y    </td>
   112     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   113     *    <tr><td> {@link #start}                   </td><td>   Y    </td>
   114     *  <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   115     *    <tr><td> {@link #stop}                    </td><td>   Y    </td>
   116     *  <td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   117     *    <tr><td colspan="6"> Definitions: <br />
   118     *       <ul>
   119     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   120     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   121     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   122     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   123     *           <ul>
   124     *             <li> In your module startup after this module is started
   125     *  (e.g. Timer_Module_startupDone() returns TRUE). </li>
   126     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   127     *             <li> During main().</li>
   128     *             <li> During BIOS.startupFxns.</li>
   129     *           </ul>
   130     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   131     *           <ul>
   132     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   133     *             <li> In your module startup before this module is started
   134     *  (e.g. Timer_Module_startupDone() returns FALSE).</li>
   135     *           </ul>
   136     *       </ul>
   137     *    </td></tr>
   138     *
   139     *  </table>
   140     *  @p
   141     *
   142     *  @p(html)
   143     *  <h3> Timer Mapping Tables </h3>
   144     *  <p>
   145     *  The Timer module allows the user to use and configure the various timers
   146     *  that exist on a particular device.  This is achieved by specifying a timer
   147     *  ID when statically creating the Timer instance.
   148     *  A convention is used to assign logical IDs to physical timers.  ID '0'
   149     *  corresponds to the first Timer_A peripheral (TA0).  ID '1' is assigned to
   150     *  the next Timer_A (TA1), until there are no more Timer_A peripherals.  Then
   151     *  the next ID is assigned to the first Timer_B peripheral (if present), and
   152     *  so on.
   153     *  These tables are provided to show which timers map to which timer IDs.
   154     *  </p>
   155     *  {@link ./doc-files/TimerTables.html Timer Mapping Tables}
   156     *  @p
   157     */
   158    @ModuleStartup          /* To configure static timers */
   159    @InstanceInitStatic
   160    
   161    module Timer inherits ti.sysbios.interfaces.ITimer
   162    {
   163        /*! override supportsDynamic - this Timer does support RunMode_DYNAMIC */
   164        override metaonly config Bool supportsDynamic = true;
   165    
   166        /*! override defaultMode - use RunMode_PERIODIC by default */
   167        override metaonly config Bool defaultDynamic = false;
   168    
   169        // -------- Module Types --------
   170    
   171        /*! Lists of input clock sources for timers */
   172        enum Source {
   173            Source_ACLK = 0x100,               /*! ACLK */
   174            Source_SMCLK = 0x200,              /*! SMCLK */
   175            Source_EXTERNAL = 0x000,           /*! External clock */
   176            Source_EXTERNAL_INVERTED = 0x300   /*! Inverted external clock */
   177        };
   178    
   179        /*! Input divider (ID) bit field values */
   180        enum ID {
   181            ID_1 = 0x0,                     /*! /1 */
   182            ID_2 = 0x40,                    /*! /2 */
   183            ID_4 = 0x80,                    /*! /4 */
   184            ID_8 = 0xC0                     /*! /8 */
   185        };
   186    
   187        /*! Input Divider Expansion (IDEX) bit field values */
   188        enum IDEX {
   189            IDEX_1 = 0x0,                   /*! /1 */
   190            IDEX_2 = 0x1,                   /*! /2 */
   191            IDEX_3 = 0x2,                   /*! /3 */
   192            IDEX_4 = 0x3,                   /*! /4 */
   193            IDEX_5 = 0x4,                   /*! /5 */
   194            IDEX_6 = 0x5,                   /*! /6 */
   195            IDEX_7 = 0x6,                   /*! /7 */
   196            IDEX_8 = 0x7                    /*! /8 */
   197        };
   198    
   199        /*! Max value of Timer period for PeriodType_COUNTS */
   200        const UInt MAX_PERIOD = 0x0000ffff;
   201    
   202        /*! @_nodoc
   203         *  Min instructions to use in trigger().
   204         */
   205        const Int MIN_SWEEP_PERIOD = 1;
   206    
   207        /*! @_nodoc */
   208        @XmlDtd
   209        metaonly struct BasicView {
   210            Ptr         halTimerHandle;
   211            String      label;
   212            UInt        id;
   213            String      startMode;
   214            String      runMode;
   215            UInt        period;
   216            String      periodType;
   217            Bool        synchronous;
   218            UInt        intNum;
   219            String      tickFxn[];
   220            UArg        arg;
   221            UInt        frequency;
   222            String      hwiHandle;
   223        };
   224    
   225        /*! @_nodoc */
   226        metaonly struct DeviceView {
   227            UInt        id;
   228            String      device;
   229            String      devAddr;
   230            UInt        intNum;
   231            String      runMode;
   232            String      clockSource;
   233            UInt        period;
   234            UInt        currCount;
   235            UInt        remainingCount;
   236            UInt        prevThreshold;
   237            String      state;
   238        };
   239    
   240        /*! @_nodoc */
   241        metaonly struct ModuleView {
   242            String      availMask;      /* available timers */
   243        }
   244    
   245        /*! @_nodoc */
   246        @Facet
   247        metaonly config ViewInfo.Instance rovViewInfo =
   248            ViewInfo.create({
   249                viewMap: [
   250                [
   251                    'Basic',
   252                    {
   253                        type: ViewInfo.INSTANCE,
   254                        viewInitFxn: 'viewInitBasic',
   255                        structName: 'BasicView'
   256                    }
   257                ],
   258                [
   259                    'Device',
   260                    {
   261                        type: ViewInfo.INSTANCE,
   262                        viewInitFxn: 'viewInitDevice',
   263                        structName: 'DeviceView'
   264                    }
   265                ],
   266                [
   267                    'Module',
   268                    {
   269                        type: ViewInfo.MODULE,
   270                        viewInitFxn: 'viewInitModule',
   271                        structName: 'ModuleView'
   272                    }
   273                ],
   274                ]
   275            });
   276    
   277        /*!
   278         *  ======== E_invalidTimer ========
   279         *  Error raised when specified timer id is not supported
   280         */
   281        config Error.Id E_invalidTimer = {
   282            msg: "E_invalidTimer: Invalid Timer Id %d"
   283        };
   284    
   285        /*!
   286         *  ======== E_notAvailable ========
   287         *  Error raised when requested timer is in use
   288         */
   289        config Error.Id E_notAvailable = {
   290            msg: "E_notAvailable: Timer not available %d"
   291        };
   292    
   293        /*!
   294         *  ======== E_cannotSupport ========
   295         *  Error raised when requested period is not supported
   296         */
   297        config Error.Id E_cannotSupport = {
   298            msg: "E_cannotSupport: Timer cannot support requested period %d"
   299        };
   300    
   301        /*!
   302         *  ======== anyMask ========
   303         *  Mask of available timers
   304         *
   305         *  This mask is used to identify the timers that can be used when
   306         *  Timer_create() is called with an id equal to
   307         *  {@link Timer#ANY Timer_ANY}.
   308         */
   309        config UInt anyMask = 0xF;
   310    
   311        /*!
   312         *  ======== getAvailMask ========
   313         *  Returns the availMask.
   314         *
   315         *  @b(returns)     Mask of available timers
   316         */
   317        UInt getAvailMask();
   318    
   319        /*!
   320         *  ======== oneShotStub ========
   321         *  @_nodoc
   322         *
   323         *  @param(arg)     Unused.
   324         */
   325        Void oneShotStub(UArg arg);
   326    
   327        /*!
   328         *  ======== oneShotNestStub ========
   329         *  @_nodoc
   330         *
   331         *  @param(arg)     Unused.
   332         */
   333        Void oneShotNestStub(UArg arg);
   334    
   335        /*!
   336         *  ======== periodicStub ========
   337         *  @_nodoc
   338         *
   339         *  @param(arg)     Unused.
   340         */
   341        Void periodicStub(UArg arg);
   342    
   343        /*!
   344         *  ======== periodicNestStub ========
   345         *  @_nodoc
   346         *
   347         *  @param(arg)     Unused.
   348         */
   349        Void periodicNestStub(UArg arg);
   350    
   351        /*!
   352         *  ======== setAvailMask ========
   353         *  Set the availMask to given mask.
   354         *
   355         *  This function validates the given mask to ensure it does not mark
   356         *  any currently used timer as available. If validation is successful,
   357         *  the mask overwrites the current availMask and the function returns
   358         *  TRUE. Otherwise, the mask is discarded and the function returns
   359         *  FALSE.
   360         *
   361         *  @param(mask)    Mask used to write to availMask
   362         */
   363        Bool setAvailMask(UInt mask);
   364    
   365        /*!
   366         *  ======== getHandle ========
   367         *  @_nodoc
   368         *  Used by TimestampProvider module to get hold of timer handle used by
   369         *  Clock.
   370         *
   371         *  @param(id)      timer Id.
   372         */
   373        Handle getHandle(UInt id);
   374    
   375    instance:
   376    
   377        /*! Hwi Params for Hwi Object. Default is null. */
   378        config Hwi.Params *hwiParams = null;
   379    
   380        /*! Clock source input select. Default is ACLK. */
   381        config Source clockSource = Source_ACLK;
   382    
   383        /*! Selected clock source is synchronous to CPU clock? Default is false. */
   384        config Bool synchronous = false;
   385    
   386        /*! Clock Input Divider (ID) select. Default is /1. */
   387        config ID inputDivider = ID_1;
   388    
   389        /*! Clock Input Divider Expansion (IDEX) select. Default is /1. */
   390        config IDEX inputDividerExp = IDEX_1;
   391    
   392        /*! Enable nesting of other interrupts on top of this Timer's ISR? */
   393        config Bool nesting = false;
   394    
   395        /*! Previous threshold count value. */
   396        config UInt prevThreshold = 0;
   397    
   398        /*! Control register configuration. Default source = ACLK. */
   399        config UInt controlRegInit = Source_ACLK;
   400    
   401        /*!
   402         *  ======== reconfig ========
   403         *  Modify timer instances at runtime
   404         *
   405         *  @param(timerParams)     timer Params
   406         *  @param(tickFxn)         function that runs when timer expires.
   407         */
   408        Void reconfig(FuncPtr tickFxn, const Params *timerParams, Error.Block *eb);
   409    
   410    
   411    internal:   /* not for client use */
   412    
   413        /*!
   414         *  ======== noStartupNeeded ========
   415         *  Flag used to prevent misc code from being brought in
   416         *  un-necessarily
   417         */
   418        config UInt startupNeeded = false;
   419    
   420        /*
   421         *  ======== initDevice ========
   422         *  reset timer to its resting state
   423         */
   424        Void initDevice(Object *timer);
   425    
   426        /*
   427         *  ======== postInit ========
   428         *  finish initializing static and dynamic Timers
   429         */
   430        Int postInit(Object *timer, Error.Block *eb);
   431    
   432        /*
   433         *  ======== checkOverflow ========
   434         */
   435        Bool checkOverflow(UInt32 a, UInt32 b);
   436    
   437        /*! Information about timer */
   438        struct TimerDevice {
   439            UInt intNum;
   440            Ptr  baseAddr;
   441        };
   442    
   443        /*!
   444         *  ======== numTimerDevices ========
   445         *  The number of physical timers on the device
   446         */
   447        config Int numTimerDevices;
   448    
   449        struct Instance_State {
   450            Bool                        staticInst;
   451            Int                         id;
   452            UInt16                      controlRegInit;
   453            ITimer.RunMode              runMode;
   454            ITimer.StartMode            startMode;
   455            UInt                        period;
   456            ITimer.PeriodType           periodType;
   457            UInt                        intNum;
   458            UArg                        arg;
   459            Hwi.FuncPtr                 tickFxn;
   460            Types.FreqHz                frequency;
   461            Hwi.Handle                  hwi;
   462            UInt16                      prevThreshold;
   463            UInt16                      savedCurrCount;
   464            UInt32                      rollovers;
   465            Bool                        synchronous;
   466            UInt                        inputDivider;
   467            UInt                        inputDividerExp;
   468        }
   469    
   470        struct Module_State {
   471            UInt            availMask;      /* available peripherals */
   472            TimerDevice     device[];       /* timer device information */
   473            Handle          handles[];      /* array of handles based on id */
   474        }
   475    }