1    /*
     2     * Copyright (c) 2015-2016, 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    package ti.sysbios.timers.rti;
    37    
    38    import xdc.rov.ViewInfo;
    39    
    40    import xdc.runtime.Assert;
    41    import xdc.runtime.Error;
    42    import xdc.runtime.Types;
    43    import ti.sysbios.interfaces.ITimer;
    44    import ti.sysbios.hal.Hwi;
    45    
    46    /*!
    47     *  ======== Timer ========
    48     *  RTI Timer Peripheral Manager.
    49     *
    50     *  @p(html)
    51     *  <h3> Calling Context </h3>
    52     *  <table border="1" cellpadding="3">
    53     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
    54     *
    55     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th><th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    56     *    <!--                                                                                                                 -->
    57     *    <tr><td> {@link #getNumTimers}            </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    58     *    <tr><td> {@link #getStatus}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    59     *    <tr><td> {@link #Params_init}             </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    60     *    <tr><td> {@link #construct}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    61     *    <tr><td> {@link #create}                  </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    62     *    <tr><td> {@link #delete}                  </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    63     *    <tr><td> {@link #destruct}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    64     *    <tr><td> {@link #getCount}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    65     *    <tr><td> {@link #getFreq}                 </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    66     *    <tr><td> {@link #getPeriod}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    67     *    <tr><td> {@link #reconfig}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    68     *    <tr><td> {@link #setPeriod}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    69     *    <tr><td> {@link #setPeriodMicroSecs}      </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    70     *    <tr><td> {@link #start}                   </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    71     *    <tr><td> {@link #stop}                    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    72     *    <tr><td colspan="6"> Definitions: <br />
    73     *       <ul>
    74     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
    75     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
    76     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
    77     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
    78     *           <ul>
    79     *             <li> In your module startup after this module is started (e.g. Timer_Module_startupDone() returns TRUE). </li>
    80     *             <li> During xdc.runtime.Startup.lastFxns. </li>
    81     *             <li> During main().</li>
    82     *             <li> During BIOS.startupFxns.</li>
    83     *           </ul>
    84     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
    85     *           <ul>
    86     *             <li> During xdc.runtime.Startup.firstFxns.</li>
    87     *             <li> In your module startup before this module is started (e.g. Timer_Module_startupDone() returns FALSE).</li>
    88     *           </ul>
    89     *       </ul>
    90     *    </td></tr>
    91     *
    92     *  </table>
    93     *  @p
    94     *
    95     */
    96    @ModuleStartup          /* to configure static timers */
    97    
    98    module Timer inherits ti.sysbios.interfaces.ITimer
    99    {
   100        /*! Max value of Timer period for PeriodType_COUNTS*/
   101        const UInt MAX_PERIOD = 0xffffffff;
   102    
   103        /*! Number of timer peripherals on chip */
   104        const Int NUM_TIMER_DEVICES = 2;
   105    
   106        /*! @_nodoc
   107         *  Min instructions to use in trigger().
   108         */
   109        const Int MIN_SWEEP_PERIOD = 8;
   110    
   111        /*! @_nodoc */
   112        @XmlDtd
   113        metaonly struct BasicView {
   114            Ptr         halTimerHandle;
   115            String      label;
   116            UInt        id;
   117            String      startMode;
   118            String      runMode;
   119            UInt        periodInCounts;
   120            UInt        periodInMicroSecs;
   121            UInt        intNum;
   122            String      tickFxn[];
   123            UArg        arg;
   124            String      extFreq;
   125            String      hwiHandle;
   126        };
   127    
   128        /*! @_nodoc */
   129        metaonly struct DeviceView {
   130            UInt        id;
   131            String      device;
   132            String      devAddr;
   133            UInt        intNum;
   134            String      runMode;
   135            UInt        period;
   136            UInt        currCount;
   137            UInt        remainingCount;
   138            String      state;
   139        };
   140    
   141        /*! @_nodoc */
   142        metaonly struct ModuleView {
   143            String      availMask;      /* available 32-bit timer halves */
   144        }
   145    
   146        /*! @_nodoc */
   147        @Facet
   148        metaonly config ViewInfo.Instance rovViewInfo =
   149            ViewInfo.create({
   150                viewMap: [
   151                [
   152                    'Basic',
   153                    {
   154                        type: ViewInfo.MODULE_DATA,
   155                        viewInitFxn: 'viewInitBasic',
   156                        structName: 'BasicView'
   157                    }
   158                ],
   159                [
   160                    'Device',
   161                    {
   162                        type: ViewInfo.INSTANCE,
   163                        viewInitFxn: 'viewInitDevice',
   164                        structName: 'DeviceView'
   165                    }
   166                ],
   167                [
   168                    'Module',
   169                    {
   170                        type: ViewInfo.MODULE,
   171                        viewInitFxn: 'viewInitModule',
   172                        structName: 'ModuleView'
   173                    }
   174                ],
   175                ]
   176            });
   177    
   178        /*!
   179         *  ======== A_invalidTimer ========
   180         *  Assert raised when timer id specified is not supported.
   181         */
   182        config xdc.runtime.Assert.Id A_invalidTimer  = {
   183            msg: "A_invalidTimer: Invalid Timer Id."
   184        };
   185    
   186        /*!
   187         *  Error raised when timer id specified is not supported.
   188         */
   189        config Error.Id E_invalidTimer =
   190            {msg: "E_invalidTimer: Invalid Timer Id %d"};
   191    
   192        /*!
   193         *  Error raised when timer requested is in use
   194         */
   195        config Error.Id E_notAvailable =
   196            {msg: "E_notAvailable: Timer not available %d"};
   197    
   198        /*!
   199         *  Error raised when Hwi Params has mask where self is turned on.
   200         *
   201         *  This is not allowed because the timers on this platform do not
   202         *  support one-shot mode and a stub is used to stop it.
   203         *  Another timer interrupt cannot go off when the ISR is running.
   204         */
   205        config Error.Id E_invalidHwiMask  =
   206            {msg: "E_InvalidMask: Mask in hwiParams cannot enable self"};
   207    
   208        /*!
   209         *  Error raised when period requested is not supported
   210         */
   211        config Error.Id E_cannotSupport  =
   212            {msg: "E_cannotSupport: Timer cannot support requested period %d"};
   213    
   214        /*!
   215         * Timer base address
   216         */
   217        metaonly config Ptr rtiBaseAddress;
   218    
   219        /*!
   220         *  ======== anyMask ========
   221         *  Available mask to be used when select = Timer_ANY
   222         */
   223        config UInt anyMask = 0x3;
   224    
   225        /*!
   226         *  ======== continueOnSuspend ========
   227         *  Continue counting during emulation halt. Default is false.
   228         *
   229         *  When false, timer stops counting during emulation halt. When true,
   230         *  timer continues to count during emulation halt.
   231         */
   232        config Bool continueOnSuspend = false;
   233    
   234        /*!
   235         *  ======== intFreq ========
   236         *  Default internal timer input clock frequency.
   237         *
   238         *  @a(NOTE)
   239         *  By default, the RTI timer clock source is VCLK which is configured
   240         *  to run at 1/2 the CPU frequency (GCLK). If the clock divide ratios
   241         *  are changed, then this config param can be used to configure this
   242         *  module to run at a different frequency.
   243         *
   244         *  @p(code)
   245         *  var Timer = xdc.useModule('ti.sysbios.timers.rti.Timer');
   246         *  Timer.intFreq.lo = 50000000; // = (CPU freq / 2)
   247         *  Timer.intFreq.hi = 0;
   248         *  @p
   249         */
   250        config Types.FreqHz intFreq = {lo: 0, hi: 0};
   251    
   252        /*!
   253         *  @_nodoc
   254         *  RTI timer registers. Symbol "Timer_deviceRegs" is a physical device.
   255         */
   256        struct DeviceRegs {
   257            UInt32 RTIGCTRL;        /*! 0x00h */
   258            UInt32 RTITBCTRL;       /*! 0x04h */
   259            UInt32 RTICAPCTRL;      /*! 0x08h */
   260            UInt32 RTICOMPCTRL;     /*! 0x0Ch */
   261            UInt32 RTIFRC0;         /*! 0x10h */
   262            UInt32 RTIUC0;          /*! 0x14h */
   263            UInt32 RTICPUC0;        /*! 0x18h */
   264            UInt32 RESERVED0;       /*! 0x1Ch */
   265            UInt32 RTICAFRC0;       /*! 0x20h */
   266            UInt32 RTICAUC0;        /*! 0x24h */
   267            UInt32 RESERVED1;       /*! 0x28h */
   268            UInt32 RESERVED2;       /*! 0x2Ch */
   269            UInt32 RTIFRC1;         /*! 0x30h */
   270            UInt32 RTIUC1;          /*! 0x34h */
   271            UInt32 RTICPUC1;        /*! 0x38h */
   272            UInt32 RESERVED3;       /*! 0x3Ch */
   273            UInt32 RTICAFRC1;       /*! 0x40h */
   274            UInt32 RTICAUC1;        /*! 0x44h */
   275            UInt32 RESERVED4;       /*! 0x48h */
   276            UInt32 RESERVED5;       /*! 0x4Ch */
   277            UInt32 RTICOMP0;        /*! 0x50h */
   278            UInt32 RTIUDCP0;        /*! 0x54h */
   279            UInt32 RTICOMP1;        /*! 0x58h */
   280            UInt32 RTIUDCP1;        /*! 0x5Ch */
   281            UInt32 RTICOMP2;        /*! 0x60h */
   282            UInt32 RTIUDCP2;        /*! 0x64h */
   283            UInt32 RTICOMP3;        /*! 0x68h */
   284            UInt32 RTIUDCP3;        /*! 0x6Ch */
   285            UInt32 RTITBLCOMP;      /*! 0x70h */
   286            UInt32 RTITBLHCOMP;     /*! 0x74h */
   287            UInt32 RESERVED6;       /*! 0x78h */
   288            UInt32 RESERVED7;       /*! 0x7Ch */
   289            UInt32 RTISETINTENA;    /*! 0x80h */
   290            UInt32 RTICLEARINTENA;  /*! 0x84h */
   291            UInt32 RTIINTFLAG;      /*! 0x88h */
   292            UInt32 RESERVED8;       /*! 0x8Ch */
   293            UInt32 RTIDWDCTRL;      /*! 0x90h */
   294            UInt32 RTIDWDPRLD;      /*! 0x94h */
   295            UInt32 RTIWDSTATUS;     /*! 0x98h */
   296            UInt32 RTIWDKEY;        /*! 0x9Ch */
   297            UInt32 RTIDWDCNTR;      /*! 0xA0h */
   298            UInt32 RTIWWDRXNCTRL;   /*! 0xA4h */
   299            UInt32 RTIWWDSIZECTRL;  /*! 0xA8h */
   300            UInt32 RTIINTCLRENABLE; /*! 0xACh */
   301            UInt32 RTICOMP0CLR;     /*! 0xB0h */
   302            UInt32 RTICOMP1CLR;     /*! 0xB4h */
   303            UInt32 RTICOMP2CLR;     /*! 0xB8h */
   304            UInt32 RTICOMP3CLR;     /*! 0xBCh */
   305        };
   306    
   307        extern volatile DeviceRegs deviceRegs;
   308    
   309        /*!
   310         *  ======== oneShotStub ========
   311         *  @_nodoc
   312         *  RTI timer does not support one shot mode. This stub stops timer
   313         *  and disables its interrupt.
   314         *
   315         *  @param(arg)     Timer Handle.
   316         */
   317        Void oneShotStub(UArg arg);
   318    
   319        /*!
   320         *  ======== periodicStub ========
   321         *  @_nodoc
   322         *
   323         *  @param(arg)     Timer Handle.
   324         */
   325        Void periodicStub(UArg arg);
   326    
   327        /*!
   328         *  ======== getHandle ========
   329         *  @_nodoc
   330         *  Used by TimestampProvider module to get hold of timer handle used by
   331         *  Clock.
   332         *
   333         *  @param(id)      timer Id.
   334         */
   335        Handle getHandle(UInt id);
   336    
   337    instance:
   338    
   339        /*!
   340         *  ======== createHwi ========
   341         *  Controls whether the timer module creates a Hwi. Default is true.
   342         *
   343         *  If an application needs to create a Hwi for the timer, it is possible
   344         *  to indicate to the timer module to not create a Hwi by setting this
   345         *  param to false. This feature may be useful if the application needs to
   346         *  create a Hwi using the family specific Hwi module or on certain ARM
   347         *  targets create a Hwi of FIQ type to minimize latency.
   348         *
   349         *  If the application creates its own Hwi, it needs to select an interrupt
   350         *  number corresponding to the timer Id (see
   351         *  {@link ./doc-files/TimerTables.html Timer Mapping Tables}).
   352         *
   353         *  Here's an example for the Cortex-R5 target that creates a custom
   354         *  Hwi of FIQ type and sets "Timer.createHwi" param to false when
   355         *  creating a Timer object, in order to prevent the Timer module from
   356         *  creating a Hwi.
   357         *
   358         *  @p(code)
   359         *  *.cfg:
   360         *  xdc.useModule('ti.sysbios.timers.rti.Timer');
   361         *  xdc.useModule('ti.sysbios.family.arm.v7r.vim.Hwi');
   362         *
   363         *  *.c:
   364         *  #include <xdc/std.h>
   365         *  #include <xdc/runtime/Error.h>
   366         *
   367         *  #include <ti/sysbios/timers/rti/Timer.h>
   368         *  #include <ti/sysbios/family/arm/v7r/vim/Hwi.h>
   369         *  ...
   370         *
   371         *  Timer_Struct timer0;
   372         *  Timer_Handle handle0;
   373         *
   374         *  interrupt Void myIsr()
   375         *  {
   376         *      // Timer needs to be stopped only if run mode is One shot.
   377         *      // For periodic run mode, this function needs to only ack
   378         *      // the timer interrupt.
   379         *      Timer_stop(handle0);
   380         *      Timer_ackInterrupt(handle0);
   381         *      ...
   382         *  }
   383         *
   384         *  Int main(Int argc, char* argv[])
   385         *  {
   386         *      Timer_Params timerParams;
   387         *      Hwi_Params hwiParams;
   388         *      Error_Block eb;
   389         *
   390         *      Error_init(&eb);
   391         *
   392         *      // The interrupt number corresponding to a given Timer Id
   393         *      // can be determined from the Timer Mapping table. A link
   394         *      // to the table can be found in this document.
   395         *      Hwi_Params_init(&hwiParams);
   396         *      hwiParams.type = Hwi_Type_FIQ;
   397         *      Hwi_create(2, (Hwi_FuncPtr)(&myIsr), &hwiParams, &eb);
   398         *
   399         *      Timer_Params_init(&timerParams);
   400         *      timerParams.period = 60000;
   401         *      timerParams.runMode = Timer_RunMode_ONESHOT;
   402         *      timerParams.periodType = Timer_PeriodType_MICROSECS;
   403         *      timerParams.createHwi = FALSE;
   404         *      Timer_construct(&timer0, 0, NULL, &timerParams, &eb);
   405         *
   406         *      handle0 = Timer_handle(&timer0);
   407         *      ...
   408         *
   409         *      BIOS_start();
   410         *      return(0);
   411         *  }
   412         *  @p
   413         */
   414        config Bool createHwi = true;
   415    
   416        /*!
   417         *  ======== hwiParams ========
   418         *  Hwi Params for Hwi Object. Default is null.
   419         */
   420        config Hwi.Params *hwiParams = null;
   421    
   422        /*!
   423         *  ======== prescale ========
   424         *  Prescale factor. Default is 1 (0 is not recommended).
   425         *
   426         *  The Prescale factor can be used to achieve longer timer periods.
   427         *  With a prescale factor specified, the actual timer period is
   428         *  period * (prescale + 1).
   429         */
   430        config UInt8 prescale = 1;
   431    
   432        /*!
   433         *  ======== reconfig ========
   434         *  Used to modify static timer instances at runtime.
   435         *
   436         *  @param(timerParams)     timer Params
   437         *  @param(tickFxn)         functions that runs when timer expires.
   438         */
   439        Void reconfig(FuncPtr tickFxn, const Params *timerParams, Error.Block *eb);
   440    
   441        /*!
   442         *  ======== ackInterrupt ========
   443         *  clear the current timer interrupt flag
   444         */
   445        Void ackInterrupt();
   446    
   447    internal:   /* not for client use */
   448    
   449        /*!
   450         *  ======== startupNeeded ========
   451         *  Flag used to prevent misc code from being brought in
   452         *  un-necessarily
   453         */
   454        config UInt startupNeeded = false;
   455    
   456        /*
   457         * array of Timer intNums
   458         */
   459        config UInt8 intNumDef[2];
   460    
   461        /*
   462         * array of Timer eventIds
   463         */
   464        config UInt8 evtIdDef[2];
   465    
   466        /*
   467         *  ======== initDevice ========
   468         *  reset timer to its resting state
   469         */
   470        Void initDevice(Object *timer);
   471    
   472        /*
   473         *  ======== postInit ========
   474         *  finish initializing static and dynamic Timers
   475         */
   476        Int postInit(Object *timer, Error.Block *eb);
   477    
   478        /*
   479         *  ======== checkOverflow ========
   480         */
   481        Bool checkOverflow(UInt32 a, UInt32 b);
   482    
   483        struct Instance_State {
   484            Bool                    staticInst;
   485            Int                     id;
   486            ITimer.RunMode          runMode;
   487            ITimer.StartMode        startMode;
   488            UInt                    prescale;
   489            UInt                    period;
   490            ITimer.PeriodType       periodType;
   491            UInt                    intNum;
   492            UArg                    arg;
   493            Hwi.FuncPtr             tickFxn;
   494            Types.FreqHz            extFreq;
   495            Hwi.Handle              hwi;
   496            Bool                    createHwi;
   497        }
   498    
   499        struct Module_State {
   500            UInt            availMask;      /* available peripherals */
   501            Handle          handles[];      /* array of handles based on id */
   502        }
   503    }