1    /*
     2     * Copyright (c) 2014, 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        /*! Timer Configuration struct.
   208         *
   209         *  @field(source)  Timer clock source.
   210         */
   211        struct Control {
   212            UInt source;   /*! 0x100=ACLK, 0x200=SMCLK, 0=EXT, 0x300=EXT_INVERT */
   213        };
   214    
   215        /*! @_nodoc */
   216        @XmlDtd
   217        metaonly struct BasicView {
   218            Ptr         halTimerHandle;
   219            String      label;
   220            UInt        id;
   221            Control     configuration;
   222            String      startMode;
   223            String      runMode;
   224            UInt        period;
   225            String      periodType;
   226            Bool        synchronous;
   227            UInt        intNum;
   228            String      tickFxn[];
   229            UArg        arg;
   230            UInt        frequency;
   231            String      hwiHandle;
   232        };
   233    
   234        /*! @_nodoc */
   235        metaonly struct DeviceView {
   236            UInt        id;
   237            String      device;
   238            String      devAddr;
   239            UInt        intNum;
   240            String      runMode;
   241            UInt        period;
   242            UInt        currCount;
   243            UInt        remainingCount;
   244            UInt        prevThreshold;
   245            String      state;
   246        };
   247    
   248        /*! @_nodoc */
   249        metaonly struct ModuleView {
   250            String      availMask;      /* available timers */
   251        }
   252    
   253        /*! @_nodoc */
   254        @Facet
   255        metaonly config ViewInfo.Instance rovViewInfo =
   256            ViewInfo.create({
   257                viewMap: [
   258                [
   259                    'Basic',
   260                    {
   261                        type: ViewInfo.INSTANCE,
   262                        viewInitFxn: 'viewInitBasic',
   263                        structName: 'BasicView'
   264                    }
   265                ],
   266                [
   267                    'Device',
   268                    {
   269                        type: ViewInfo.INSTANCE,
   270                        viewInitFxn: 'viewInitDevice',
   271                        structName: 'DeviceView'
   272                    }
   273                ],
   274                [
   275                    'Module',
   276                    {
   277                        type: ViewInfo.MODULE,
   278                        viewInitFxn: 'viewInitModule',
   279                        structName: 'ModuleView'
   280                    }
   281                ],
   282                ]
   283            });
   284    
   285        /*!
   286         *  ======== E_invalidTimer ========
   287         *  Error raised when specified timer id is not supported
   288         */
   289        config Error.Id E_invalidTimer = {
   290            msg: "E_invalidTimer: Invalid Timer Id %d"
   291        };
   292    
   293        /*!
   294         *  ======== E_notAvailable ========
   295         *  Error raised when requested timer is in use
   296         */
   297        config Error.Id E_notAvailable = {
   298            msg: "E_notAvailable: Timer not available %d"
   299        };
   300    
   301        /*!
   302         *  ======== E_cannotSupport ========
   303         *  Error raised when requested period is not supported
   304         */
   305        config Error.Id E_cannotSupport = {
   306            msg: "E_cannotSupport: Timer cannot support requested period %d"
   307        };
   308    
   309        /*!
   310         *  ======== anyMask ========
   311         *  Mask of available timers
   312         *
   313         *  This mask is used to identify the timers that can be used when
   314         *  Timer_create() is called with an id equal to
   315         *  {@link Timer#ANY Timer_ANY}.
   316         */
   317        config UInt anyMask = 0xF;
   318    
   319        /*!
   320         *  ======== getAvailMask ========
   321         *  Returns the availMask.
   322         *
   323         *  @b(returns)     Mask of available timers
   324         */
   325        UInt getAvailMask();
   326    
   327        /*!
   328         *  ======== oneShotStub ========
   329         *  @_nodoc
   330         *
   331         *  @param(arg)     Unused.
   332         */
   333        Void oneShotStub(UArg arg);
   334    
   335        /*!
   336         *  ======== oneShotNestStub ========
   337         *  @_nodoc
   338         *
   339         *  @param(arg)     Unused.
   340         */
   341        Void oneShotNestStub(UArg arg);
   342    
   343        /*!
   344         *  ======== periodicStub ========
   345         *  @_nodoc
   346         *
   347         *  @param(arg)     Unused.
   348         */
   349        Void periodicStub(UArg arg);
   350    
   351        /*!
   352         *  ======== periodicNestStub ========
   353         *  @_nodoc
   354         *
   355         *  @param(arg)     Unused.
   356         */
   357        Void periodicNestStub(UArg arg);
   358    
   359        /*!
   360         *  ======== setAvailMask ========
   361         *  Set the availMask to given mask.
   362         *
   363         *  This function validates the given mask to ensure it does not mark
   364         *  any currently used timer as available. If validation is successful,
   365         *  the mask overwrites the current availMask and the function returns
   366         *  TRUE. Otherwise, the mask is discarded and the function returns
   367         *  FALSE.
   368         *
   369         *  @param(mask)    Mask used to write to availMask
   370         */
   371        Bool setAvailMask(UInt mask);
   372    
   373        /*!
   374         *  ======== getHandle ========
   375         *  @_nodoc
   376         *  Used by TimestampProvider module to get hold of timer handle used by
   377         *  Clock.
   378         *
   379         *  @param(id)      timer Id.
   380         */
   381        Handle getHandle(UInt id);
   382    
   383    instance:
   384    
   385        /*! Hwi Params for Hwi Object. Default is null. */
   386        config Hwi.Params *hwiParams = null;
   387    
   388        /*! Clock source input select. Default is ACLK. */
   389        config Source clockSource = Source_ACLK;
   390    
   391        /*! Selected clock source is synchronous to CPU clock? Default is false. */
   392        config Bool synchronous = false;
   393    
   394        /*! Clock Input Divider (ID) select. Default is /1. */
   395        config ID inputDivider = ID_1;
   396    
   397        /*! Clock Input Divider Expansion (IDEX) select. Default is /1. */
   398        config IDEX inputDividerExp = IDEX_1;
   399    
   400        /*! Enable nesting of other interrupts on top of this Timer's ISR? */
   401        config Bool nesting = false;
   402    
   403        /*! Previous threshold count value. */
   404        config UInt prevThreshold = 0;
   405    
   406        /*! Control register configuration. Default source = ACLK. */
   407        config UInt controlRegInit = Source_ACLK;
   408    
   409        /*!
   410         *  ======== reconfig ========
   411         *  Modify timer instances at runtime
   412         *
   413         *  @param(timerParams)     timer Params
   414         *  @param(tickFxn)         function that runs when timer expires.
   415         */
   416        Void reconfig(FuncPtr tickFxn, const Params *timerParams, Error.Block *eb);
   417    
   418    
   419    internal:   /* not for client use */
   420    
   421        /*!
   422         *  ======== noStartupNeeded ========
   423         *  Flag used to prevent misc code from being brought in
   424         *  un-necessarily
   425         */
   426        config UInt startupNeeded = false;
   427    
   428        /*
   429         *  ======== initDevice ========
   430         *  reset timer to its resting state
   431         */
   432        Void initDevice(Object *timer);
   433    
   434        /*
   435         *  ======== postInit ========
   436         *  finish initializing static and dynamic Timers
   437         */
   438        Int postInit(Object *timer, Error.Block *eb);
   439    
   440        /*
   441         *  ======== checkOverflow ========
   442         */
   443        Bool checkOverflow(UInt32 a, UInt32 b);
   444    
   445        /*! Information about timer */
   446        struct TimerDevice {
   447            UInt intNum;
   448            Ptr  baseAddr;
   449        };
   450    
   451        /*!
   452         *  ======== numTimerDevices ========
   453         *  The number of physical timers on the device
   454         */
   455        config Int numTimerDevices;
   456    
   457        struct Instance_State {
   458            Bool                        staticInst;
   459            Int                         id;
   460            UInt                        controlRegInit;
   461            ITimer.RunMode              runMode;
   462            ITimer.StartMode            startMode;
   463            UInt                        period;
   464            ITimer.PeriodType           periodType;
   465            UInt                        intNum;
   466            UArg                        arg;
   467            Hwi.FuncPtr                 tickFxn;
   468            Types.FreqHz                frequency;
   469            Hwi.Handle                  hwi;
   470            UInt                        prevThreshold;
   471            UInt                        savedCurrCount;
   472            UInt32                      rollovers;
   473            Bool                        synchronous;
   474            UInt                        inputDivider;
   475            UInt                        inputDividerExp;
   476        }
   477    
   478        struct Module_State {
   479            UInt            availMask;      /* available peripherals */
   480            TimerDevice     device[];       /* timer device information */
   481            Handle          handles[];      /* array of handles based on id */
   482        }
   483    }