1    /*
     2     * Copyright (c) 2015, 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     *  ======== Hwi.xdc ========
    34     */
    35    
    36    package ti.sysbios.family.c28;
    37    
    38    import xdc.rov.ViewInfo;
    39    
    40    import xdc.runtime.Diags;
    41    import xdc.runtime.Log;
    42    import xdc.runtime.Assert;
    43    import xdc.runtime.Error;
    44    
    45    /*!
    46     *  ======== Hwi ========
    47     *  C28x Hardware Interrupt Manager
    48     *  
    49     *  This Hwi module provides C28 family-specific implementations of the
    50     *  APIs defined in {@link ti.sysbios.interfaces.IHwi IHwi}.
    51     *
    52     *  Additional C28 device-specific APIs are also provided.
    53     *
    54     *  ISRs specified with Hwi_plug will not go through the dispatcher; the
    55     *  ISR function will be directly plugged into the vector table. Hwi_plug can 
    56     *  be used for any ISR which does not call any SYS/BIOS APIs.
    57     *  
    58     *  ISRs can be plugged or created statically in the configuration script or 
    59     *  dynamically at runtime.
    60     *
    61     *  @p(html)
    62     *  <h3> PIE interrupts </h3>
    63     *  The peripheral interrupt expansion (PIE) block multiplexes 96 interrupts
    64     *  into 12 CPU interrupts. The PIE vector table includes entries for each of
    65     *  these 96 interrupts.  The relationship between the numbers corresponding
    66     *  to PIE interrupts and their groups (CPU interrupt) is as follows:
    67     *  PIEGROUPNUM = [(PIENUM - 32) / 8] + 1
    68     *  
    69     *  <h4>PIE MUXed Peripheral Interrupt Vector Table</h4>
    70     *  The table below shows a mapping between the PIENUM (interrupt id) and the
    71     *  various PIE groups. INTX.Y represents the interrupt number for the PIE 
    72     *  interrupt belonging to group X and group-specific id Y. 
    73     *  <br><br>
    74     *  <table border="1" cellpadding="3">
    75     *  <tr><th>      </th><th>INTX.1</th><th>INTX.2</th><th>INTX.3</th><th>INTX.4</th><th>INTX.5</th><th>INTX.6</th><th>INTX.7</th><th>INTX.8</th></tr>
    76     *  <tr><th>INT1.Y</th><td>32</td><td>33</td><td>34</td><td>35</td><td>36</td><td>37</td><td>38</td><td>39</td></tr>
    77     *  <tr><th>INT2.Y</th><td>40</td><td>41</td><td>42</td><td>43</td><td>44</td><td>45</td><td>46</td><td>47</td></tr>
    78     *  <tr><th>INT3.Y</th><td>48</td><td>49</td><td>50</td><td>51</td><td>52</td><td>53</td><td>54</td><td>55</td></tr>
    79     *  <tr><th>INT4.Y</th><td>56</td><td>57</td><td>58</td><td>59</td><td>60</td><td>61</td><td>62</td><td>63</td></tr>
    80     *  <tr><th>INT5.Y</th><td>64</td><td>65</td><td>66</td><td>67</td><td>68</td><td>69</td><td>70</td><td>71</td></tr>
    81     *  <tr><th>INT6.Y</th><td>72</td><td>73</td><td>74</td><td>75</td><td>76</td><td>77</td><td>78</td><td>79</td></tr>
    82     *  <tr><th>INT7.Y</th><td>80</td><td>81</td><td>82</td><td>83</td><td>84</td><td>85</td><td>86</td><td>87</td></tr>
    83     *  <tr><th>INT8.Y</th><td>88</td><td>89</td><td>90</td><td>91</td><td>92</td><td>93</td><td>94</td><td>95</td></tr>
    84     *  <tr><th>INT9.Y</th><td>96</td><td>97</td><td>98</td><td>99</td><td>100</td><td>101</td><td>102</td><td>103</td></tr>
    85     *  <tr><th>INT10.Y</th><td>104</td><td>105</td><td>106</td><td>107</td><td>108</td><td>109</td><td>110</td><td>111</td></tr>
    86     *  <tr><th>INT11.Y</th><td>112</td><td>113</td><td>114</td><td>115</td><td>116</td><td>117</td><td>118</td><td>119</td></tr>
    87     *  <tr><th>INT12.Y</th><td>120</td><td>121</td><td>122</td><td>123</td><td>124</td><td>125</td><td>126</td><td>127</td></tr>
    88     *  </table>
    89     *  <br>
    90     *
    91     *  On F2837X devices, there is an enhanced PIE block that can support up to
    92     *  192 individual interrupts multiplexed into the 12 CPU interrupts. The
    93     *  mapping between the PIENUM and PIE groups is identical to that shown in
    94     *  the above table for the first 96 interrupts. For the next 96 interrupts,
    95     *  the mapping is shown in the below table.
    96     *
    97     *  <h4>ePIE MUXed Peripheral Interrupt Vector Table</h4>
    98     *  The table below shows a mapping between the PIENUM (interrupt id) and the
    99     *  various PIE groups for ePIE interrupts 128 to 223. INTX.Y represents the
   100     *  interrupt number for the PIE interrupt belonging to group X and
   101     *  group-specific id Y.
   102     *  <br><br>
   103     *  <table border="1" cellpadding="3">
   104     *  <tr><th>      </th><th>INTX.1</th><th>INTX.2</th><th>INTX.3</th><th>INTX.4</th><th>INTX.5</th><th>INTX.6</th><th>INTX.7</th><th>INTX.8</th></tr>
   105     *  <tr><th>INT1.Y</th><td>128</td><td>129</td><td>130</td><td>131</td><td>132</td><td>133</td><td>134</td><td>135</td></tr>
   106     *  <tr><th>INT2.Y</th><td>136</td><td>137</td><td>138</td><td>139</td><td>140</td><td>141</td><td>142</td><td>143</td></tr>
   107     *  <tr><th>INT3.Y</th><td>144</td><td>145</td><td>146</td><td>147</td><td>148</td><td>149</td><td>150</td><td>151</td></tr>
   108     *  <tr><th>INT4.Y</th><td>152</td><td>153</td><td>154</td><td>155</td><td>156</td><td>157</td><td>158</td><td>159</td></tr>
   109     *  <tr><th>INT5.Y</th><td>160</td><td>161</td><td>162</td><td>163</td><td>164</td><td>165</td><td>166</td><td>167</td></tr>
   110     *  <tr><th>INT6.Y</th><td>168</td><td>169</td><td>170</td><td>171</td><td>172</td><td>173</td><td>174</td><td>175</td></tr>
   111     *  <tr><th>INT7.Y</th><td>176</td><td>177</td><td>178</td><td>179</td><td>180</td><td>181</td><td>182</td><td>183</td></tr>
   112     *  <tr><th>INT8.Y</th><td>184</td><td>185</td><td>186</td><td>187</td><td>188</td><td>189</td><td>190</td><td>191</td></tr>
   113     *  <tr><th>INT9.Y</th><td>192</td><td>193</td><td>194</td><td>195</td><td>196</td><td>197</td><td>198</td><td>199</td></tr>
   114     *  <tr><th>INT10.Y</th><td>200</td><td>201</td><td>202</td><td>203</td><td>204</td><td>205</td><td>206</td><td>207</td></tr>
   115     *  <tr><th>INT11.Y</th><td>208</td><td>209</td><td>210</td><td>211</td><td>212</td><td>213</td><td>214</td><td>215</td></tr>
   116     *  <tr><th>INT12.Y</th><td>216</td><td>217</td><td>218</td><td>219</td><td>220</td><td>221</td><td>222</td><td>223</td></tr>
   117     *  </table>
   118     *  <br>
   119     *  @p
   120     *
   121     *  PIE interrupts must clear the CPU acknowledge bit for their respective PIE
   122     *  block before further interrupts from that block can occur. The SYS/BIOS 6
   123     *  dispatcher (used by interrupts created using {@link #create}) takes care of
   124     *  this, however this differs from DSP/BIOS 5, in which the application is
   125     *  expected to acknowledge the interrupt.
   126     *
   127     *
   128     *  PIE interrupt ISRs plugged with {@link #plug}(which do not use the
   129     *  dispatcher), as well as legacy created PIE HWI instances, must
   130     *  acknowledge the interrupt manually before returning from the ISR.
   131     *
   132     *  @a(Example)
   133     *
   134     *  The following configuration code can be used to plug the function
   135     *  'myHwi' into the vector table for PIE group 5, interrupt 1.  Using the above
   136     *  table, one can see that this corresponds to interrupt ID 64:
   137     *
   138     *  @p(code)
   139     *      Program.global.hwi5 = Hwi.create(64, '&myHwi');
   140     *  @p
   141     *
   142     *  @a(Minimal Latency Interrupts)
   143     *  For applications requiring extremely low interrupt latency, 
   144     *  the 28x Hwi module allows the user to configure interrupts
   145     *  that operate independent of the SYS/BIOS interrupt dispatcher
   146     *  which are disabled for extremely short periods of time
   147     *  as compared to interrupts handled by the dispatcher.
   148     *  @p(html)
   149     *  <b>
   150     *  Though not a precisely correct classification, these
   151     *  interrupts are referred to as "Zero Latency" interrupts.
   152     *   </b>
   153     *  @p
   154     *  When configured to support "Zero Latency" interrupts, the 
   155     *  {@link #disable}, {@link #restore}, and {@link #enable} APIs
   156     *  manipulate the IER register rather than the INTM bit to 
   157     *  provide critical section protection. The IER bits associated
   158     *  with the configured "Zero Latency" interrupts are left enabled
   159     *  while all other bits are disabled and enabled as required to 
   160     *  functionally achieve the API requirements.
   161     *  Explicit calls to the {@link #disableIER} or {@link #disablePIEIER}
   162     *  APIs operate on ALL IER bits, even those associated with the
   163     *  configured "Zero Latency" interrupts.
   164     *  Refer to {@link #zeroLatencyIERMask} for using information.
   165     *
   166     *  @a(NOTE)
   167     *  In this Hwi module implementation, the instance config parameter value
   168     *  {@link #MaskingOption_LOWER} is equivalent to {@link #MaskingOption_SELF}.
   169     *  Statically configuring a Hwi object's {@link #Params.maskSetting} to 
   170     *  {@link #MaskingOption_LOWER} will result in the generation of a benign
   171     *  build warning. Dynamic usages of {@link #MaskingOption_LOWER} will be
   172     *  silently converted to {@link #MaskingOption_SELF}.
   173     *
   174     *  @p(html)
   175     *  <h3> Calling Context </h3>
   176     *  <table border="1" cellpadding="3">
   177     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
   178     *
   179     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th><th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   180     *    <!--                                                                                                                 -->
   181     *    <tr><td> {@link #clearInterrupt}    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   182     *    <tr><td> {@link #disable}           </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   183     *    <tr><td> {@link #disableIER}        </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   184     *    <tr><td> {@link #disableInterrupt}  </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   185     *    <tr><td> {@link #disablePIEIER}     </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   186     *    <tr><td> {@link #enable}            </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   187     *    <tr><td> {@link #enableIER}         </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   188     *    <tr><td> {@link #enableInterrupt}   </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   189     *    <tr><td> {@link #enablePIEIER}      </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   190     *    <tr><td> {@link #getHandle}         </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   191     *    <tr><td> {@link #getIFR}            </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   192     *    <tr><td> {@link #getIntrReturnAddr} </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   193     *    <tr><td> {@link #Params_init}       </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   194     *    <tr><td> {@link #pieEnabled}        </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   195     *    <tr><td> {@link #plug}              </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   196     *    <tr><td> {@link #restore}           </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   197     *    <tr><td> {@link #restoreIER}        </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   198     *    <tr><td> {@link #restoreInterrupt}  </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   199     *    <tr><td> {@link #ack}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   200     *    <tr><td> {@link #create}            </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr> 
   201     *    <tr><td> {@link #construct}         </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   202     *    <tr><td> {@link #delete}            </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   203     *    <tr><td> {@link #destruct}          </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   204     *    <tr><td> {@link #getHookContext}    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   205     *    <tr><td> {@link #reconfig}          </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   206     *    <tr><td> {@link #setFunc}           </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   207     *    <tr><td> {@link #setHookContext}    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   208     *    <tr><td colspan="6"> Definitions: <br />
   209     *       <ul>
   210     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   211     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   212     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   213     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   214     *           <ul>
   215     *             <li> In your module startup after this module is started (e.g. 
   216                        Hwi_Module_startupDone() returns TRUE). </li>
   217     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   218     *             <li> During main().</li>
   219     *             <li> During BIOS.startupFxns.</li>
   220     *           </ul>
   221     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   222     *           <ul>
   223     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   224     *             <li> In your module startup before this module is started 
   225                        (e.g. Hwi_Module_startupDone() returns FALSE).</li>
   226     *           </ul>
   227     *       </ul>
   228     *    </td></tr>
   229     *
   230     *
   231     *  </table>
   232     *  @p
   233     *
   234     */
   235    
   236    @Template("./Hwi.xdt")  /* generates the vector table and the dispatcher */
   237    @ModuleStartup          /* generate a call to Hwi_init at startup */
   238    @InstanceInitStatic     /* allow constructs in static only systems */
   239    
   240    module Hwi inherits ti.sysbios.interfaces.IHwi
   241    {
   242    
   243        // -------- Module Constants --------
   244    
   245        /*! C28 supports 32 interrupts. */
   246        const Int NUM_INTERRUPTS = 32;
   247    
   248        /*!
   249         * ======== NUM_INTERRUPTS_PIE ========
   250         * C28 supports 96 PIE interrupts
   251         *
   252         * Note: TMS320F2837X devices have an enhanced PIE that supports
   253         * 196 PIE interrupts. This config param is set to 192 by default.
   254         */
   255        config Int NUM_INTERRUPTS_PIE = 96;
   256        config Int NUM_INTERRUPTS_ALL = NUM_INTERRUPTS + NUM_INTERRUPTS_PIE;
   257    
   258        // -------- Module Types --------
   259    
   260        /*! Hwi plug function type definition, which doesn't take an arg. */
   261        typedef Void (*PlugFuncPtr)(void);
   262    
   263        /*! @_nodoc */
   264        metaonly struct BasicView {
   265            Ptr         halHwiHandle;
   266            String      label;
   267            Int         intNum;
   268            String      fxn; 
   269            UArg        arg; 
   270            Ptr         irp; 
   271            String      disableMask;   /* Interrupts to mask during ISR.   */
   272            String      restoreMask;   /* Interrupts to restore after ISR. */
   273        };
   274        
   275        /*! @_nodoc */
   276        metaonly struct ModuleView {
   277            String      options[4];
   278            String      hwiStackPeak;
   279            SizeT       hwiStackSize;
   280            Ptr         hwiStackBase;
   281            String      globalEnable;
   282            String      shadowIER;
   283        };
   284    
   285        /*! @_nodoc */
   286        @Facet
   287        metaonly config ViewInfo.Instance rovViewInfo = 
   288            ViewInfo.create({
   289                viewMap: [
   290                    ['Basic',    {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic',    structName: 'BasicView'}],
   291                    ['Module',   {type: ViewInfo.MODULE,   viewInitFxn: 'viewInitModule',   structName: 'ModuleView'}]
   292                ]
   293            });
   294     
   295        /*! 
   296         *  Assert raised when an invalid interrupt number is passed to a Hwi call
   297         */
   298        config Assert.Id A_badIntNum = {
   299            msg: "A_badIntNum: Invalid interrupt number"
   300        }; 
   301        
   302        /*! 
   303         *  Assert raised when an invalid argument has been passed to a function
   304         */
   305        config Assert.Id A_invalidArg = {
   306            msg: "A_invalidArg: Invalid argument"
   307        };
   308        
   309        /*! 
   310         *  Assert raised when there is a conflict with the zero latency IER mask
   311         * 
   312         *  This assert is raised when trying to create a Hwi with an intNum that
   313         *  conflicts with the supplied zero latency IER mask.
   314         */
   315        config Assert.Id A_zeroLatencyConflict = {
   316            msg: "A_zeroLatencyConflict: Conflict with zero latency IER mask"
   317        };
   318        
   319        /*! 
   320         *  Error raised when an unplugged interrupt is flagged
   321         */
   322        config Error.Id E_unpluggedInterrupt = {
   323            msg: "E_unpluggedInterrupt: Unplugged interrupt flagged: intr# %d"
   324        };
   325    
   326        /*!
   327         *  Error raised when Hwi is already defined
   328         */
   329        config Error.Id E_alreadyDefined = {
   330            msg: "E_alreadyDefined: Hwi already defined: intr# %d"
   331        };
   332        
   333    
   334        // -------- Module Configuration --------
   335    
   336        /*!
   337         *  ======== NonDispatchedInterrupt ========
   338         *  Non-dispatched interrupt object
   339         *
   340         *  Provided so that XGCONF users can easily plug non-dispatched interrupts
   341         *  
   342         *  @field(intNum)      Interrupt number
   343         *  @field(fxn)         Non-dispatched interrupt service routine (ISR)
   344         *  @field(enableInt)   Enable the interrupt after plugging the vector
   345         */
   346        metaonly struct NonDispatchedInterrupt {
   347            Int             intNum;
   348            PlugFuncPtr     fxn;
   349            Bool            enableInt;
   350        };
   351    
   352        /*!
   353         *  ======== nonDispatchedInterrupts ========
   354         *  Non-dispatched interrupt array.
   355         *
   356         *  Provided so that XGCONF users can easily plug non-dispatched interrupts
   357         */
   358        metaonly config NonDispatchedInterrupt nonDispatchedInterrupts[string];
   359        
   360        /*!
   361         *  ======== zeroLatencyIERMask ========
   362         *  Zero Latency IER Mask
   363         *
   364         *  CPU interrupts specified in this mask (which corresponds to the 16-bit 
   365         *  IER register) are carefully managed so that they are disabled for
   366         *  only the bare minimum time required to safely manipulated the IER 
   367         *  register.
   368         *  This means that the  
   369         *  {@link #disable}, {@link #enable}, and {@link #restore} calls leave the
   370         *  zero latency CPU interrupts enabled after being called.  Zero latency
   371         *  operation may be used to ensure minimal interrupt-to-ISR time for 
   372         *  non-BIOS interrupt handlers in applications that demand low latency.
   373         *
   374         *  @a(note)
   375         *  @p(html)
   376         *  <b>
   377         *  While referred to as "Zero Latency Interrupts", the interrupts 
   378         *  specified in the {@link #zeroLatencyIERMask} are NOT TRULY ZERO
   379         *  LATENCY!
   380         *  They are still disabled briefly in software by the Hwi_disable(),
   381         *  Hwi_restore(), and Hwi_enable() APIs while the IER register bits
   382         *  are manipulated.
   383         * 
   384         *  Additionally, interrupts are globally disabled automatically 
   385         *  by the 28x hardware when an interrupt is taken. The Hwi module's
   386         *  interrupt dispatcher quickly (ie: within 30 instructions)
   387         *  re-enables interrupts globally after carefully manipulating the 
   388         *  IER register accordingly.
   389         *  </b>
   390         *  @p
   391         *
   392         *  It is important to note that zero latency and non-zero latency PIE
   393         *  interrupts may not share a common PIE group. The entire PIE group whose
   394         *  bit is set in the zeroLatencyIERMask will be treated as zero latency.
   395         *
   396         *  @a(warning)
   397         *  Enabling zero latency mode (specifying a non-zero zeroLatencyIERMask)
   398         *  generates alternate (and slower) code used to disable, enable and
   399         *  restore interrupts.  This alternate code will maintain a shadow copy
   400         *  of interrupt state (IER register and global interrupt state). {@link
   401         *  #disableIER}, {@link #enableIER} and {@link #restoreIER} will update
   402         *  both the IER register and its shadow.  The {@link #disable} call
   403         *  will copy the zero latency IER mask (supplied here) into the IER 
   404         *  register.  The {@link #enable} call will copy the contents of the
   405         *  shadow IER register into the actual register. The {@link #restore}
   406         *  call may either disable or enable the non-zero-latency interrupts.
   407         *
   408         *  It is important to be aware of the performance penalty associated with
   409         *  using zero latency interrupts before using this feature.
   410         *
   411         *  Example:
   412         *  
   413         *  @p(code)
   414         *  var Hwi = xdc.useModule('ti.sysbios.family.c28.Hwi');
   415         *  Hwi.zeroLatencyIERMask = 0x0010; 
   416         *
   417         *  // PIE group 5 classified as zero latency
   418         *  @p
   419         *      
   420         */
   421        config Bits16 zeroLatencyIERMask = 0x0;
   422    
   423        /*!
   424         *  Issued just prior to Hwi function invocation (with interrupts disabled)
   425         */
   426        config Log.Event LM_begin = {
   427            mask: Diags.USER1 | Diags.USER2,
   428            msg: "LM_begin: hwi: 0x%x, func: 0x%x, preThread: %d, intNum: %d, irp: 0x%x"
   429        };
   430    
   431        /*!
   432         *  Issued just after return from Hwi function (with interrupts disabled)
   433         */
   434        config Log.Event LD_end = {
   435            mask: Diags.USER2,
   436            msg: "LD_end: hwi: 0x%x"
   437        };
   438    
   439        // -------- Module Functions --------
   440    
   441        /*!
   442         *  ======== disable ========
   443         *  Globally disable interrupts.
   444         *
   445         *  Hwi_disable globally disables hardware interrupts and returns an
   446         *  opaque key indicating whether interrupts were globally enabled or
   447         *  disabled on entry to Hwi_disable(). 
   448         *  The actual value of the key is target/device specific and is meant 
   449         *  to be passed to Hwi_restore(). 
   450         *
   451         *  Call Hwi_disable before a portion of a function that needs
   452         *  to run without interruption. When critical processing is complete, call
   453         *  Hwi_restore or Hwi_enable to reenable hardware interrupts.
   454         *
   455         *  Servicing of interrupts that occur while interrupts are disabled is
   456         *  postponed until interrupts are reenabled. However, if the same type 
   457         *  of interrupt occurs several times while interrupts are disabled, 
   458         *  the interrupt's function is executed only once when interrupts are 
   459         *  reenabled.
   460         *
   461         *  A context switch can occur when calling Hwi_enable or Hwi_restore if
   462         *  an enabled interrupt occurred while interrupts are disabled.
   463         *
   464         *  Hwi_disable may be called from main(). However, since Hwi interrupts
   465         *  are already disabled in main(), such a call has no effect.
   466         *
   467         *  @a(constraints)
   468         *  If a Task switching API such as 
   469         *  {@link ti.sysbios.knl.Semaphore#pend Semaphore_pend()}, 
   470         *  {@link ti.sysbios.knl.Semaphore#post Semaphore_post()},
   471         *  {@link ti.sysbios.knl.Task#sleep Task_sleep()}, or
   472         *  {@link ti.sysbios.knl.Task#yield Task_yield()} 
   473         *  is invoked which results in a context switch while
   474         *  interrupts are disabled, an embedded call to 
   475         *  {@link #enable Hwi_enable} occurs
   476         *  on the way to the new thread context which unconditionally re-enables
   477         *  interrupts. Interrupts will remain enabled until a subsequent 
   478         *  {@link #disable Hwi_disable}
   479         *  invocation.
   480         *
   481         *  Swis always run with interrupts enabled.
   482         *  See {@link ti.sysbios.knl.Swi#post Swi_post()} for a discussion Swis and
   483         *  interrupts.
   484         *
   485         *  @b(returns)     opaque key for use by Hwi_restore()
   486         */
   487        @Macro
   488        override UInt disable();
   489    
   490        /*!
   491         *  ======== enable ========
   492         */
   493        @Macro
   494        override UInt enable();
   495    
   496        /*!
   497         *  ======== restore ========
   498         */
   499        @Macro
   500        override Void restore(UInt key);
   501    
   502        /*!
   503         *  ======== inUseMeta ========
   504         *  @_nodoc
   505         *  Check for Hwi already in use.
   506         *  For internal SYS/BIOS use only. 
   507         *  Should be called prior to any internal Hwi.create().
   508         *
   509         *  @param(intNum)  interrupt number
   510         */
   511        metaonly Bool inUseMeta(UInt intNum);
   512    
   513        /*!
   514         *  ======== plug ========
   515         *  Plug an interrupt vector with an ISR address.
   516         *
   517         *  plug hooks up the specified function as the branch target for a
   518         *  hardware interrupt (fielded by the CPU) at the vector address
   519         *  corresponding to intNum. plug does not enable the interrupt. Use
   520         *  Hwi_enableIER to enable specific interrupts.
   521         *
   522         *  This API can plug the full set of vectors supported by the PIE (0-127).
   523         *
   524         *  @param(intNum)  interrupt number
   525         *  @param(fxn)     pointer to ISR function
   526         */
   527        Void plug(UInt intNum, PlugFuncPtr fxn);
   528    
   529        /*!
   530         *  ======== plugMeta ========
   531         *  Statically plug an interrupt vector with an ISR address.
   532         *
   533         *  @param(intNum)  Interrupt number
   534         *  @param(fxn)     Pointer to ISR function
   535         */
   536        metaonly Void plugMeta(UInt intNum, PlugFuncPtr fxn);
   537    
   538        /*!
   539         *  ======== getHandle ========
   540         *  Returns Hwi handle associated with intNum
   541         *
   542         *  @param(intNum)  Interrupt number
   543         *
   544         *  @b(returns)     Hwi handle associated with intNum
   545         */
   546        Handle getHandle(UInt intNum);
   547        
   548        /*!
   549         *  ======== disableInterrupt ========
   550         *  @Hwi The behavior of Hwi_disableInterrupt depends on whether the intNum
   551         *  is a PIE interrupt number.  If so, the appropriate bit in its group's 
   552         *  PIEIER register is cleared.  Note that, unlike 
   553         *  {@link #enableInterrupt}, disableInterrupt does not touch IER bits
   554         *  when operating upon a PIE interrupt number. If intNum is a non-PIE  
   555         *  interrupt (1 <= intNum <= 14), then the corresponding bit in the IER 
   556         *  register is cleared.
   557         *
   558         *  @Hwi The return value is a key whose value reflects the previous state of
   559         *  the PIEIER bit.
   560         */
   561        override UInt disableInterrupt(UInt intNum);
   562        
   563        /*!
   564         *  ======== enableInterrupt ========
   565         *  @Hwi The behavior of enableInterrupt depends on whether the intNum
   566         *  is a PIE interrupt number.  If so, two operations are
   567         *  performed. The IER bit for intNum's PIE group is set and the
   568         *  appropriate bit in its group's PIEIER register is also set.  However,
   569         *  if intNum is a non-PIE interrupt (1 <= intNum <= 14), then the
   570         *  corresponding bit in the IER register is set.
   571         *
   572         *  @Hwi The return value is a key whose value reflects the previous state of
   573         *  the PIEIER bit. Note that the key does not reflect
   574         *  the IER register's previous state even if its state is modified by this
   575         *  call.
   576         */
   577        override UInt enableInterrupt(UInt intNum);
   578        
   579        /*!
   580         *  ======== restoreInterrupt ========
   581         *  @Hwi The behavior of restoreInterrupt depends on whether the intNum
   582         *  is a PIE interrupt number.  If so, the supplied key returned by an 
   583         *  earlier call to {@link #disableInterrupt} and {@link #enableInterrupt}
   584         *  is used to restore the corresponding PIEIER bit to its state before
   585         *  the earlier call.
   586         *  However, if intNum is a non-PIE interrupt (1 <= intNum <= 14), then the
   587         *  corresponding bit in the IER register is restored using the key.
   588         */
   589        override Void restoreInterrupt(UInt intNum, UInt key);
   590    
   591        /*!
   592         *  ======== clearInterrupt ========
   593         *  @Hwi The behavior of clearInterrupt depends on whether the intNum
   594         *  is a PIE interrupt number.  If so, the corresponding PIEIFR bit is 
   595         *  cleared.  If not (1 <= intNum <= 14), the corresponding IFR bit is 
   596         *  cleared.
   597         */
   598        override Void clearInterrupt(UInt intNum);
   599        
   600        /*!
   601         *  ======== disableIER ========
   602         *  Disable certain maskable interrupts.
   603         *
   604         *  Atomically disables specific interrupts by clearing the bits
   605         *  specified by mask in the Interrupt Enable Register (IER).
   606         *
   607         *  The IER bits to be cleared should be set to 1 in the mask.
   608         *
   609         *  @param(mask)    bitmask of interrupts to disable
   610         *
   611         *  @b(returns)     previous IER settings bitmask
   612         */
   613        Bits16 disableIER(Bits16 mask);
   614    
   615        /*!
   616         *  ======== enableIER ========
   617         *  Enable certain maskable interrupts.
   618         *
   619         *  Atomically enables specific interrupts by setting the bits 
   620         *  specified by mask in the Interrupt Enable Register (IER).
   621         *
   622         *  The IER bits to be set should be set to 1 in the mask.
   623         *
   624         *  @param(mask)    Bitmask of interrupts to enable
   625         *
   626         *  @b(returns)     Previous IER settings bitmask
   627         */
   628        Bits16 enableIER(Bits16 mask);
   629    
   630        /*!
   631         *  ======== restoreIER ========
   632         *  Restore maskable interrupts
   633         *
   634         *  Restores maskable interrupts to the state they were in 
   635         *  when either disableIER() or enableIER() was called.
   636         *
   637         *  Atomically writes the given mask to the IER register. Typically used
   638         *  to restore the IER register to the state returned from a call to
   639         *  either {@link #disableIER()} or {@link #enableIER()}.
   640         *
   641         *  @param(mask)    Bitmask of interrupts to restore
   642         *
   643         *  @b(returns)     Previous IER settings bitmask
   644         */
   645        Bits16 restoreIER(Bits16 mask);
   646    
   647        /*!
   648         *  ======== enablePIEIER ========
   649         *  Enable interrupts in a PIE group
   650         *
   651         *  Atomically enable PIE interrupts in a single PIE group
   652         *  according to supplied PIEIER bitmask
   653         *
   654         *  @param(groupNum)    PIE group number
   655         *  @param(pieMask)     PIEIER enable mask for group
   656         *
   657         *  @b(returns)         Previous PIEIER settings bitmask
   658         */
   659        Bits16 enablePIEIER(UInt groupNum, Bits16 pieMask);
   660    
   661        /*!
   662         *  ======== disablePIEIER ========
   663         *  Disable interrupts in a PIE group
   664         *
   665         *  Atomically disable PIE interrupts in a single PIE group
   666         *  according to supplied PIEIER bitmask
   667         *
   668         *  @param(groupNum)    PIE group number
   669         *  @param(pieMask)     PIEIER disable mask for group
   670         *
   671         *  @b(returns)         Previous PIEIER settings bitmask
   672         */
   673        Bits16 disablePIEIER(UInt groupNum, Bits16 pieMask);
   674        
   675        /*!
   676         *  ======== restorePIEIER ========
   677         *  Restores interrupts in a PIE group
   678         *
   679         *  Atomically restore PIE interrupts in a single PIE group
   680         *  according to supplied PIEIER bitmask
   681         *
   682         *  @param(groupNum)    PIE group number
   683         *  @param(pieMask)     PIEIER restore mask for group
   684         *
   685         *  @b(returns)         Previous PIEIER settings bitmask
   686         */
   687        Bits16 restorePIEIER(UInt groupNum, Bits16 pieMask);
   688    
   689        /*!
   690         *  ======== getInterruptFlag ========
   691         *  @_nodoc
   692         *  Returns IFR/PIEIFR flag corresponding to a single interrupt number
   693         *
   694         *  If intNum >= 32, the PIEIFR bit corresponding to intNum is returned.
   695         *  If 1 <= intNum <= 14, the IFR bit corresponding to intNum is returned.
   696         *
   697         *  @param(intNum)      Interrupt number
   698         *
   699         *  @b(returns)         Nonzero if interrupt is flagged, zero otherwise
   700         */   
   701        Bits16 getInterruptFlag(UInt intNum);
   702        
   703        /*!
   704         *  ======== getIERMask ========
   705         *  @_nodoc
   706         *  Calculates IER mask based on an array of C28x interrupt vector IDs
   707         *
   708         *  For each vector id the supplied array, a bit in the generated IER mask
   709         *  is set.  If 1 <= intNum <= 14, the corresponding IER bit is set. If
   710         *  intNum >= 32, the IER mask bit corresponding to the PIE interrupt's 
   711         *  group is set.
   712         *
   713         *  getIERMask may be used to generate a zero latency IER mask given
   714         *  an array of vector IDs.
   715         *
   716         *  @param(vecIds)      Array of vector IDs
   717         *
   718         *  @b(returns)         Calculated IER Mask
   719         */  
   720        metaonly UInt getIERMask(UInt vecIds[]);
   721    
   722    instance:
   723    
   724        /*! 
   725         *  Dispatcher auto-nesting interrupt disable mask.
   726         * 
   727         *  When the dispatcher's auto interrupt nesting support feature 
   728         *  is enabled (see {@link #dispatcherAutoNestingSupport}), 
   729         *  this mask defines which IER bits are disabled prior to invoking
   730         *  the user's ISR function with GIE = 1.
   731         *  
   732         *  disableMask bits set to 1 correspond to IER bits that will be cleared
   733         *  prior to invoking the ISR.
   734         *
   735         *  The value of this mask is normally auto-calculated based on the
   736         *  value of the maskSetting. However, manual setting of this
   737         *  mask is enabled by setting the maskSetting to 
   738         *  {@link #MaskingOption MaskingOption_BITMASK}.
   739         *
   740         *  The default value is derived from the 
   741         *  {@link #MaskingOption MaskingOption_SELF}
   742         *  maskSetting.
   743         */
   744        config Bits16 disableMask = 0;
   745    
   746        /*! 
   747         *  Dispatcher auto-nesting interrupt restore mask.
   748         * 
   749         *  When the dispatcher's auto interrupt nesting support feature 
   750         *  is enabled (see {@link #dispatcherAutoNestingSupport}), 
   751         *  this mask defines which IER bits are restored to their previous
   752         *  setting upon return from the user's ISR function.
   753         *  
   754         *  restoreMask bits set to 1 correspond to IER bits that will be restored.
   755         *  
   756         *  The value of this mask is normally auto-calculated based on the
   757         *  value of the maskSetting. However, manual setting of this
   758         *  mask is enabled by setting the maskSetting to 
   759         *  {@link #MaskingOption MaskingOption_BITMASK}.
   760         *
   761         *  The default value is derived from the 
   762         *  {@link #MaskingOption MaskingOption_SELF}
   763         *  maskSetting.
   764         */
   765        config Bits16 restoreMask = 0;
   766    
   767        /*!
   768         *  Interrupt priority. Not supported on this target.
   769         */
   770        override config Int priority = 0;
   771    
   772        /*!
   773         *  ======== reconfig ========
   774         *  Reconfigure a dispatched interrupt.
   775         */
   776        Void reconfig(FuncPtr fxn, const Params *params);
   777        
   778        /*!
   779         *  Enable automatic acknowledgement of PIE interrupts by the Hwi interrupt
   780         *  dispatcher.
   781         */
   782        config Bool enableAck = true;
   783    
   784    internal:   /* not for client use */
   785    
   786        /*
   787         *  ======== postInit ========
   788         *  finish initializing static and dynamic Hwis
   789         */
   790        Int postInit(Object *hwi, Error.Block *eb);
   791    
   792        /* 
   793         * Swi and Task module function pointers. 
   794         * Used to decouple Hwi from Swi and Task when 
   795         * dispatcherSwiSupport or
   796         * dispatcherTaskSupport is false.
   797         */
   798        config UInt (*swiDisable)();
   799        config Void (*swiRestoreHwi)(UInt);
   800        config UInt (*taskDisable)();
   801        config Void (*taskRestoreHwi)(UInt);
   802    
   803        /*
   804         *  The IFR cregister is write-only, so a special assembly function is
   805         *  needed to read the value of the IFR on the 28x.
   806         */
   807        Bits16 getIFR();
   808        
   809        /* 'ack' interrupt in case of PIE */
   810        Void ack(Handle hwi);
   811        
   812        /* Used to temporarily plug PIE vector table when clearing PIEIFR */
   813        Void interruptReturn();
   814        
   815        /* Used in assert that no conflict exists between zero/non-zero latency */
   816        Bits16 getIERBit(UInt intNum);
   817        
   818        /* Interrupt Dispatcher */
   819        Void dispatchC(Int intNum);
   820        /* Interrupt dispatcher core */
   821        Void dispatchCore(Int intNum);
   822    
   823        /* assembly language code that switches SP and calls dispatchCore */
   824        Void switchAndDispatch(Int intNum);
   825        
   826        /* unplugged interrupt handler */
   827        Void unPluggedInterrupt();
   828    
   829        /* const array to hold all HookSet objects. */
   830        config HookSet hooks[length] = [];
   831    
   832        /* Meta World Only Hwi Configuration Object. */
   833        metaonly struct InterruptObj {
   834            String name;                /* symbol used for vector table entry   */
   835            Bool used;                  /* Interrupt already defined?           */
   836            Bool useDispatcher;         /* Should dispatcher handle this Int?   */
   837            FuncPtr fxn;                /* Dispatched ISR function              */
   838            PlugFuncPtr pfxn;           /* "Hwi_plug'd" ISR function.           */
   839        };
   840        
   841        /* Used for statically fixing certain PIEIER addresses */
   842        const Ptr PIEIER1_ADDR = 0x000CE2;
   843    
   844        /* Example string: '0x02a0' */
   845        metaonly config String zeroLatencyIERMaskStr;
   846        metaonly config String nonZeroLatencyIERMaskStr;
   847        
   848        /*
   849         * Meta-only array of interrupt objects.
   850         * This meta-only array of Hwi config objects is initialized
   851         * in Hwi.xs:module$meta$init().
   852         */
   853        metaonly config InterruptObj interrupt[];
   854    
   855        struct Instance_State {
   856            UInt        intNum;         /* interrupt number                     */
   857            Bool        enableInt;      /* enable interrupt during startup?     */
   858            Bool        enableAck;      /* should dispatcher ack the int?       */
   859            Bits16      disableMask;    /* Interrupts to mask during ISR.       */
   860            Bits16      restoreMask;    /* Interrupts to restore after ISR.     */
   861            Bits16      ierBitMask;     /* bit number in IER for the instance   */
   862            UArg        arg;            /* Argument to Hwi function.            */
   863            FuncPtr     fxn;            /* Hwi function.                        */
   864            Irp         irp;            /* for IRP tracking                     */
   865            Ptr         hookEnv[];
   866        };
   867     
   868        struct Module_State {
   869            Bits16      ierMask;        /* Initial IER mask                     */
   870            Char        *isrStack;      /* Points to isrStack address           */
   871            Char        *taskSP;        /* temporary storage of Task's SP       */
   872            Handle      dispatchTable[];/* dispatch table                       */
   873            Irp         irp;            /* current IRP                          */
   874            Bool        globalEnable;   /* for zero latency only                */
   875            Bits16      shadowIER;      /* for zero latency only                */
   876            Ptr         isrStackBase;   /* ISR stack base address               */
   877            Ptr         isrStackSize;   /* ISR stack size                       */
   878        };
   879    }