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