safety_critical_embedded_controller.html 129 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
  4. <title>Safety Critical Embedded Controller</title>
  5. <link rel="stylesheet" href="boostbook.css" type="text/css">
  6. <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
  7. <link rel="home" href="index.html" title="Safe Numerics">
  8. <link rel="up" href="case_studies.html" title="Case Studies">
  9. <link rel="prev" href="composition_with_other_libraries.html" title="Composition with Other Libraries">
  10. <link rel="next" href="notes.html" title="Background">
  11. </head>
  12. <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
  13. <table cellpadding="2" width="100%"><tr>
  14. <td valign="top"><img href="index.html" height="164px" src="pre-boost.jpg" alt="Library Documentation Index"></td>
  15. <td><h2>Safe Numerics</h2></td>
  16. </tr></table>
  17. <div class="spirit-nav">
  18. <a accesskey="p" href="composition_with_other_libraries.html"><img src="images/prev.png" alt="Prev"></a><a accesskey="u" href="case_studies.html"><img src="images/up.png" alt="Up"></a><a accesskey="h" href="index.html"><img src="images/home.png" alt="Home"></a><a accesskey="n" href="notes.html"><img src="images/next.png" alt="Next"></a>
  19. </div>
  20. <div class="section">
  21. <div class="titlepage"><div><div><h3 class="title">
  22. <a name="safe_numerics.safety_critical_embedded_controller"></a>Safety Critical Embedded Controller</h3></div></div></div>
  23. <div class="toc"><dl class="toc">
  24. <dt><span class="section"><a href="safety_critical_embedded_controller.html#idm130205797504">How a Stepper Motor Works</a></span></dt>
  25. <dt><span class="section"><a href="safety_critical_embedded_controller.html#idm130205785344">Updating the Code</a></span></dt>
  26. <dt><span class="section"><a href="safety_critical_embedded_controller.html#idm130205769072">Refactor for Testing</a></span></dt>
  27. <dt><span class="section"><a href="safety_critical_embedded_controller.html#idm130205760352">Compiling on the Desktop</a></span></dt>
  28. <dt><span class="section"><a href="safety_critical_embedded_controller.html#idm130205230160">Trapping Errors at Compile Time</a></span></dt>
  29. <dt><span class="section"><a href="safety_critical_embedded_controller.html#idm130204123024">Summary</a></span></dt>
  30. </dl></div>
  31. <p>Suppose we are given the task of creating stepper motor driver
  32. software to drive a robotic hand to be used in robotic micro surgery. The
  33. processor that has been selected by the engineers is the <a href="http://www.microchip.com/wwwproducts/en/PIC18F2520" target="_top">PIC18F2520</a>
  34. manufactured by <a href="http://www.microchip.com" target="_top">Microchip
  35. Corporation</a>. This processor has 32KB of program memory. On a
  36. processor this small, it's common to use a mixture of 8, 16, and 32 bit data
  37. types in order to minimize memory footprint and program run time. The type
  38. <code class="computeroutput">int</code> has 16 bits. It's programmed in C. Since this program is
  39. going to be running life critical function, it must be demonstrably correct.
  40. This implies that it needs to be verifiable and testable. Since the target
  41. micro processor is inconvenient for accomplishing these goals, we will build
  42. and test the code on the desktop.</p>
  43. <div class="section">
  44. <div class="titlepage"><div><div><h4 class="title">
  45. <a name="idm130205797504"></a>How a Stepper Motor Works</h4></div></div></div>
  46. <div class="figure">
  47. <a name="idm130205796864"></a><p class="title"><b>Figure&#160;1.&#160;Stepper Motor</b></p>
  48. <div class="figure-contents"><div class="mediaobject" align="left"><table border="0" summary="manufactured viewport for HTML img" style="cellpadding: 0; cellspacing: 0;" width="50%"><tr><td align="left"><img src="StepperMotor.gif" align="left" width="216" alt="Stepper Motor"></td></tr></table></div></div>
  49. </div>
  50. <br class="figure-break"><p>A stepper motor controller emits a pulse which causes the motor to
  51. move one step. It seems simple, but in practice it turns out to be quite
  52. intricate to get right as one has to time the pulses individually to
  53. smoothly accelerate the rotation of the motor from a standing start until
  54. it reaches the some maximum velocity. Failure to do this will either limit
  55. the stepper motor to very low speed or result in skipped steps when the
  56. motor is under load. Similarly, a loaded motor must be slowly decelerated
  57. down to a stop.</p>
  58. <div class="figure">
  59. <a name="idm130205792544"></a><p class="title"><b>Figure&#160;2.&#160;Motion Profile</b></p>
  60. <div class="figure-contents"><div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" style="cellpadding: 0; cellspacing: 0;" width="100%"><tr><td><img src="stepper_profile.png" width="100%" alt="Motion Profile"></td></tr></table></div></div>
  61. </div>
  62. <p><br class="figure-break"></p>
  63. <p>This implies the the width of the pulses must decrease as the motor
  64. accelerates. That is the pulse with has to be computed while the motor is
  65. in motion. This is illustrated in the above drawing. A program to
  66. accomplish this might look something like the following:</p>
  67. <div class="literallayout"><p>setup&#160;registers&#160;and&#160;step&#160;to&#160;zero&#160;position<br>
  68. <br>
  69. specify&#160;target&#160;position<br>
  70. set&#160;initial&#160;time&#160;to&#160;interrupt<br>
  71. enable&#160;interrupts<br>
  72. <br>
  73. On&#160;interrupt<br>
  74. &#160;&#160;&#160;&#160;if&#160;at&#160;target&#160;position<br>
  75. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;disable&#160;interrupts&#160;and&#160;return<br>
  76. &#160;&#160;&#160;&#160;calculate&#160;width&#160;of&#160;next&#160;step<br>
  77. &#160;&#160;&#160;&#160;change&#160;current&#160;winding&#160;according&#160;to&#160;motor&#160;direction<br>
  78. &#160;&#160;&#160;&#160;set&#160;delay&#160;time&#160;to&#160;next&#160;interrupt&#160;to&#160;width&#160;of&#160;next&#160;step</p></div>
  79. <p>Already, this is turning it to a much more complex project than it
  80. first seemed. Searching around the net, we find a popular <a href="../../example/stepper-motor.pdf" target="_top">article</a> on the operation of
  81. stepper motors using simple micro controllers. The algorithm is very well
  82. explained and it includes complete <a href="../../example/motor.c" target="_top">code
  83. we can test</a>. The engineers are still debugging the prototype
  84. boards and hope to have them ready before the product actually ships. But
  85. this doesn't have to keep us from working on our code.</p>
  86. </div>
  87. <div class="section">
  88. <div class="titlepage"><div><div><h4 class="title">
  89. <a name="idm130205785344"></a>Updating the Code</h4></div></div></div>
  90. <p>Inspecting this <a href="../../example/motor.c" target="_top">code</a>, we
  91. find that it is written in a dialect of C rather than C itself. At the
  92. time this code was written, conforming versions of the C compiler were not
  93. available for PIC processors. We want to compile this code on the <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/50002053G.pdf" target="_top">Microchip
  94. XC8 compiler</a> which, for the most part, is standards conforming. So
  95. we made the following minimal changes:</p>
  96. <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  97. <li class="listitem"><p>Factor into <a href="../../example/motor1.c" target="_top">motor1.c</a> which contains the
  98. motor driving code and <a href="../../example/motor_test1.c" target="_top">motor_test1.c</a> which tests
  99. that code.</p></li>
  100. <li class="listitem"><p>Include header <code class="computeroutput">&lt;xc.h&gt;</code> which contains
  101. constants for the <a href="http://www.microchip.com/wwwproducts/en/PIC18F2520" target="_top">PIC18F2520</a>
  102. processor</p></li>
  103. <li class="listitem"><p>Include header <code class="computeroutput">&lt;stdint.h&gt;</code> to include
  104. standard Fixed width integer types.</p></li>
  105. <li class="listitem"><p>Include header <code class="computeroutput">&lt;stdbool.h&gt;</code> to include
  106. keywords true and false in a C program.</p></li>
  107. <li class="listitem"><p>The original has some anomalies in the names of types. For
  108. example, int16 is assumed to be unsigned. This is an artifact of the
  109. original C compiler being used. So type names in the code were
  110. altered to standard ones while retaining the intent of the original
  111. code.</p></li>
  112. <li class="listitem"><p>Add in missing <code class="computeroutput">make16</code> function.</p></li>
  113. <li class="listitem"><p>Format code to personal taste.</p></li>
  114. <li class="listitem"><p>Replaced enable_interrupts and disable_interrupts functions
  115. with appropriate PIC commands.</p></li>
  116. </ul></div>
  117. <p>The resulting program can be checked to be identical to the original
  118. but compiles on with the Microchip XC8 compiler. Given a development
  119. board, we could hook it up to a stepper motor, download and boot the code
  120. and verify that the motor rotates 5 revolutions in each direction with
  121. smooth acceleration and deceleration. We don't have such a board yet, but
  122. the engineers have promised a working board real soon now.</p>
  123. </div>
  124. <div class="section">
  125. <div class="titlepage"><div><div><h4 class="title">
  126. <a name="idm130205769072"></a>Refactor for Testing</h4></div></div></div>
  127. <p>In order to develop our test suite and execute the same code on the
  128. desktop and the target system we factor out the shared code as a separate
  129. module which will used in both environments without change. The shared
  130. module <a href="../../example/motor2.c" target="_top"><code class="computeroutput"><a href="../../example/motor1.c" target="_top">motor2.c</a></code></a> contains the
  131. algorithm for handling the interrupts in such a way as to create the
  132. smooth acceleration we require.</p>
  133. <div class="literallayout"><p>&#160;&#160;&#160;&#160;<a href="../../example/motor2.c" target="_top"><code class="computeroutput"><a href="../../example/motor_test2.c" target="_top">motor_test2.c</a></code></a>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<a href="../../example/motor2.c" target="_top"><code class="computeroutput"><a href="../../example/example92.cpp" target="_top">example92.cpp</a></code></a><br>
  134. <br>
  135. &#160;&#160;&#160;&#160;#include&#160;...&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;#include&#160;...<br>
  136. &#160;&#160;&#160;&#160;PIC&#160;typedefs&#160;...&#160;&#160;&#160;&#160;&#160;desktop&#160;types&#160;...<br>
  137. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;\&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;/<br>
  138. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;\&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;/<br>
  139. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;#include&#160;<a href="../../example/motor2.c" target="_top"><code class="computeroutput"><a href="../../example/motor2.c" target="_top">motor2.c</a></code></a><br>
  140. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;/&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;\<br>
  141. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;/&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;\<br>
  142. &#160;&#160;&#160;&#160;PIC&#160;test&#160;code&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;desktop&#160;test&#160;code</p></div>
  143. </div>
  144. <div class="section">
  145. <div class="titlepage"><div><div><h4 class="title">
  146. <a name="idm130205760352"></a>Compiling on the Desktop</h4></div></div></div>
  147. <p>Using the target environment to run tests is often very difficult or
  148. impossible due to limited resources. So software unit testing for embedded
  149. systems is very problematic and often skipped. The C language on our
  150. desktop is the same used by the <a href="http://www.microchip.com/wwwproducts/en/PIC18F2520" target="_top">PIC18F2520</a>.
  151. So now we can also run and debug the code on our desktop machine. Once our
  152. code passes all our tests, we can download the code to the embedded
  153. hardware and run the code natively. Here is a program we use on the
  154. desktop to do that:</p>
  155. <pre class="programlisting"><span class="comment">//////////////////////////////////////////////////////////////////</span>
  156. <span class="comment">// example92.cpp</span>
  157. <span class="comment">//</span>
  158. <span class="comment">// Copyright (c) 2015 Robert Ramey</span>
  159. <span class="comment">//</span>
  160. <span class="comment">// Distributed under the Boost Software License, Version 1.0. (See</span>
  161. <span class="comment">// accompanying file LICENSE_1_0.txt or copy at</span>
  162. <span class="comment">// http://www.boost.org/LICENSE_1_0.txt)</span>
  163. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
  164. <span class="comment">// *************************** </span>
  165. <span class="comment">// 1. include headers to support safe integers</span>
  166. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">cpp</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  167. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">exception</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  168. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">safe_integer</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  169. <span class="comment">// *************************** </span>
  170. <span class="comment">// 2. specify a promotion policy to support proper emulation of </span>
  171. <span class="comment">// PIC types on the desktop</span>
  172. <span class="keyword">using</span> <span class="identifier">pic16_promotion</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">cpp</span><span class="special">&lt;</span>
  173. <span class="number">8</span><span class="special">,</span> <span class="comment">// char 8 bits</span>
  174. <span class="number">16</span><span class="special">,</span> <span class="comment">// short 16 bits</span>
  175. <span class="number">16</span><span class="special">,</span> <span class="comment">// int 16 bits</span>
  176. <span class="number">16</span><span class="special">,</span> <span class="comment">// long 16 bits</span>
  177. <span class="number">32</span> <span class="comment">// long long 32 bits</span>
  178. <span class="special">&gt;</span><span class="special">;</span>
  179. <span class="comment">// 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)</span>
  180. <span class="preprocessor">#define</span> <span class="identifier">C0</span> <span class="special">(</span><span class="number">50000</span> <span class="special">&lt;&lt;</span> <span class="number">8</span><span class="special">)</span>
  181. <span class="preprocessor">#define</span> <span class="identifier">C_MIN</span> <span class="special">(</span><span class="number">2500</span> <span class="special">&lt;&lt;</span> <span class="number">8</span><span class="special">)</span>
  182. <span class="identifier">static_assert</span><span class="special">(</span><span class="identifier">C0</span> <span class="special">&lt;</span> <span class="number">0xffffff</span><span class="special">,</span> <span class="string">"Largest step too long"</span><span class="special">)</span><span class="special">;</span>
  183. <span class="identifier">static_assert</span><span class="special">(</span><span class="identifier">C_MIN</span> <span class="special">&gt;</span> <span class="number">0</span><span class="special">,</span> <span class="string">"Smallest step must be greater than zero"</span><span class="special">)</span><span class="special">;</span>
  184. <span class="identifier">static_assert</span><span class="special">(</span><span class="identifier">C_MIN</span> <span class="special">&lt;</span> <span class="identifier">C0</span><span class="special">,</span> <span class="string">"Smallest step must be smaller than largest step"</span><span class="special">)</span><span class="special">;</span>
  185. <span class="comment">// *************************** </span>
  186. <span class="comment">// 3. define PIC integer type names to be safe integer types of he same size.</span>
  187. <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="comment">// T is char, int, etc data type</span>
  188. <span class="keyword">using</span> <span class="identifier">safe_t</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe</span><span class="special">&lt;</span>
  189. <span class="identifier">T</span><span class="special">,</span>
  190. <span class="identifier">pic16_promotion</span>
  191. <span class="special">&gt;</span><span class="special">;</span>
  192. <span class="comment">// alias original program's integer types to corresponding PIC safe types</span>
  193. <span class="comment">// In conjunction with the promotion policy above, this will permit us to </span>
  194. <span class="comment">// guarantee that the resulting program will be free of arithmetic errors </span>
  195. <span class="comment">// introduced by C expression syntax and type promotion with no runtime penalty</span>
  196. <span class="keyword">typedef</span> <span class="identifier">safe_t</span><span class="special">&lt;</span><span class="identifier">int8_t</span><span class="special">&gt;</span> <span class="identifier">int8</span><span class="special">;</span>
  197. <span class="keyword">typedef</span> <span class="identifier">safe_t</span><span class="special">&lt;</span><span class="identifier">int16_t</span><span class="special">&gt;</span> <span class="identifier">int16</span><span class="special">;</span>
  198. <span class="keyword">typedef</span> <span class="identifier">safe_t</span><span class="special">&lt;</span><span class="identifier">int32_t</span><span class="special">&gt;</span> <span class="identifier">int32</span><span class="special">;</span>
  199. <span class="keyword">typedef</span> <span class="identifier">safe_t</span><span class="special">&lt;</span><span class="identifier">uint8_t</span><span class="special">&gt;</span> <span class="identifier">uint8</span><span class="special">;</span>
  200. <span class="keyword">typedef</span> <span class="identifier">safe_t</span><span class="special">&lt;</span><span class="identifier">uint16_t</span><span class="special">&gt;</span> <span class="identifier">uint16</span><span class="special">;</span>
  201. <span class="keyword">typedef</span> <span class="identifier">safe_t</span><span class="special">&lt;</span><span class="identifier">uint32_t</span><span class="special">&gt;</span> <span class="identifier">uint32</span><span class="special">;</span>
  202. <span class="comment">// *************************** </span>
  203. <span class="comment">// 4. emulate PIC features on the desktop</span>
  204. <span class="comment">// filter out special keyword used only by XC8 compiler</span>
  205. <span class="preprocessor">#define</span> <span class="identifier">__interrupt</span>
  206. <span class="comment">// filter out XC8 enable/disable global interrupts</span>
  207. <span class="preprocessor">#define</span> <span class="identifier">ei</span><span class="special">(</span><span class="special">)</span>
  208. <span class="preprocessor">#define</span> <span class="identifier">di</span><span class="special">(</span><span class="special">)</span>
  209. <span class="comment">// emulate PIC special registers</span>
  210. <span class="identifier">uint8</span> <span class="identifier">RCON</span><span class="special">;</span>
  211. <span class="identifier">uint8</span> <span class="identifier">INTCON</span><span class="special">;</span>
  212. <span class="identifier">uint8</span> <span class="identifier">CCP1IE</span><span class="special">;</span>
  213. <span class="identifier">uint8</span> <span class="identifier">CCP2IE</span><span class="special">;</span>
  214. <span class="identifier">uint8</span> <span class="identifier">PORTC</span><span class="special">;</span>
  215. <span class="identifier">uint8</span> <span class="identifier">TRISC</span><span class="special">;</span>
  216. <span class="identifier">uint8</span> <span class="identifier">T3CON</span><span class="special">;</span>
  217. <span class="identifier">uint8</span> <span class="identifier">T1CON</span><span class="special">;</span>
  218. <span class="identifier">uint8</span> <span class="identifier">CCPR2H</span><span class="special">;</span>
  219. <span class="identifier">uint8</span> <span class="identifier">CCPR2L</span><span class="special">;</span>
  220. <span class="identifier">uint8</span> <span class="identifier">CCPR1H</span><span class="special">;</span>
  221. <span class="identifier">uint8</span> <span class="identifier">CCPR1L</span><span class="special">;</span>
  222. <span class="identifier">uint8</span> <span class="identifier">CCP1CON</span><span class="special">;</span>
  223. <span class="identifier">uint8</span> <span class="identifier">CCP2CON</span><span class="special">;</span>
  224. <span class="identifier">uint8</span> <span class="identifier">TMR1H</span><span class="special">;</span>
  225. <span class="identifier">uint8</span> <span class="identifier">TMR1L</span><span class="special">;</span>
  226. <span class="comment">// create type used to map PIC bit names to</span>
  227. <span class="comment">// correct bit in PIC register</span>
  228. <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">int8_t</span> <span class="identifier">N</span><span class="special">&gt;</span>
  229. <span class="keyword">struct</span> <span class="identifier">bit</span> <span class="special">{</span>
  230. <span class="identifier">T</span> <span class="special">&amp;</span> <span class="identifier">m_word</span><span class="special">;</span>
  231. <span class="keyword">constexpr</span> <span class="keyword">explicit</span> <span class="identifier">bit</span><span class="special">(</span><span class="identifier">T</span> <span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">)</span> <span class="special">:</span>
  232. <span class="identifier">m_word</span><span class="special">(</span><span class="identifier">rhs</span><span class="special">)</span>
  233. <span class="special">{</span><span class="special">}</span>
  234. <span class="keyword">constexpr</span> <span class="identifier">bit</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">b</span><span class="special">)</span><span class="special">{</span>
  235. <span class="keyword">if</span><span class="special">(</span><span class="identifier">b</span> <span class="special">!=</span> <span class="number">0</span><span class="special">)</span>
  236. <span class="identifier">m_word</span> <span class="special">|=</span> <span class="special">(</span><span class="number">1</span> <span class="special">&lt;&lt;</span> <span class="identifier">N</span><span class="special">)</span><span class="special">;</span>
  237. <span class="keyword">else</span>
  238. <span class="identifier">m_word</span> <span class="special">&amp;=</span> <span class="special">~</span><span class="special">(</span><span class="number">1</span> <span class="special">&lt;&lt;</span> <span class="identifier">N</span><span class="special">)</span><span class="special">;</span>
  239. <span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
  240. <span class="special">}</span>
  241. <span class="keyword">constexpr</span> <span class="keyword">operator</span> <span class="keyword">int</span> <span class="special">(</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span>
  242. <span class="keyword">return</span> <span class="identifier">m_word</span> <span class="special">&gt;&gt;</span> <span class="identifier">N</span> <span class="special">&amp;</span> <span class="number">1</span><span class="special">;</span>
  243. <span class="special">}</span>
  244. <span class="special">}</span><span class="special">;</span>
  245. <span class="comment">// define bits for T1CON register</span>
  246. <span class="keyword">struct</span> <span class="special">{</span>
  247. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">7</span><span class="special">&gt;</span> <span class="identifier">RD16</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  248. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">5</span><span class="special">&gt;</span> <span class="identifier">T1CKPS1</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  249. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">4</span><span class="special">&gt;</span> <span class="identifier">T1CKPS0</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  250. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;</span> <span class="identifier">T1OSCEN</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  251. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span> <span class="identifier">T1SYNC</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  252. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">1</span><span class="special">&gt;</span> <span class="identifier">TMR1CS</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  253. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">0</span><span class="special">&gt;</span> <span class="identifier">TMR1ON</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  254. <span class="special">}</span> <span class="identifier">T1CONbits</span><span class="special">;</span>
  255. <span class="comment">// define bits for T1CON register</span>
  256. <span class="keyword">struct</span> <span class="special">{</span>
  257. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">7</span><span class="special">&gt;</span> <span class="identifier">GEI</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  258. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">5</span><span class="special">&gt;</span> <span class="identifier">PEIE</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  259. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">4</span><span class="special">&gt;</span> <span class="identifier">TMR0IE</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  260. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;</span> <span class="identifier">RBIE</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  261. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span> <span class="identifier">TMR0IF</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  262. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">1</span><span class="special">&gt;</span> <span class="identifier">INT0IF</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  263. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">uint8</span><span class="special">,</span> <span class="number">0</span><span class="special">&gt;</span> <span class="identifier">RBIF</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  264. <span class="special">}</span> <span class="identifier">INTCONbits</span><span class="special">;</span>
  265. <span class="comment">// ***************************</span>
  266. <span class="comment">// 5. include the environment independent code we want to test</span>
  267. <span class="preprocessor">#include</span> <span class="string">"motor2.c"</span>
  268. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">chrono</span><span class="special">&gt;</span>
  269. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">thread</span><span class="special">&gt;</span>
  270. <span class="comment">// round 24.8 format to microseconds</span>
  271. <span class="identifier">int32</span> <span class="identifier">to_microseconds</span><span class="special">(</span><span class="identifier">uint32</span> <span class="identifier">t</span><span class="special">)</span><span class="special">{</span>
  272. <span class="keyword">return</span> <span class="special">(</span><span class="identifier">t</span> <span class="special">+</span> <span class="number">128</span><span class="special">)</span> <span class="special">/</span> <span class="number">256</span><span class="special">;</span>
  273. <span class="special">}</span>
  274. <span class="keyword">using</span> <span class="identifier">result_t</span> <span class="special">=</span> <span class="identifier">uint8_t</span><span class="special">;</span>
  275. <span class="keyword">const</span> <span class="identifier">result_t</span> <span class="identifier">success</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span>
  276. <span class="keyword">const</span> <span class="identifier">result_t</span> <span class="identifier">fail</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
  277. <span class="comment">// move motor to the indicated target position in steps</span>
  278. <span class="identifier">result_t</span> <span class="identifier">test</span><span class="special">(</span><span class="identifier">int32</span> <span class="identifier">m</span><span class="special">)</span><span class="special">{</span>
  279. <span class="keyword">try</span> <span class="special">{</span>
  280. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"move motor to "</span> <span class="special">&lt;&lt;</span> <span class="identifier">m</span> <span class="special">&lt;&lt;</span> <span class="char">'\n'</span><span class="special">;</span>
  281. <span class="identifier">motor_run</span><span class="special">(</span><span class="identifier">m</span><span class="special">)</span><span class="special">;</span>
  282. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span>
  283. <span class="special">&lt;&lt;</span> <span class="string">"step #"</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  284. <span class="special">&lt;&lt;</span> <span class="string">"delay(us)(24.8)"</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  285. <span class="special">&lt;&lt;</span> <span class="string">"delay(us)"</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  286. <span class="special">&lt;&lt;</span> <span class="string">"CCPR"</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  287. <span class="special">&lt;&lt;</span> <span class="string">"motor position"</span> <span class="special">&lt;&lt;</span> <span class="char">'\n'</span><span class="special">;</span>
  288. <span class="keyword">do</span><span class="special">{</span>
  289. <span class="identifier">std</span><span class="special">::</span><span class="identifier">this_thread</span><span class="special">::</span><span class="identifier">sleep_for</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">microseconds</span><span class="special">(</span><span class="identifier">to_microseconds</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span><span class="special">)</span><span class="special">)</span><span class="special">;</span>
  290. <span class="identifier">uint32</span> <span class="identifier">last_c</span> <span class="special">=</span> <span class="identifier">c</span><span class="special">;</span>
  291. <span class="identifier">uint32</span> <span class="identifier">last_ccpr</span> <span class="special">=</span> <span class="identifier">ccpr</span><span class="special">;</span>
  292. <span class="identifier">isr_motor_step</span><span class="special">(</span><span class="special">)</span><span class="special">;</span>
  293. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span>
  294. <span class="special">&lt;&lt;</span> <span class="identifier">step_no</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  295. <span class="special">&lt;&lt;</span> <span class="identifier">last_c</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  296. <span class="special">&lt;&lt;</span> <span class="identifier">to_microseconds</span><span class="special">(</span><span class="identifier">last_c</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  297. <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">hex</span> <span class="special">&lt;&lt;</span> <span class="identifier">last_ccpr</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">dec</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  298. <span class="special">&lt;&lt;</span> <span class="identifier">motor_pos</span> <span class="special">&lt;&lt;</span> <span class="char">'\n'</span><span class="special">;</span>
  299. <span class="special">}</span><span class="keyword">while</span><span class="special">(</span><span class="identifier">run_flg</span><span class="special">)</span><span class="special">;</span>
  300. <span class="special">}</span>
  301. <span class="keyword">catch</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception</span> <span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span><span class="special">{</span>
  302. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">(</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="char">'\n'</span><span class="special">;</span>
  303. <span class="keyword">return</span> <span class="identifier">fail</span><span class="special">;</span>
  304. <span class="special">}</span>
  305. <span class="keyword">return</span> <span class="identifier">success</span><span class="special">;</span>
  306. <span class="special">}</span>
  307. <span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="special">)</span><span class="special">{</span>
  308. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"start test\n"</span><span class="special">;</span>
  309. <span class="identifier">result_t</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">success</span><span class="special">;</span>
  310. <span class="keyword">try</span><span class="special">{</span>
  311. <span class="identifier">initialize</span><span class="special">(</span><span class="special">)</span><span class="special">;</span>
  312. <span class="comment">// move motor to position 1000</span>
  313. <span class="identifier">result</span> <span class="special">&amp;=</span> <span class="identifier">test</span><span class="special">(</span><span class="number">1000</span><span class="special">)</span><span class="special">;</span>
  314. <span class="comment">// move motor to position 200</span>
  315. <span class="identifier">result</span> <span class="special">&amp;=</span> <span class="identifier">test</span><span class="special">(</span><span class="number">200</span><span class="special">)</span><span class="special">;</span>
  316. <span class="comment">// move motor to position 200 again! Should result in no movement.</span>
  317. <span class="identifier">result</span> <span class="special">&amp;=</span> <span class="identifier">test</span><span class="special">(</span><span class="number">200</span><span class="special">)</span><span class="special">;</span>
  318. <span class="comment">// move back to position 0</span>
  319. <span class="identifier">result</span> <span class="special">&amp;=</span> <span class="identifier">test</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span>
  320. <span class="comment">// ***************************</span>
  321. <span class="comment">// 6. error detected here! data types can't handle enough</span>
  322. <span class="comment">// steps to move the carriage from end to end! Suppress this</span>
  323. <span class="comment">// test for now.</span>
  324. <span class="comment">// move motor to position 50000.</span>
  325. <span class="comment">// result &amp;= test(50000);</span>
  326. <span class="comment">// move motor back to position 0.</span>
  327. <span class="identifier">result</span> <span class="special">&amp;=</span> <span class="identifier">test</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span>
  328. <span class="special">}</span>
  329. <span class="keyword">catch</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception</span> <span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span><span class="special">{</span>
  330. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">(</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="char">'\n'</span><span class="special">;</span>
  331. <span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
  332. <span class="special">}</span>
  333. <span class="keyword">catch</span><span class="special">(</span><span class="special">...</span><span class="special">)</span><span class="special">{</span>
  334. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"test interrupted\n"</span><span class="special">;</span>
  335. <span class="keyword">return</span> <span class="identifier">EXIT_FAILURE</span><span class="special">;</span>
  336. <span class="special">}</span>
  337. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"end test\n"</span><span class="special">;</span>
  338. <span class="keyword">return</span> <span class="identifier">result</span> <span class="special">==</span> <span class="identifier">success</span> <span class="special">?</span> <span class="identifier">EXIT_SUCCESS</span> <span class="special">:</span> <span class="identifier">EXIT_FAILURE</span><span class="special">;</span>
  339. <span class="special">}</span>
  340. </pre>
  341. <p>Here are the essential features of the desktop version of the test
  342. program.</p>
  343. <div class="orderedlist"><ol class="orderedlist" type="1">
  344. <li class="listitem"><p>Include headers required to support safe integers.</p></li>
  345. <li class="listitem">
  346. <p>Specify a <a class="link" href="promotion_policy.html" title="PromotionPolicy&lt;PP&gt;">promotion policy</a> to
  347. support proper emulation of PIC types on the desktop.</p>
  348. <p>The C language standard doesn't specify sizes for primitive
  349. data types like <code class="computeroutput">int</code>. They can and do differ between
  350. environments. Hence, the characterization of C/C++ as "portable"
  351. languages is not strictly true. Here we choose aliases for data
  352. types so that they can be defined to be the same in both
  353. environments. But this is not enough to emulate the <a href="http://www.microchip.com/wwwproducts/en/PIC18F2520" target="_top">PIC18F2520</a>
  354. on the desktop. The problem is that compilers implicitly convert
  355. arguments of C expressions to some common type before performing
  356. arithmetic operations. Often, this common type is the native
  357. <code class="computeroutput">int</code> and the size of this native type is different in
  358. the desktop and embedded environment. Thus, many arithmetic results
  359. would be different in the two environments.</p>
  360. <p>But now we can specify our own implicit promotion rules for
  361. test programs on the development platform that are identical to
  362. those on the target environment! So unit testing executed in the
  363. development environment can now provide results relevant to the
  364. target environment.</p>
  365. </li>
  366. <li class="listitem">
  367. <p>Define PIC integer type aliases to be safe integer types of he
  368. same size.</p>
  369. <p>Code tested in the development environment will use safe
  370. numerics to detect errors. We need these aliases to permit the code
  371. in <a href="../../example/motor2.c" target="_top">motor2.c</a> to be tested
  372. in the desktop environment. The same code run in the target system
  373. without change.</p>
  374. </li>
  375. <li class="listitem">
  376. <p>Emulate PIC features on the desktop.</p>
  377. <p>The PIC processor, in common with most micro controllers these
  378. days, includes a myriad of special purpose peripherals to handle
  379. things like interrupts, USB, timers, SPI bus, I^2C bus, etc.. These
  380. peripherals are configured using special 8 bit words in reserved
  381. memory locations. Configuration consists of setting particular bits
  382. in these words. To facilitate configuration operations, the XC8
  383. compiler includes a special syntax for setting and accessing bits in
  384. these locations. One of our goals is to permit the testing of the
  385. identical code with our desktop C++ compiler as will run on the
  386. micro controller. To realize this goal, we create some C++ code
  387. which implements the XC8 C syntax for setting bits in particular
  388. memory locations.</p>
  389. </li>
  390. <li class="listitem"><p>include <a href="../../example/motor1.c" target="_top">motor1.c</a></p></li>
  391. <li class="listitem"><p>Add test to verify that the motor will be able to keep track
  392. of a position from 0 to 50000 steps. This will be needed to maintain
  393. the position of out linear stage across a range from 0 to 500
  394. mm.</p></li>
  395. </ol></div>
  396. <p>Our first attempt to run this program fails by throwing an exception
  397. from <a href="../../example/motor1.c" target="_top">motor1.c</a> indicating that
  398. the code attempts to left shift a negative number at the
  399. statements:</p>
  400. <pre class="programlisting"><span class="identifier">denom</span> <span class="special">=</span> <span class="special">(</span><span class="special">(</span><span class="identifier">step_no</span> <span class="special">-</span> <span class="identifier">move</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="number">2</span><span class="special">)</span> <span class="special">+</span> <span class="number">1</span><span class="special">;</span></pre>
  401. <p>According to the C/C++ standards this is implementation defined
  402. behavior. But in practice with all modern platforms (as far as I know),
  403. this will be equivalent to a multiplication by 4. Clearly the intent of
  404. the original author is to "micro optimize" the operation by substituting a
  405. cheap left shift for a potentially expensive integer multiplication. But
  406. on all modern compilers, this substitution will be performed automatically
  407. by the compiler's optimizer. So we have two alternatives here:</p>
  408. <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  409. <li class="listitem">
  410. <p>Just ignore the issue.</p>
  411. <p>This will work when the code is run on the PIC. But, in order to
  412. permit testing on the desktop, we need to inhibit the error detection
  413. in that environment. With safe numerics, error handling is determined
  414. by specifying an <a class="link" href="exception_policy.html" title="ExceptionPolicy&lt;EP&gt;">exception policy</a>. In
  415. this example, we've used the default exception policy which traps
  416. implementation defined behavior. To ignore this kind of behavior we
  417. could define our own custom <a class="link" href="exception_policy.html" title="ExceptionPolicy&lt;EP&gt;">exception
  418. policy</a>.</p>
  419. </li>
  420. <li class="listitem"><p>change the <code class="computeroutput">&lt;&lt; 2</code> to <code class="computeroutput">* 4</code>. This
  421. will produce the intended result in an unambiguous, portable way. For
  422. all known compilers, this change should not affect runtime performance
  423. in any way. It will result in unambiguously portable code.</p></li>
  424. <li class="listitem"><p>Alter the code so that the expression in question is never
  425. negative. Depending on sizes of the operands and the size of the
  426. native integer, this expression might return convert the operands to
  427. int or result in an invalid result.</p></li>
  428. </ul></div>
  429. <p>Of these alternatives, the third seems the more definitive fix so
  430. we'll choose that one. We also decide to make a couple of minor changes to
  431. simplify the code and make mapping of the algorithm in the article to the
  432. code more transparent. With these changes, our test program runs to the
  433. end with no errors or exceptions. In addition, I made a minor change which
  434. simplifies the handling of floating point values in format of 24.8. This
  435. results in <a href="../../example/motor2.c" target="_top">motor2.c</a> which
  436. makes the above changes. It should be easy to see that these two versions
  437. are otherwise identical.</p>
  438. <p>Finally our range test fails. In order to handle the full range we
  439. need, we'll have to change some data types used for holding step count and
  440. position. We won't do that here as it would make our example too complex.
  441. We'll deal with this on the next version.</p>
  442. </div>
  443. <div class="section">
  444. <div class="titlepage"><div><div><h4 class="title">
  445. <a name="idm130205230160"></a>Trapping Errors at Compile Time</h4></div></div></div>
  446. <p>We can test the same code we're going to load into our target system
  447. on the desktop. We could build and execute a complete unit test suite. We
  448. could capture the output and graph it. We have the ability to make are
  449. code much more likely to be bug free. But:</p>
  450. <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  451. <li class="listitem"><p>This system detects errors and exceptions on the test machine -
  452. but it fails to address and detect such problems on the target system.
  453. Since the target system is compiles only C code, we can't use the
  454. exception/error facilities of this library at runtime.</p></li>
  455. <li class="listitem"><p><a href="https://en.wikiquote.org/wiki/Edsger_W._Dijkstra" target="_top">Testing shows
  456. the presence, not the absence of bugs</a>. Can we not prove that
  457. all integer arithmetic is correct?</p></li>
  458. <li class="listitem"><p>For at least some operations on safe integers there is runtime
  459. cost in checking for errors. In this example, this is not really a
  460. problem as the safe integer code is not included when the code is run
  461. on the target - it's only a C compiler after all. But more generally,
  462. using safe integers might incur an undesired runtime cost.</p></li>
  463. </ul></div>
  464. <p>Can we catch all potential problems at compiler time and therefore
  465. eliminate all runtime cost?</p>
  466. <p>Our first attempt consists of simply changing default exception
  467. policy from the default runtime checking to the compile time trapping one.
  468. Then we redefine the aliases for the types used by the PIC to use this
  469. exception policy.</p>
  470. <pre class="programlisting"><span class="comment">// generate compile time errors if operation could fail </span>
  471. <span class="keyword">using</span> <span class="identifier">trap_policy</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">numeric</span><span class="special">::</span><span class="identifier">loose_trap_policy</span><span class="special">;</span>
  472. <span class="special">...</span>
  473. <span class="keyword">typedef</span> <span class="identifier">safe_t</span><span class="special">&lt;</span><span class="identifier">int8_t</span><span class="special">,</span> <span class="identifier">trap_policy</span><span class="special">&gt;</span> <span class="identifier">int8</span><span class="special">;</span>
  474. <span class="special">...</span>
  475. </pre>
  476. <p>When we compile now, any expressions which could possibly fail will
  477. be flagged as syntax errors. This occurs 11 times when compiling the
  478. <a href="../../example/motor2.c" target="_top">motor2.c</a> program. This is
  479. fewer than one might expect. To understand why, consider the following
  480. example:</p>
  481. <pre class="programlisting"><span class="identifier">safe</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">int8_t</span><span class="special">&gt;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">;</span>
  482. <span class="special">...</span>
  483. <span class="identifier">safe</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">int16_t</span><span class="special">&gt;</span> <span class="identifier">z</span> <span class="special">=</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">;</span>
  484. </pre>
  485. <p>C promotion rules and arithmetic are such that the z will
  486. always contain an arithmetically correct result regardless of what values
  487. are assigned to x and y. Hence there is no need for any kind of checking
  488. of the arithmetic or result. The Safe Numerics library uses compile time
  489. range arithmetic, C++ template multiprogramming and other techniques to
  490. restrict invocation of checking code to only those operations which could
  491. possible fail. So the above code incurs no runtime overhead.</p>
  492. <p>Now we have 11 cases to consider. Our goal is to modify the program
  493. so that this number of cases is reduced - hopefully to zero. Initially I
  494. wanted to just make a few tweaks in the versions of
  495. <code class="computeroutput">example92.c</code>, <code class="computeroutput">motor2.c</code> and
  496. <code class="computeroutput">motor_test2.c</code> above without actually having to understand the
  497. code. It turns out that one needs to carefully consider what various types
  498. and variables are used for. This can be a good thing or a bad thing
  499. depending on one's circumstances, goals and personality. The programs
  500. above evolved into <a href="../../example/example93.c" target="_top"><code class="computeroutput">example93.c</code></a>,
  501. <code class="computeroutput"><a href="../../example/motor3.c" target="_top">motor3.c</a></code> and
  502. <a href="../../example/motor_test3.c" target="_top"><code class="computeroutput">motor_test3.c</code></a>.
  503. First we'll look at <code class="computeroutput">example93.c</code>:</p>
  504. <pre class="programlisting"><span class="comment">//////////////////////////////////////////////////////////////////</span>
  505. <span class="comment">// example93.cpp</span>
  506. <span class="comment">//</span>
  507. <span class="comment">// Copyright (c) 2015 Robert Ramey</span>
  508. <span class="comment">//</span>
  509. <span class="comment">// Distributed under the Boost Software License, Version 1.0. (See</span>
  510. <span class="comment">// accompanying file LICENSE_1_0.txt or copy at</span>
  511. <span class="comment">// http://www.boost.org/LICENSE_1_0.txt)</span>
  512. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
  513. <span class="comment">// include headers to support safe integers</span>
  514. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">cpp</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  515. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">exception</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  516. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">safe_integer</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  517. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">safe_integer_range</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  518. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">safe_integer_literal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  519. <span class="comment">// use same type promotion as used by the pic compiler</span>
  520. <span class="comment">// target compiler XC8 supports:</span>
  521. <span class="keyword">using</span> <span class="identifier">pic16_promotion</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">cpp</span><span class="special">&lt;</span>
  522. <span class="number">8</span><span class="special">,</span> <span class="comment">// char 8 bits</span>
  523. <span class="number">16</span><span class="special">,</span> <span class="comment">// short 16 bits</span>
  524. <span class="number">16</span><span class="special">,</span> <span class="comment">// int 16 bits</span>
  525. <span class="number">16</span><span class="special">,</span> <span class="comment">// long 16 bits</span>
  526. <span class="number">32</span> <span class="comment">// long long 32 bits</span>
  527. <span class="special">&gt;</span><span class="special">;</span>
  528. <span class="comment">// ***************************</span>
  529. <span class="comment">// 1. Specify exception policies so we will generate a</span>
  530. <span class="comment">// compile time error whenever an operation MIGHT fail.</span>
  531. <span class="comment">// ***************************</span>
  532. <span class="comment">// generate runtime errors if operation could fail</span>
  533. <span class="keyword">using</span> <span class="identifier">exception_policy</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">default_exception_policy</span><span class="special">;</span>
  534. <span class="comment">// generate compile time errors if operation could fail</span>
  535. <span class="keyword">using</span> <span class="identifier">trap_policy</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">loose_trap_policy</span><span class="special">;</span>
  536. <span class="comment">// ***************************</span>
  537. <span class="comment">// 2. Create a macro named literal an integral value</span>
  538. <span class="comment">// that can be evaluated at compile time.</span>
  539. <span class="preprocessor">#define</span> <span class="identifier">literal</span><span class="special">(</span><span class="identifier">n</span><span class="special">)</span> <span class="identifier">make_safe_literal</span><span class="special">(</span><span class="identifier">n</span><span class="special">,</span> <span class="identifier">pic16_promotion</span><span class="special">,</span> <span class="keyword">void</span><span class="special">)</span>
  540. <span class="comment">// For min speed of 2 mm / sec (24.8 format)</span>
  541. <span class="comment">// sec / step = sec / 2 mm * 2 mm / rotation * rotation / 200 steps</span>
  542. <span class="preprocessor">#define</span> <span class="identifier">C0</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">5000</span> <span class="special">&lt;&lt;</span> <span class="number">8</span><span class="special">)</span>
  543. <span class="comment">// For max speed of 400 mm / sec</span>
  544. <span class="comment">// sec / step = sec / 400 mm * 2 mm / rotation * rotation / 200 steps</span>
  545. <span class="preprocessor">#define</span> <span class="identifier">C_MIN</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">25</span> <span class="special">&lt;&lt;</span> <span class="number">8</span><span class="special">)</span>
  546. <span class="identifier">static_assert</span><span class="special">(</span>
  547. <span class="identifier">C0</span> <span class="special">&lt;</span> <span class="identifier">make_safe_literal</span><span class="special">(</span><span class="number">0xffffff</span><span class="special">,</span> <span class="identifier">pic16_promotion</span><span class="special">,</span><span class="identifier">trap_policy</span><span class="special">)</span><span class="special">,</span>
  548. <span class="string">"Largest step too long"</span>
  549. <span class="special">)</span><span class="special">;</span>
  550. <span class="identifier">static_assert</span><span class="special">(</span>
  551. <span class="identifier">C_MIN</span> <span class="special">&gt;</span> <span class="identifier">make_safe_literal</span><span class="special">(</span><span class="number">0</span><span class="special">,</span> <span class="identifier">pic16_promotion</span><span class="special">,</span><span class="identifier">trap_policy</span><span class="special">)</span><span class="special">,</span>
  552. <span class="string">"Smallest step must be greater than zero"</span>
  553. <span class="special">)</span><span class="special">;</span>
  554. <span class="comment">// ***************************</span>
  555. <span class="comment">// 3. Create special ranged types for the motor program</span>
  556. <span class="comment">// These wiil guarantee that values are in the expected</span>
  557. <span class="comment">// ranges and permit compile time determination of when</span>
  558. <span class="comment">// exceptional conditions might occur.</span>
  559. <span class="keyword">using</span> <span class="identifier">pic_register_t</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe</span><span class="special">&lt;</span>
  560. <span class="identifier">uint8_t</span><span class="special">,</span>
  561. <span class="identifier">pic16_promotion</span><span class="special">,</span>
  562. <span class="identifier">trap_policy</span> <span class="comment">// use for compiling and running tests</span>
  563. <span class="special">&gt;</span><span class="special">;</span>
  564. <span class="comment">// note: the maximum value of step_t would be:</span>
  565. <span class="comment">// 50000 = 500 mm / 2 mm/rotation * 200 steps/rotation.</span>
  566. <span class="comment">// But in one expression the value of number of steps * 4 is</span>
  567. <span class="comment">// used. To prevent introduction of error, permit this</span>
  568. <span class="comment">// type to hold the larger value.</span>
  569. <span class="keyword">using</span> <span class="identifier">step_t</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe_unsigned_range</span><span class="special">&lt;</span>
  570. <span class="number">0</span><span class="special">,</span>
  571. <span class="number">200000</span><span class="special">,</span>
  572. <span class="identifier">pic16_promotion</span><span class="special">,</span>
  573. <span class="identifier">exception_policy</span>
  574. <span class="special">&gt;</span><span class="special">;</span>
  575. <span class="comment">// position</span>
  576. <span class="keyword">using</span> <span class="identifier">position_t</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe_unsigned_range</span><span class="special">&lt;</span>
  577. <span class="number">0</span><span class="special">,</span>
  578. <span class="number">50000</span><span class="special">,</span> <span class="comment">// 500 mm / 2 mm/rotation * 200 steps/rotation</span>
  579. <span class="identifier">pic16_promotion</span><span class="special">,</span>
  580. <span class="identifier">exception_policy</span>
  581. <span class="special">&gt;</span><span class="special">;</span>
  582. <span class="comment">// next end of step timer value in format 24.8</span>
  583. <span class="comment">// where the .8 is the number of bits in the fractional part.</span>
  584. <span class="keyword">using</span> <span class="identifier">ccpr_t</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe</span><span class="special">&lt;</span>
  585. <span class="identifier">uint32_t</span><span class="special">,</span>
  586. <span class="identifier">pic16_promotion</span><span class="special">,</span>
  587. <span class="identifier">exception_policy</span>
  588. <span class="special">&gt;</span><span class="special">;</span>
  589. <span class="comment">// pulse length in format 24.8</span>
  590. <span class="comment">// note: this value is constrainted to be a positive value. But</span>
  591. <span class="comment">// we still need to make it a signed type. We get an arithmetic</span>
  592. <span class="comment">// error when moving to a negative step number.</span>
  593. <span class="keyword">using</span> <span class="identifier">c_t</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe_unsigned_range</span><span class="special">&lt;</span>
  594. <span class="identifier">C_MIN</span><span class="special">,</span>
  595. <span class="identifier">C0</span><span class="special">,</span>
  596. <span class="identifier">pic16_promotion</span><span class="special">,</span>
  597. <span class="identifier">exception_policy</span>
  598. <span class="special">&gt;</span><span class="special">;</span>
  599. <span class="comment">// index into phase table</span>
  600. <span class="comment">// note: The legal values are 0-3. So why must this be a signed</span>
  601. <span class="comment">// type? Turns out that expressions like phase_ix + d</span>
  602. <span class="comment">// will convert both operands to unsigned. This in turn will</span>
  603. <span class="comment">// create an exception. So leave it signed even though the</span>
  604. <span class="comment">// value is greater than zero.</span>
  605. <span class="keyword">using</span> <span class="identifier">phase_ix_t</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe_signed_range</span><span class="special">&lt;</span>
  606. <span class="number">0</span><span class="special">,</span>
  607. <span class="number">3</span><span class="special">,</span>
  608. <span class="identifier">pic16_promotion</span><span class="special">,</span>
  609. <span class="identifier">trap_policy</span>
  610. <span class="special">&gt;</span><span class="special">;</span>
  611. <span class="comment">// settings for control value output</span>
  612. <span class="keyword">using</span> <span class="identifier">phase_t</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe</span><span class="special">&lt;</span>
  613. <span class="identifier">uint16_t</span><span class="special">,</span>
  614. <span class="identifier">pic16_promotion</span><span class="special">,</span>
  615. <span class="identifier">trap_policy</span>
  616. <span class="special">&gt;</span><span class="special">;</span>
  617. <span class="comment">// direction of rotation</span>
  618. <span class="keyword">using</span> <span class="identifier">direction_t</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe_signed_range</span><span class="special">&lt;</span>
  619. <span class="special">-</span><span class="number">1</span><span class="special">,</span>
  620. <span class="special">+</span><span class="number">1</span><span class="special">,</span>
  621. <span class="identifier">pic16_promotion</span><span class="special">,</span>
  622. <span class="identifier">trap_policy</span>
  623. <span class="special">&gt;</span><span class="special">;</span>
  624. <span class="comment">// some number of microseconds</span>
  625. <span class="keyword">using</span> <span class="identifier">microseconds</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe</span><span class="special">&lt;</span>
  626. <span class="identifier">uint32_t</span><span class="special">,</span>
  627. <span class="identifier">pic16_promotion</span><span class="special">,</span>
  628. <span class="identifier">trap_policy</span>
  629. <span class="special">&gt;</span><span class="special">;</span>
  630. <span class="comment">// *************************** </span>
  631. <span class="comment">// emulate PIC features on the desktop</span>
  632. <span class="comment">// filter out special keyword used only by XC8 compiler</span>
  633. <span class="preprocessor">#define</span> <span class="identifier">__interrupt</span>
  634. <span class="comment">// filter out XC8 enable/disable global interrupts</span>
  635. <span class="preprocessor">#define</span> <span class="identifier">ei</span><span class="special">(</span><span class="special">)</span>
  636. <span class="preprocessor">#define</span> <span class="identifier">di</span><span class="special">(</span><span class="special">)</span>
  637. <span class="comment">// emulate PIC special registers</span>
  638. <span class="identifier">pic_register_t</span> <span class="identifier">RCON</span><span class="special">;</span>
  639. <span class="identifier">pic_register_t</span> <span class="identifier">INTCON</span><span class="special">;</span>
  640. <span class="identifier">pic_register_t</span> <span class="identifier">CCP1IE</span><span class="special">;</span>
  641. <span class="identifier">pic_register_t</span> <span class="identifier">CCP2IE</span><span class="special">;</span>
  642. <span class="identifier">pic_register_t</span> <span class="identifier">PORTC</span><span class="special">;</span>
  643. <span class="identifier">pic_register_t</span> <span class="identifier">TRISC</span><span class="special">;</span>
  644. <span class="identifier">pic_register_t</span> <span class="identifier">T3CON</span><span class="special">;</span>
  645. <span class="identifier">pic_register_t</span> <span class="identifier">T1CON</span><span class="special">;</span>
  646. <span class="identifier">pic_register_t</span> <span class="identifier">CCPR2H</span><span class="special">;</span>
  647. <span class="identifier">pic_register_t</span> <span class="identifier">CCPR2L</span><span class="special">;</span>
  648. <span class="identifier">pic_register_t</span> <span class="identifier">CCPR1H</span><span class="special">;</span>
  649. <span class="identifier">pic_register_t</span> <span class="identifier">CCPR1L</span><span class="special">;</span>
  650. <span class="identifier">pic_register_t</span> <span class="identifier">CCP1CON</span><span class="special">;</span>
  651. <span class="identifier">pic_register_t</span> <span class="identifier">CCP2CON</span><span class="special">;</span>
  652. <span class="identifier">pic_register_t</span> <span class="identifier">TMR1H</span><span class="special">;</span>
  653. <span class="identifier">pic_register_t</span> <span class="identifier">TMR1L</span><span class="special">;</span>
  654. <span class="comment">// ***************************</span>
  655. <span class="comment">// special checked type for bits - values restricted to 0 or 1</span>
  656. <span class="keyword">using</span> <span class="identifier">safe_bit_t</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">::</span><span class="identifier">safe_unsigned_range</span><span class="special">&lt;</span>
  657. <span class="number">0</span><span class="special">,</span>
  658. <span class="number">1</span><span class="special">,</span>
  659. <span class="identifier">pic16_promotion</span><span class="special">,</span>
  660. <span class="identifier">trap_policy</span>
  661. <span class="special">&gt;</span><span class="special">;</span>
  662. <span class="comment">// create type used to map PIC bit names to</span>
  663. <span class="comment">// correct bit in PIC register</span>
  664. <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">int8_t</span> <span class="identifier">N</span><span class="special">&gt;</span>
  665. <span class="keyword">struct</span> <span class="identifier">bit</span> <span class="special">{</span>
  666. <span class="identifier">T</span> <span class="special">&amp;</span> <span class="identifier">m_word</span><span class="special">;</span>
  667. <span class="keyword">constexpr</span> <span class="keyword">explicit</span> <span class="identifier">bit</span><span class="special">(</span><span class="identifier">T</span> <span class="special">&amp;</span> <span class="identifier">rhs</span><span class="special">)</span> <span class="special">:</span>
  668. <span class="identifier">m_word</span><span class="special">(</span><span class="identifier">rhs</span><span class="special">)</span>
  669. <span class="special">{</span><span class="special">}</span>
  670. <span class="comment">// special functions for assignment of literal</span>
  671. <span class="keyword">constexpr</span> <span class="identifier">bit</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=</span><span class="special">(</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">literal</span><span class="special">(</span><span class="number">1</span><span class="special">)</span><span class="special">)</span><span class="special">)</span><span class="special">{</span>
  672. <span class="identifier">m_word</span> <span class="special">|=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">1</span> <span class="special">&lt;&lt;</span> <span class="identifier">N</span><span class="special">)</span><span class="special">;</span>
  673. <span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
  674. <span class="special">}</span>
  675. <span class="keyword">constexpr</span> <span class="identifier">bit</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=</span><span class="special">(</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">)</span><span class="special">)</span><span class="special">{</span>
  676. <span class="identifier">m_word</span> <span class="special">&amp;=</span> <span class="special">~</span><span class="identifier">literal</span><span class="special">(</span><span class="number">1</span> <span class="special">&lt;&lt;</span> <span class="identifier">N</span><span class="special">)</span><span class="special">;</span>
  677. <span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span>
  678. <span class="special">}</span>
  679. <span class="comment">// operator to convert to 0 or 1</span>
  680. <span class="keyword">constexpr</span> <span class="keyword">operator</span> <span class="identifier">safe_bit_t</span> <span class="special">(</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span>
  681. <span class="keyword">return</span> <span class="identifier">m_word</span> <span class="special">&gt;&gt;</span> <span class="identifier">literal</span><span class="special">(</span><span class="identifier">N</span><span class="special">)</span> <span class="special">&amp;</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">1</span><span class="special">)</span><span class="special">;</span>
  682. <span class="special">}</span>
  683. <span class="special">}</span><span class="special">;</span>
  684. <span class="comment">// define bits for T1CON register</span>
  685. <span class="keyword">struct</span> <span class="special">{</span>
  686. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">7</span><span class="special">&gt;</span> <span class="identifier">RD16</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  687. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">5</span><span class="special">&gt;</span> <span class="identifier">T1CKPS1</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  688. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">4</span><span class="special">&gt;</span> <span class="identifier">T1CKPS0</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  689. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;</span> <span class="identifier">T1OSCEN</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  690. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span> <span class="identifier">T1SYNC</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  691. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">1</span><span class="special">&gt;</span> <span class="identifier">TMR1CS</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  692. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">0</span><span class="special">&gt;</span> <span class="identifier">TMR1ON</span><span class="special">{</span><span class="identifier">T1CON</span><span class="special">}</span><span class="special">;</span>
  693. <span class="special">}</span> <span class="identifier">T1CONbits</span><span class="special">;</span>
  694. <span class="comment">// define bits for T1CON register</span>
  695. <span class="keyword">struct</span> <span class="special">{</span>
  696. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">7</span><span class="special">&gt;</span> <span class="identifier">GEI</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  697. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">5</span><span class="special">&gt;</span> <span class="identifier">PEIE</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  698. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">4</span><span class="special">&gt;</span> <span class="identifier">TMR0IE</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  699. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">3</span><span class="special">&gt;</span> <span class="identifier">RBIE</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  700. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span> <span class="identifier">TMR0IF</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  701. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">1</span><span class="special">&gt;</span> <span class="identifier">INT0IF</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  702. <span class="identifier">bit</span><span class="special">&lt;</span><span class="identifier">pic_register_t</span><span class="special">,</span> <span class="number">0</span><span class="special">&gt;</span> <span class="identifier">RBIF</span><span class="special">{</span><span class="identifier">INTCON</span><span class="special">}</span><span class="special">;</span>
  703. <span class="special">}</span> <span class="identifier">INTCONbits</span><span class="special">;</span>
  704. <span class="preprocessor">#include</span> <span class="string">"motor3.c"</span>
  705. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">chrono</span><span class="special">&gt;</span>
  706. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">thread</span><span class="special">&gt;</span>
  707. <span class="comment">// round 24.8 format to microseconds</span>
  708. <span class="identifier">microseconds</span> <span class="identifier">to_microseconds</span><span class="special">(</span><span class="identifier">ccpr_t</span> <span class="identifier">t</span><span class="special">)</span><span class="special">{</span>
  709. <span class="keyword">return</span> <span class="special">(</span><span class="identifier">t</span> <span class="special">+</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">128</span><span class="special">)</span><span class="special">)</span> <span class="special">/</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">256</span><span class="special">)</span><span class="special">;</span>
  710. <span class="special">}</span>
  711. <span class="keyword">using</span> <span class="identifier">result_t</span> <span class="special">=</span> <span class="identifier">uint8_t</span><span class="special">;</span>
  712. <span class="keyword">const</span> <span class="identifier">result_t</span> <span class="identifier">success</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span>
  713. <span class="keyword">const</span> <span class="identifier">result_t</span> <span class="identifier">fail</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
  714. <span class="comment">// move motor to the indicated target position in steps</span>
  715. <span class="identifier">result_t</span> <span class="identifier">test</span><span class="special">(</span><span class="identifier">position_t</span> <span class="identifier">new_position</span><span class="special">)</span><span class="special">{</span>
  716. <span class="keyword">try</span> <span class="special">{</span>
  717. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"move motor to "</span> <span class="special">&lt;&lt;</span> <span class="identifier">new_position</span> <span class="special">&lt;&lt;</span> <span class="char">'\n'</span><span class="special">;</span>
  718. <span class="identifier">motor_run</span><span class="special">(</span><span class="identifier">new_position</span><span class="special">)</span><span class="special">;</span>
  719. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span>
  720. <span class="special">&lt;&lt;</span> <span class="string">"step #"</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  721. <span class="special">&lt;&lt;</span> <span class="string">"delay(us)(24.8)"</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  722. <span class="special">&lt;&lt;</span> <span class="string">"delay(us)"</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  723. <span class="special">&lt;&lt;</span> <span class="string">"CCPR"</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  724. <span class="special">&lt;&lt;</span> <span class="string">"motor position"</span> <span class="special">&lt;&lt;</span> <span class="char">'\n'</span><span class="special">;</span>
  725. <span class="keyword">while</span><span class="special">(</span><span class="identifier">busy</span><span class="special">(</span><span class="special">)</span><span class="special">)</span><span class="special">{</span>
  726. <span class="identifier">std</span><span class="special">::</span><span class="identifier">this_thread</span><span class="special">::</span><span class="identifier">sleep_for</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">microseconds</span><span class="special">(</span><span class="identifier">to_microseconds</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span><span class="special">)</span><span class="special">)</span><span class="special">;</span>
  727. <span class="identifier">c_t</span> <span class="identifier">last_c</span> <span class="special">=</span> <span class="identifier">c</span><span class="special">;</span>
  728. <span class="identifier">ccpr_t</span> <span class="identifier">last_ccpr</span> <span class="special">=</span> <span class="identifier">ccpr</span><span class="special">;</span>
  729. <span class="identifier">isr_motor_step</span><span class="special">(</span><span class="special">)</span><span class="special">;</span>
  730. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  731. <span class="special">&lt;&lt;</span> <span class="identifier">last_c</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  732. <span class="special">&lt;&lt;</span> <span class="identifier">to_microseconds</span><span class="special">(</span><span class="identifier">last_c</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  733. <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">hex</span> <span class="special">&lt;&lt;</span> <span class="identifier">last_ccpr</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">dec</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span>
  734. <span class="special">&lt;&lt;</span> <span class="identifier">motor_position</span> <span class="special">&lt;&lt;</span> <span class="char">'\n'</span><span class="special">;</span>
  735. <span class="special">}</span><span class="special">;</span>
  736. <span class="special">}</span>
  737. <span class="keyword">catch</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception</span> <span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span><span class="special">{</span>
  738. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">(</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="char">'\n'</span><span class="special">;</span>
  739. <span class="keyword">return</span> <span class="identifier">fail</span><span class="special">;</span>
  740. <span class="special">}</span>
  741. <span class="keyword">return</span> <span class="identifier">success</span><span class="special">;</span>
  742. <span class="special">}</span>
  743. <span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="special">)</span><span class="special">{</span>
  744. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"start test\n"</span><span class="special">;</span>
  745. <span class="identifier">result_t</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">success</span><span class="special">;</span>
  746. <span class="keyword">try</span> <span class="special">{</span>
  747. <span class="identifier">initialize</span><span class="special">(</span><span class="special">)</span><span class="special">;</span>
  748. <span class="comment">// move motor to position 1000</span>
  749. <span class="identifier">result</span> <span class="special">&amp;=</span> <span class="identifier">test</span><span class="special">(</span><span class="identifier">literal</span><span class="special">(</span><span class="number">1000</span><span class="special">)</span><span class="special">)</span><span class="special">;</span>
  750. <span class="comment">// move to the left before zero position</span>
  751. <span class="comment">// fails to compile !</span>
  752. <span class="comment">// result &amp;= ! test(-10);</span>
  753. <span class="comment">// move motor to position 200</span>
  754. <span class="identifier">result</span> <span class="special">&amp;=</span> <span class="identifier">test</span><span class="special">(</span><span class="identifier">literal</span><span class="special">(</span><span class="number">200</span><span class="special">)</span><span class="special">)</span><span class="special">;</span>
  755. <span class="comment">// move motor to position 200 again! Should result in no movement.</span>
  756. <span class="identifier">result</span> <span class="special">&amp;=</span> <span class="identifier">test</span><span class="special">(</span><span class="identifier">literal</span><span class="special">(</span><span class="number">200</span><span class="special">)</span><span class="special">)</span><span class="special">;</span>
  757. <span class="comment">// move motor to position 50000.</span>
  758. <span class="identifier">result</span> <span class="special">&amp;=</span> <span class="identifier">test</span><span class="special">(</span><span class="identifier">literal</span><span class="special">(</span><span class="number">50000</span><span class="special">)</span><span class="special">)</span><span class="special">;</span>
  759. <span class="comment">// move motor back to position 0.</span>
  760. <span class="identifier">result</span> <span class="special">&amp;=</span> <span class="identifier">test</span><span class="special">(</span><span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">)</span><span class="special">;</span>
  761. <span class="special">}</span>
  762. <span class="keyword">catch</span><span class="special">(</span><span class="special">...</span><span class="special">)</span><span class="special">{</span>
  763. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"test interrupted\n"</span><span class="special">;</span>
  764. <span class="keyword">return</span> <span class="identifier">EXIT_FAILURE</span><span class="special">;</span>
  765. <span class="special">}</span>
  766. <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"end test\n"</span><span class="special">;</span>
  767. <span class="keyword">return</span> <span class="identifier">result</span> <span class="special">==</span> <span class="identifier">success</span> <span class="special">?</span> <span class="identifier">EXIT_SUCCESS</span> <span class="special">:</span> <span class="identifier">EXIT_FAILURE</span><span class="special">;</span>
  768. <span class="special">}</span>
  769. </pre>
  770. <p>Here are the changes we've made int the desktop test
  771. program</p>
  772. <div class="orderedlist"><ol class="orderedlist" type="1">
  773. <li class="listitem"><p>Specify exception policies so we can generate a compile time
  774. error whenever an operation MIGHT fail. We've aliased this policy
  775. with the name <code class="computeroutput">trap_policy</code>. The default policy of which
  776. throws a runtime exception when an error is countered is aliased as
  777. <code class="computeroutput">exception_policy</code>. When creating safe types, we'll now
  778. specify which type of checking, compile time or runtime, we want
  779. done.</p></li>
  780. <li class="listitem">
  781. <p>Create a macro named "literal" an integral value that can be
  782. evaluated at compile time.</p>
  783. <p>"literal" values are instances of safe numeric types which are
  784. determined at compile time. They are <code class="computeroutput">constexpr</code> values.
  785. When used along with other instances of safe numeric types, the
  786. compiler can calculate the range of the result and verify whether or
  787. not it can be contained in the result type. To create "literal"
  788. types we use the macro <code class="computeroutput"><a class="link" href="safe_literal.html#safe_numerics.safe_literal.make_safe_literal" title="make_safe_literal(n, PP, EP)">make_safe_literal</a>(n,
  789. p, e)</code> where n is the value, p is the <a class="link" href="promotion_policy.html" title="PromotionPolicy&lt;PP&gt;">promotion policy</a> and
  790. e is the <a class="link" href="exception_policy.html" title="ExceptionPolicy&lt;EP&gt;">exception
  791. policy</a>.</p>
  792. <p>When all the values in an expression are safe numeric values,
  793. the compiler can calculate the narrowest range of the result. If all
  794. the values in this range can be represented by the result type, then
  795. it can be guaranteed that an invalid result cannot be produced at
  796. runtime and no runtime checking is required.</p>
  797. <p>Make sure that all literal values are x are replaced with the
  798. macro invocation "literal(x)".</p>
  799. <p>It's unfortunate that the "literal" macro is required as it
  800. clutters the code. The good news is that is some future version of
  801. C++, expansion of <code class="computeroutput">constexpr</code> facilities may result in
  802. elimination of this requirement.</p>
  803. </li>
  804. <li class="listitem">
  805. <p>Create special types for the motor program. These will
  806. guarantee that values are in the expected ranges and permit compile
  807. time determination of when exceptional conditions might occur. In
  808. this example we create a special type c_t to the width of the pulse
  809. applied to the motor. Engineering constraints (motor load inertia)
  810. limit this value to the range of C0 to C_MIN. So we create a type
  811. with those limits. By using limits no larger than necessary, we
  812. supply enough information for the compiler to determine that the
  813. result of a calculation cannot fall outside the range of the result
  814. type. So less runtime checking is required. In addition, we get
  815. extra verification at compile time that values are in reasonable
  816. ranges for the quantity being modeled.</p>
  817. <p>We call these types "strong types".</p>
  818. </li>
  819. </ol></div>
  820. <p>And we've made changes consistent with the above to <a href="../../example/motor3.c" target="_top">motor3.c</a> as well</p>
  821. <pre class="programlisting"><span class="comment">/*
  822. * david austin
  823. * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
  824. * DECEMBER 30, 2004
  825. *
  826. * Demo program for stepper motor control with linear ramps
  827. * Hardware: PIC18F252, L6219
  828. *
  829. * Copyright (c) 2015 Robert Ramey
  830. *
  831. * Distributed under the Boost Software License, Version 1.0. (See
  832. * accompanying file LICENSE_1_0.txt or copy at
  833. * http://www.boost.org/LICENSE_1_0.txt)
  834. */</span>
  835. <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">assert</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span>
  836. <span class="comment">// ramp state-machine states</span>
  837. <span class="keyword">enum</span> <span class="identifier">ramp_state</span> <span class="special">{</span>
  838. <span class="identifier">ramp_idle</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span>
  839. <span class="identifier">ramp_up</span> <span class="special">=</span> <span class="number">1</span><span class="special">,</span>
  840. <span class="identifier">ramp_const</span> <span class="special">=</span> <span class="number">2</span><span class="special">,</span>
  841. <span class="identifier">ramp_down</span> <span class="special">=</span> <span class="number">3</span><span class="special">,</span>
  842. <span class="special">}</span><span class="special">;</span>
  843. <span class="comment">// ***************************</span>
  844. <span class="comment">// 1. Define state variables using custom strong types</span>
  845. <span class="comment">// initial setup</span>
  846. <span class="keyword">enum</span> <span class="identifier">ramp_state</span> <span class="identifier">ramp_sts</span><span class="special">;</span>
  847. <span class="identifier">position_t</span> <span class="identifier">motor_position</span><span class="special">;</span>
  848. <span class="identifier">position_t</span> <span class="identifier">m</span><span class="special">;</span> <span class="comment">// target position</span>
  849. <span class="identifier">position_t</span> <span class="identifier">m2</span><span class="special">;</span> <span class="comment">// midpoint or point where acceleration changes</span>
  850. <span class="identifier">direction_t</span> <span class="identifier">d</span><span class="special">;</span> <span class="comment">// direction of traval -1 or +1</span>
  851. <span class="comment">// curent state along travel</span>
  852. <span class="identifier">step_t</span> <span class="identifier">i</span><span class="special">;</span> <span class="comment">// step number</span>
  853. <span class="identifier">c_t</span> <span class="identifier">c</span><span class="special">;</span> <span class="comment">// 24.8 fixed point delay count increment</span>
  854. <span class="identifier">ccpr_t</span> <span class="identifier">ccpr</span><span class="special">;</span> <span class="comment">// 24.8 fixed point delay count</span>
  855. <span class="identifier">phase_ix_t</span> <span class="identifier">phase_ix</span><span class="special">;</span> <span class="comment">// motor phase index</span>
  856. <span class="comment">// ***************************</span>
  857. <span class="comment">// 2. Surround all literal values with the "literal" keyword</span>
  858. <span class="comment">// Config data to make CCP1&amp;2 generate quadrature sequence on PHASE pins</span>
  859. <span class="comment">// Action on CCP match: 8=set+irq; 9=clear+irq</span>
  860. <span class="identifier">phase_t</span> <span class="keyword">const</span> <span class="identifier">ccpPhase</span><span class="special">[</span><span class="special">]</span> <span class="special">=</span> <span class="special">{</span>
  861. <span class="identifier">literal</span><span class="special">(</span><span class="number">0x909</span><span class="special">)</span><span class="special">,</span>
  862. <span class="identifier">literal</span><span class="special">(</span><span class="number">0x908</span><span class="special">)</span><span class="special">,</span>
  863. <span class="identifier">literal</span><span class="special">(</span><span class="number">0x808</span><span class="special">)</span><span class="special">,</span>
  864. <span class="identifier">literal</span><span class="special">(</span><span class="number">0x809</span><span class="special">)</span>
  865. <span class="special">}</span><span class="special">;</span> <span class="comment">// 00,01,11,10</span>
  866. <span class="keyword">void</span> <span class="identifier">current_on</span><span class="special">(</span><span class="special">)</span><span class="special">{</span><span class="comment">/* code as needed */</span><span class="special">}</span> <span class="comment">// motor drive current</span>
  867. <span class="keyword">void</span> <span class="identifier">current_off</span><span class="special">(</span><span class="special">)</span><span class="special">{</span><span class="comment">/* code as needed */</span><span class="special">}</span> <span class="comment">// reduce to holding value</span>
  868. <span class="comment">// ***************************</span>
  869. <span class="comment">// 3. Refactor code to make it easier to understand</span>
  870. <span class="comment">// and relate to the documentation</span>
  871. <span class="keyword">bool</span> <span class="identifier">busy</span><span class="special">(</span><span class="special">)</span><span class="special">{</span>
  872. <span class="keyword">return</span> <span class="identifier">ramp_idle</span> <span class="special">!=</span> <span class="identifier">ramp_sts</span><span class="special">;</span>
  873. <span class="special">}</span>
  874. <span class="comment">// set outputs to energize motor coils</span>
  875. <span class="keyword">void</span> <span class="identifier">update</span><span class="special">(</span><span class="identifier">ccpr_t</span> <span class="identifier">ccpr</span><span class="special">,</span> <span class="identifier">phase_ix_t</span> <span class="identifier">phase_ix</span><span class="special">)</span><span class="special">{</span>
  876. <span class="comment">// energize correct windings</span>
  877. <span class="keyword">const</span> <span class="identifier">phase_t</span> <span class="identifier">phase</span> <span class="special">=</span> <span class="identifier">ccpPhase</span><span class="special">[</span><span class="identifier">phase_ix</span><span class="special">]</span><span class="special">;</span>
  878. <span class="identifier">CCP1CON</span> <span class="special">=</span> <span class="identifier">phase</span> <span class="special">&amp;</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0xff</span><span class="special">)</span><span class="special">;</span> <span class="comment">// set CCP action on next match</span>
  879. <span class="identifier">CCP2CON</span> <span class="special">=</span> <span class="identifier">phase</span> <span class="special">&gt;&gt;</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">8</span><span class="special">)</span><span class="special">;</span>
  880. <span class="comment">// timer value at next CCP match</span>
  881. <span class="identifier">CCPR1H</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0xff</span><span class="special">)</span> <span class="special">&amp;</span> <span class="special">(</span><span class="identifier">ccpr</span> <span class="special">&gt;&gt;</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">8</span><span class="special">)</span><span class="special">)</span><span class="special">;</span>
  882. <span class="identifier">CCPR1L</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0xff</span><span class="special">)</span> <span class="special">&amp;</span> <span class="identifier">ccpr</span><span class="special">;</span>
  883. <span class="special">}</span>
  884. <span class="comment">// compiler-specific ISR declaration</span>
  885. <span class="comment">// ***************************</span>
  886. <span class="comment">// 4. Rewrite interrupt handler in a way which mirrors the orginal</span>
  887. <span class="comment">// description of the algorithm and minimizes usage of state variable,</span>
  888. <span class="comment">// accumulated values, etc.</span>
  889. <span class="keyword">void</span> <span class="identifier">__interrupt</span> <span class="identifier">isr_motor_step</span><span class="special">(</span><span class="keyword">void</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// CCP1 match -&gt; step pulse + IRQ</span>
  890. <span class="comment">// *** possible exception</span>
  891. <span class="comment">// motor_position += d;</span>
  892. <span class="comment">// use the following to avoid mixing exception policies which is an error</span>
  893. <span class="keyword">if</span><span class="special">(</span><span class="identifier">d</span> <span class="special">&lt;</span> <span class="number">0</span><span class="special">)</span>
  894. <span class="special">--</span><span class="identifier">motor_position</span><span class="special">;</span>
  895. <span class="keyword">else</span>
  896. <span class="special">++</span><span class="identifier">motor_position</span><span class="special">;</span>
  897. <span class="comment">// *** possible exception</span>
  898. <span class="special">++</span><span class="identifier">i</span><span class="special">;</span>
  899. <span class="comment">// calculate next difference in time</span>
  900. <span class="keyword">for</span><span class="special">(</span><span class="special">;</span><span class="special">;</span><span class="special">)</span><span class="special">{</span>
  901. <span class="keyword">switch</span> <span class="special">(</span><span class="identifier">ramp_sts</span><span class="special">)</span> <span class="special">{</span>
  902. <span class="keyword">case</span> <span class="identifier">ramp_up</span><span class="special">:</span> <span class="comment">// acceleration</span>
  903. <span class="keyword">if</span> <span class="special">(</span><span class="identifier">i</span> <span class="special">==</span> <span class="identifier">m2</span><span class="special">)</span> <span class="special">{</span>
  904. <span class="identifier">ramp_sts</span> <span class="special">=</span> <span class="identifier">ramp_down</span><span class="special">;</span>
  905. <span class="keyword">continue</span><span class="special">;</span>
  906. <span class="special">}</span>
  907. <span class="comment">// equation 13</span>
  908. <span class="comment">// *** possible negative overflow on update of c</span>
  909. <span class="identifier">c</span> <span class="special">-=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">2</span><span class="special">)</span> <span class="special">*</span> <span class="identifier">c</span> <span class="special">/</span> <span class="special">(</span><span class="identifier">literal</span><span class="special">(</span><span class="number">4</span><span class="special">)</span> <span class="special">*</span> <span class="identifier">i</span> <span class="special">+</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">1</span><span class="special">)</span><span class="special">)</span><span class="special">;</span>
  910. <span class="keyword">if</span><span class="special">(</span><span class="identifier">c</span> <span class="special">&lt;</span> <span class="identifier">C_MIN</span><span class="special">)</span><span class="special">{</span>
  911. <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">C_MIN</span><span class="special">;</span>
  912. <span class="identifier">ramp_sts</span> <span class="special">=</span> <span class="identifier">ramp_const</span><span class="special">;</span>
  913. <span class="comment">// *** possible exception</span>
  914. <span class="identifier">m2</span> <span class="special">=</span> <span class="identifier">m</span> <span class="special">-</span> <span class="identifier">i</span><span class="special">;</span> <span class="comment">// new inflection point</span>
  915. <span class="keyword">continue</span><span class="special">;</span>
  916. <span class="special">}</span>
  917. <span class="keyword">break</span><span class="special">;</span>
  918. <span class="keyword">case</span> <span class="identifier">ramp_const</span><span class="special">:</span> <span class="comment">// constant speed</span>
  919. <span class="keyword">if</span><span class="special">(</span><span class="identifier">i</span> <span class="special">&gt;</span> <span class="identifier">m2</span><span class="special">)</span> <span class="special">{</span>
  920. <span class="identifier">ramp_sts</span> <span class="special">=</span> <span class="identifier">ramp_down</span><span class="special">;</span>
  921. <span class="keyword">continue</span><span class="special">;</span>
  922. <span class="special">}</span>
  923. <span class="keyword">break</span><span class="special">;</span>
  924. <span class="keyword">case</span> <span class="identifier">ramp_down</span><span class="special">:</span> <span class="comment">// deceleration</span>
  925. <span class="keyword">if</span> <span class="special">(</span><span class="identifier">i</span> <span class="special">==</span> <span class="identifier">m</span><span class="special">)</span> <span class="special">{</span>
  926. <span class="identifier">ramp_sts</span> <span class="special">=</span> <span class="identifier">ramp_idle</span><span class="special">;</span>
  927. <span class="identifier">current_off</span><span class="special">(</span><span class="special">)</span><span class="special">;</span> <span class="comment">// reduce motor current to holding value</span>
  928. <span class="identifier">CCP1IE</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span> <span class="comment">// disable_interrupts(INT_CCP1);</span>
  929. <span class="keyword">return</span><span class="special">;</span>
  930. <span class="special">}</span>
  931. <span class="comment">// equation 14</span>
  932. <span class="comment">// *** possible positive overflow on update of c</span>
  933. <span class="comment">// note: re-arrange expression to avoid negative result</span>
  934. <span class="comment">// from difference of two unsigned values</span>
  935. <span class="identifier">c</span> <span class="special">+=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">2</span><span class="special">)</span> <span class="special">*</span> <span class="identifier">c</span> <span class="special">/</span> <span class="special">(</span><span class="identifier">literal</span><span class="special">(</span><span class="number">4</span><span class="special">)</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">m</span> <span class="special">-</span> <span class="identifier">i</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">1</span><span class="special">)</span><span class="special">)</span><span class="special">;</span>
  936. <span class="keyword">if</span><span class="special">(</span><span class="identifier">c</span> <span class="special">&gt;</span> <span class="identifier">C0</span><span class="special">)</span><span class="special">{</span>
  937. <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">C0</span><span class="special">;</span>
  938. <span class="special">}</span>
  939. <span class="keyword">break</span><span class="special">;</span>
  940. <span class="keyword">default</span><span class="special">:</span>
  941. <span class="comment">// should never arrive here!</span>
  942. <span class="identifier">assert</span><span class="special">(</span><span class="keyword">false</span><span class="special">)</span><span class="special">;</span>
  943. <span class="special">}</span> <span class="comment">// switch (ramp_sts)</span>
  944. <span class="keyword">break</span><span class="special">;</span>
  945. <span class="special">}</span>
  946. <span class="identifier">assert</span><span class="special">(</span><span class="identifier">c</span> <span class="special">&lt;=</span> <span class="identifier">C0</span> <span class="special">&amp;&amp;</span> <span class="identifier">c</span> <span class="special">&gt;=</span> <span class="identifier">C_MIN</span><span class="special">)</span><span class="special">;</span>
  947. <span class="comment">// *** possible exception</span>
  948. <span class="identifier">ccpr</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0xffffff</span><span class="special">)</span> <span class="special">&amp;</span> <span class="special">(</span><span class="identifier">ccpr</span> <span class="special">+</span> <span class="identifier">c</span><span class="special">)</span><span class="special">;</span>
  949. <span class="identifier">phase_ix</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">phase_ix</span> <span class="special">+</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">&amp;</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">3</span><span class="special">)</span><span class="special">;</span>
  950. <span class="identifier">update</span><span class="special">(</span><span class="identifier">ccpr</span><span class="special">,</span> <span class="identifier">phase_ix</span><span class="special">)</span><span class="special">;</span>
  951. <span class="special">}</span> <span class="comment">// isr_motor_step()</span>
  952. <span class="comment">// set up to drive motor to pos_new (absolute step#)</span>
  953. <span class="keyword">void</span> <span class="identifier">motor_run</span><span class="special">(</span><span class="identifier">position_t</span> <span class="identifier">new_position</span><span class="special">)</span> <span class="special">{</span>
  954. <span class="keyword">if</span><span class="special">(</span><span class="identifier">new_position</span> <span class="special">&gt;</span> <span class="identifier">motor_position</span><span class="special">)</span><span class="special">{</span>
  955. <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">1</span><span class="special">)</span><span class="special">;</span>
  956. <span class="comment">// *** possible exception</span>
  957. <span class="identifier">m</span> <span class="special">=</span> <span class="identifier">new_position</span> <span class="special">-</span> <span class="identifier">motor_position</span><span class="special">;</span>
  958. <span class="special">}</span>
  959. <span class="keyword">else</span>
  960. <span class="keyword">if</span><span class="special">(</span><span class="identifier">motor_position</span> <span class="special">&gt;</span> <span class="identifier">new_position</span><span class="special">)</span><span class="special">{</span>
  961. <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="special">-</span><span class="number">1</span><span class="special">)</span><span class="special">;</span>
  962. <span class="comment">// *** possible exception</span>
  963. <span class="identifier">m</span> <span class="special">=</span> <span class="identifier">motor_position</span> <span class="special">-</span> <span class="identifier">new_position</span><span class="special">;</span>
  964. <span class="special">}</span>
  965. <span class="keyword">else</span><span class="special">{</span>
  966. <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span>
  967. <span class="identifier">m</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span>
  968. <span class="identifier">ramp_sts</span> <span class="special">=</span> <span class="identifier">ramp_idle</span><span class="special">;</span> <span class="comment">// start ramp state-machine</span>
  969. <span class="keyword">return</span><span class="special">;</span>
  970. <span class="special">}</span>
  971. <span class="identifier">i</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span>
  972. <span class="identifier">m2</span> <span class="special">=</span> <span class="identifier">m</span> <span class="special">/</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">2</span><span class="special">)</span><span class="special">;</span>
  973. <span class="identifier">ramp_sts</span> <span class="special">=</span> <span class="identifier">ramp_up</span><span class="special">;</span> <span class="comment">// start ramp state-machine</span>
  974. <span class="identifier">T1CONbits</span><span class="special">.</span><span class="identifier">TMR1ON</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span> <span class="comment">// stop timer1;</span>
  975. <span class="identifier">current_on</span><span class="special">(</span><span class="special">)</span><span class="special">;</span> <span class="comment">// current in motor windings</span>
  976. <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">C0</span><span class="special">;</span>
  977. <span class="identifier">ccpr</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">TMR1H</span> <span class="special">&lt;&lt;</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">8</span><span class="special">)</span> <span class="special">|</span> <span class="identifier">TMR1L</span><span class="special">)</span> <span class="special">+</span> <span class="identifier">C0</span> <span class="special">+</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">1000</span><span class="special">)</span><span class="special">;</span>
  978. <span class="identifier">phase_ix</span> <span class="special">=</span> <span class="identifier">d</span> <span class="special">&amp;</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">3</span><span class="special">)</span><span class="special">;</span>
  979. <span class="identifier">update</span><span class="special">(</span><span class="identifier">ccpr</span><span class="special">,</span> <span class="identifier">phase_ix</span><span class="special">)</span><span class="special">;</span>
  980. <span class="identifier">CCP1IE</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">1</span><span class="special">)</span><span class="special">;</span> <span class="comment">// enable_interrupts(INT_CCP1);</span>
  981. <span class="identifier">T1CONbits</span><span class="special">.</span><span class="identifier">TMR1ON</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">1</span><span class="special">)</span><span class="special">;</span> <span class="comment">// restart timer1;</span>
  982. <span class="special">}</span> <span class="comment">// motor_run()</span>
  983. <span class="keyword">void</span> <span class="identifier">initialize</span><span class="special">(</span><span class="special">)</span> <span class="special">{</span>
  984. <span class="identifier">di</span><span class="special">(</span><span class="special">)</span><span class="special">;</span> <span class="comment">// disable_interrupts(GLOBAL);</span>
  985. <span class="identifier">motor_position</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span>
  986. <span class="identifier">CCP1IE</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span> <span class="comment">// disable_interrupts(INT_CCP1);</span>
  987. <span class="identifier">CCP2IE</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span> <span class="comment">// disable_interrupts(INT_CCP2);</span>
  988. <span class="identifier">PORTC</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span> <span class="comment">// output_c(0);</span>
  989. <span class="identifier">TRISC</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span> <span class="comment">// set_tris_c(0);</span>
  990. <span class="identifier">T3CON</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span>
  991. <span class="identifier">T1CON</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0x35</span><span class="special">)</span><span class="special">;</span>
  992. <span class="identifier">INTCONbits</span><span class="special">.</span><span class="identifier">PEIE</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">1</span><span class="special">)</span><span class="special">;</span>
  993. <span class="identifier">INTCONbits</span><span class="special">.</span><span class="identifier">RBIF</span> <span class="special">=</span> <span class="identifier">literal</span><span class="special">(</span><span class="number">0</span><span class="special">)</span><span class="special">;</span>
  994. <span class="identifier">ei</span><span class="special">(</span><span class="special">)</span><span class="special">;</span> <span class="comment">// enable_interrupts(GLOBAL);</span>
  995. <span class="special">}</span> <span class="comment">// initialize()</span>
  996. </pre>
  997. <div class="orderedlist"><ol class="orderedlist" type="1">
  998. <li class="listitem"><p>Define variables using strong types</p></li>
  999. <li class="listitem"><p>Surround all literal values with the "literal" keyword</p></li>
  1000. <li class="listitem"><p>Re-factor code to make it easier to understand and compare
  1001. with the algorithm as described in the original <a href="../../example/stepper-motor.pdf" target="_top">article</a>.</p></li>
  1002. <li class="listitem"><p>Rewrite interrupt handler in a way which mirrors the original
  1003. description of the algorithm and minimizes usage of state variable,
  1004. accumulated values, etc.</p></li>
  1005. <li class="listitem"><p>Distinguish all the statements which might invoke a runtime
  1006. exception with a comment. There are 12 such instances.</p></li>
  1007. </ol></div>
  1008. <p>Finally we make a couple minor changes in <a href="../../example/motor_test3.c" target="_top">motor_test3.c</a> to verify that we
  1009. can compile the exact same version of motor3.c on the PIC as well as on
  1010. the desktop.</p>
  1011. </div>
  1012. <div class="section">
  1013. <div class="titlepage"><div><div><h4 class="title">
  1014. <a name="idm130204123024"></a>Summary</h4></div></div></div>
  1015. <p>The intent of this case study is to show that the Safe Numerics
  1016. Library can be an essential tool in validating the correctness of C/C++
  1017. programs in all environments - including the most restricted.</p>
  1018. <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  1019. <li class="listitem"><p>We started with a program written for a tiny micro controller
  1020. for controlling the acceleration and deceleration of a stepper
  1021. motor. The algorithm for doing this is very non-trivial and
  1022. difficult prove that it is correct.</p></li>
  1023. <li class="listitem"><p>We used the type promotion policies of the Safe Numerics
  1024. Library to test and validate this algorithm on the desk top. The
  1025. tested code is also compiled for the target micro controller.</p></li>
  1026. <li class="listitem"><p>We used <span class="emphasis"><em>strong typing</em></span> features of Safe
  1027. Numerics to check that all types hold the values expected and invoke
  1028. no invalid implicit conversions. Again the tested code is compiled
  1029. for the target processor.</p></li>
  1030. </ul></div>
  1031. <p>What we failed to do is to create a version of the program which
  1032. uses the type system to prove that no results can be invalid. I turns out
  1033. that states such as</p>
  1034. <pre class="programlisting"><span class="special">++</span><span class="identifier">i</span><span class="special">;</span>
  1035. <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span><span class="special">;</span></pre>
  1036. <p>can't be proved not to overflow with this system. So we're left with
  1037. having to depend upon exhaustive testing. It's not what we hoped, but it's
  1038. the best we can do.</p>
  1039. </div>
  1040. </div>
  1041. <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
  1042. <td align="left"></td>
  1043. <td align="right"><div class="copyright-footer">Copyright &#169; 2012-2018 Robert Ramey<p><a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">Subject to Boost
  1044. Software License</a></p>
  1045. </div></td>
  1046. </tr></table>
  1047. <hr>
  1048. <div class="spirit-nav">
  1049. <a accesskey="p" href="composition_with_other_libraries.html"><img src="images/prev.png" alt="Prev"></a><a accesskey="u" href="case_studies.html"><img src="images/up.png" alt="Up"></a><a accesskey="h" href="index.html"><img src="images/home.png" alt="Home"></a><a accesskey="n" href="notes.html"><img src="images/next.png" alt="Next"></a>
  1050. </div>
  1051. </body>
  1052. </html>