1    /*
     2     * Copyright (c) 2013, 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    /*
    34     *  ======== SysMin.xdc ========
    35     *  SMP aware SysStd replacement
    36     */
    37    
    38    /*!
    39     *  ======== SysMin ========
    40     *
    41     *  Minimal implementation of `{@link xdc.runtime.ISystemSupport}`.
    42     *
    43     *  This implementation provides a fully functional implementation of
    44     *  all methods specified by `ISystemSupport`.
    45     *
    46     *  The module maintains an internal buffer (with a configurable size)
    47     *  that stores on the "output". When full, the data is over-written.  When
    48     *  `System_flush()` is called the characters in the internal buffer are
    49     *  "output" using the user configuratble `{@link #outputFxn}`.
    50     *
    51     *  As with all `ISystemSupport` modules, this module is the back-end for the
    52     *  `{@link xdc.runtime.System}` module; application code does not directly call these
    53     *  functions.
    54     */
    55    
    56    @Template("./SysMin.xdt")
    57    @ModuleStartup
    58    @CustomHeader
    59    module SysMin inherits xdc.runtime.ISystemSupport {
    60    
    61        metaonly struct ModuleView {
    62            Ptr outBuf;
    63            UInt outBufIndex;
    64            Bool wrapped;    /* has the buffer wrapped */
    65        };
    66    
    67        metaonly struct BufferEntryView {
    68            String entry;
    69        }
    70    
    71        /*!
    72         *  ======== rovViewInfo ========
    73         *  @_nodoc
    74         */
    75        @Facet
    76        metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
    77            xdc.rov.ViewInfo.create({
    78                viewMap: [
    79                    ['Module',
    80                        {
    81                            type: xdc.rov.ViewInfo.MODULE,
    82                            viewInitFxn: 'viewInitModule',
    83                            structName: 'ModuleView'
    84                        }
    85                    ],
    86                    ['OutputBuffer',
    87                        {
    88                            type: xdc.rov.ViewInfo.MODULE_DATA,
    89                            viewInitFxn: 'viewInitOutputBuffer',
    90                            structName: 'BufferEntryView'
    91                        }
    92                    ]
    93                ]
    94            });
    95    
    96        /*!
    97         *  ======== bufSize ========
    98         *  Size (in MAUs) of the output.
    99         *
   100         *  An internal buffer of this size is allocated. All output is stored
   101         *  in this internal buffer.
   102         *
   103         *  If 0 is specified for the size, no buffer is created.
   104         */
   105        config SizeT bufSize = 1024;
   106    
   107        /*!
   108         *  ======== flushAtExit ========
   109         *  Flush the internal buffer during `{@link #exit}` or `{@link #abort}`.
   110         *
   111         *  If the application's target is a TI target, the internal buffer is
   112         *  flushed via the `HOSTwrite` function in the TI C Run Time Support
   113         *  (RTS) library.
   114         *
   115         *  If the application's target is not a TI target, the internal buffer
   116         *  is flushed to `stdout` via `fwrite(..., stdout)`.
   117         *
   118         *  Setting this parameter to `false` reduces the footprint of the
   119         *  application at the expense of not getting output when the application
   120         *  ends via a `System_exit()`, `System_abort()`, `exit()` or `abort()`.
   121         */
   122        config Bool flushAtExit = true;
   123    
   124        /*!
   125         *  ======== sectionName ========
   126         *  Section where the internal character output buffer is placed
   127         *
   128         *  The default is to have no explicit placement; i.e., the linker is
   129         *  free to place it anywhere in the memory map.
   130         */
   131        metaonly config String sectionName = null;
   132    
   133        /*!
   134         *  ======== OutputFxn ========
   135         *  Output characters in the specified buffer
   136         *
   137         *  The first parameter is a pointer to a buffer of characters to be
   138         *  output.  The second parameter is the number of characters in the
   139         *  buffer to output.
   140         *
   141         *  This function may be called with 0 as the second parameter.  In this
   142         *  case, the function should simply return.
   143         *
   144         */
   145        typedef Void (*OutputFxn)(Char *, UInt);
   146    
   147        /*!
   148         *  ======== outputFxn ========
   149         *  User suplied character output function
   150         *
   151         *  If this parameter is set to a non-`null` value, the specified
   152         *  function will be called by to output characters buffered within
   153         *  `SysMin`.
   154         *
   155         *  For example, if you define a function named `myOutputFxn`, the
   156         *  following configuration fragment will cause `SysMin` to call
   157         *  `myOutputFxn` whenever the character buffer is flushed.
   158         *  @p(code)
   159         *      var SysMin = xdc.useModule("xdc.runtime.SysMin");
   160         *      SysMin.outputFxn = "&myOutputFxn";
   161         *  @p
   162         *
   163         *  If this parameter is not set, a default function will be used which
   164         *  uses the ANSI C Standard Library function `fwrite()` (or `HOSTwrite`
   165         *  in the TI C Run Time Support library) to output
   166         *  accumulated output characters.
   167         *
   168         *  @see #OutputFxn
   169         */
   170        config OutputFxn outputFxn = null;
   171    
   172        /*!
   173         *  ======== abort ========
   174         *  Backend for `{@link xdc.runtime.System#abort()}`
   175         *
   176         *  This abort function writes the string to the internal
   177         *  output buffer and then gives all internal output to the
   178         *  `{@link #outputFxn}` function if the `{@link #flushAtExit}`
   179         *  configuration parameter is true.
   180         *
   181         *  @param(str)  message to output just prior to aborting
   182         *
   183         *      If non-`NULL`, this string should be output just prior to
   184         *      terminating.
   185         *
   186         *  @see xdc.runtime.ISystemSupport#abort
   187         */
   188        override Void abort(CString str);
   189    
   190        /*!
   191         *  ======== exit ========
   192         *  Backend for `{@link xdc.runtime.System#exit()}`
   193         *
   194         *  This exit function gives all internal output to the
   195         *  `{@link #outputFxn}` function if the `{@link #flushAtExit}`
   196         *  configuration parameter is true.
   197         *
   198         *  @see xdc.runtime.ISystemSupport#exit
   199         */
   200        override Void exit(Int stat);
   201    
   202        /*!
   203         *  ======== flush ========
   204         *  Backend for `{@link xdc.runtime.System#flush()}`
   205         *
   206         *  The `flush` writes the contents of the internal character buffer
   207         *  via the `{@link #outputFxn}` function.
   208         *
   209         *  @a(Warning)
   210         *  The `{@link xdc.runtime.System}` gate is used for thread safety during the
   211         *  entire flush operation, so care must be taken when flushing with
   212         *  this `ISystemSupport` module.  Depending on the nature of the
   213         *  `System` gate, your application's interrupt latency
   214         *  may become a function of the `bufSize` parameter!
   215         *
   216         *  @see xdc.runtime.ISystemSupport#flush
   217         */
   218        override Void flush();
   219    
   220        /*!
   221         *  ======== putch ========
   222         *  Backend for `{@link xdc.runtime.System#printf()}` and `{@link System#putch()}`
   223         *
   224         *  Places the character into an internal buffer. The `{@link #flush}`
   225         *  sends the internal buffer to the `{@link #outputFxn}` function.
   226         *  The internal buffer is also sent to the `SysMin_outputFxn`
   227         *  function by `{@link #exit}` and `{@link #abort}` if the
   228         *  `{@link #flushAtExit}` configuration parameter is true.
   229         *
   230         *  @see xdc.runtime.ISystemSupport#putch
   231         */
   232        override Void putch(Char ch);
   233    
   234        /*!
   235         *  ======== ready ========
   236         *  Test if character output can proceed
   237         *
   238         *  This function returns true if the internal buffer is non-zero.
   239         *
   240         *  @see xdc.runtime.ISystemSupport#ready
   241         */
   242        override Bool ready();
   243    
   244    internal:
   245    
   246        /*
   247         * ======== output ========
   248         *  SysMin_output__I is generated based on bufSize.
   249         *
   250         *  This function is generated so that the code does not contain a call to
   251         *  HOSTwrite if bufSize is 0. Otherwise, if bufSize is 0, the compiler
   252         *  would optimize out the HOSTwrite function, leaving a 0-length symbol.
   253         *  If the a client later tried to pull in HOSTwrite, there would be a
   254         *  symbol error.
   255         *
   256         *  This generated function is accessed through an internal config so
   257         *  that it is an indirect call in the ROM case, but optimized to a direct
   258         *  call in the RAM case.
   259         */
   260        Void output(Char *buf, UInt size);
   261        readonly config OutputFxn outputFunc = '&ti_sysbios_smp_SysMin_output__I';
   262    
   263        struct LineBuffer {
   264            UInt outidx;    /* index within outbuf to next Char to write */
   265            Char outbuf[256];
   266        }
   267    
   268        struct Module_State {
   269            LineBuffer lineBuffers[];
   270            Char outbuf[];  /* the output buffer */
   271            UInt outidx;    /* index within outbuf to next Char to write */
   272            Bool wrapped;   /* has the index (outidx) wrapped */
   273        }
   274    }