{"id":128,"date":"2014-08-24T09:56:04","date_gmt":"2014-08-24T09:56:04","guid":{"rendered":"http:\/\/visualgdb.com\/w\/?p=128"},"modified":"2015-09-24T10:25:34","modified_gmt":"2015-09-24T17:25:34","slug":"arm-stm32-fpu","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/arm\/stm32\/fpu\/","title":{"rendered":"Using STM32 Hardware Floating Point Support"},"content":{"rendered":"<p>This tutorial shows how to use the hardware floating-point module present on STM32F4 devices. We will demonstrate the use of floating point by producing a &#8220;breathing LED effect&#8221; &#8211; gradually turning the LED on and off. The LED itself cannot be &#8216;partially on&#8217;, however if we quickly turn it on and off (&gt;100Hz) having it on X% of the time, it will look like the LED is at the X% of its maximum brightness:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/pwm.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/pwm.png\" alt=\"pwm\" width=\"700\" height=\"144\" \/><\/a><\/p>\n<p>The proportion of the time when the LED is on is called <strong>duty cycle<\/strong>. To achieve the &#8220;breathing effect&#8221; we will adjust the duty cycle gradually according to the sine waveform:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/sine.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/sine.png\" alt=\"sine\" width=\"700\" height=\"247\" \/><\/a><\/p>\n<p>The PWM pulse width will hence be calculated as T\u00b7(1 +<br \/>\nsin(<em>arg<\/em>)) \/ 2, where T is the PWM period and <em>arg<\/em> is a floating-point counter that we keep increasing in small increments.<\/p>\n<ol>\n<li>Follow our <a href=\"http:\/\/visualgdb.com\/tutorials\/arm\/stm32\/fpu\/..\/pwm\/\">PWM tutorial<\/a> to create a basic PWM blinking LED program. Use the default &#8216;software floating point mode&#8217; for the beginning. Build the project and run it to ensure that it works:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/01-prj.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/01-prj.png\" alt=\"01-prj\" width=\"698\" height=\"600\" \/><\/a><\/li>\n<li>Now we will modify the PWM sample to produce a basic &#8216;breathing effect&#8217;. First of all, change the prescaler in <strong>InitializeTimer()<\/strong> from 40000 to 1. This will increase the timer frequency to a point where the blinking is not noticeable anymore:\n<pre>timerInitStructure.TIM_Prescaler = 1;<\/pre>\n<\/li>\n<li>Then include the <strong>&lt;math.h&gt;<\/strong> file and replace the contents of main() with the following:\n<pre class=\"\">const int period = 1000;\r\n\r\nInitializeLEDs();\r\nInitializeTimer(period);\r\nInitializePWMChannel();\r\nfor (float arg = 0;;arg += 0.0001F)\r\n{\r\n    uint32_t pulseWidth = (period \/ 2) * (1 + sinf(arg));\r\n    TIM_SetCompare1(TIM4, pulseWidth);\r\n}<\/pre>\n<\/li>\n<li>Build and start debugging your program. Notice the smooth LED &#8216;breathing&#8217;. Set a breakpoint on the line calling the sinf() function and once it is hit go to disassembly:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/02-disasm.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/02-disasm.png\" alt=\"02-disasm\" width=\"698\" height=\"600\" \/><\/a>Note how addition and multiplication have been implemented by calling the library functions (with arguments being passed via general-purpose registers).<\/li>\n<li>Now we will change the floating-point mode to hardware. Go to VisualGDB Project Properties, press &#8220;Change Settings&#8221; and select &#8220;Hardware&#8221; in &#8220;floating point support&#8221;:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/03-hardfp.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/03-hardfp.png\" alt=\"03-hardfp\" width=\"690\" height=\"648\" \/><\/a><\/li>\n<li>Press OK and rebuild your project. Note that <strong>-mfloat-abi=hard<\/strong> has been added to GCC flags:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/04-eabi.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/04-eabi.png\" alt=\"04-eabi\" width=\"698\" height=\"600\" \/><\/a><\/li>\n<li>Press F5 to start debugging. Note how the LED &#8216;breathing&#8217; has become significantly faster as each iteration of the loop now takes fewer time to complete:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/led_on.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/led_on.png\" alt=\"led_on\" width=\"700\" height=\"466\" \/><\/a><\/li>\n<li>Set a breakpoint on the line calling <strong>sinf()<\/strong>. Once it hits, open the Disassembly view:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/05-disasm2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/05-disasm2.png\" alt=\"05-disasm2\" width=\"698\" height=\"600\" \/><\/a>Note how addition and multiplication now take one instruction each (<strong>vadd<\/strong>\/<strong>vmul<\/strong>). Sine is still computed by calling a library function.<\/li>\n<li>STM32F4 floating-point unit only supports 32-bit floating point numbers (<strong>float <\/strong>type, but not the <strong>double <\/strong>type). If you are using an older GCC version, it will still try to generate hardware floating-point instructions for operations with <strong>double <\/strong>that will cause a run-time exception. We will demonstrate it now. Change &#8216;<strong>float<\/strong>&#8216; to &#8216;<strong>double<\/strong>&#8216; in the loop declaration, build and run your program. Once the program is running (and the LED looks frozen) select Debug-&gt;Break All:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/06-handler.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/06-handler.png\" alt=\"06-handler\" width=\"698\" height=\"600\" \/><\/a><\/li>\n<li>You will see that the program is stopped at the exception handler, and the call stack does not provide meaningful information about the cause of the exception. This happens because GDB does not know how to unwind ARM exception frames, so we need to do it manually. Open the Memory view and type &#8220;$sp&#8221; in the Address field:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/07-sp.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/07-sp.png\" alt=\"07-sp\" width=\"698\" height=\"600\" \/><\/a><\/li>\n<li>According to the <a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.dui0552a\/Babefdjc.html\"> ARM documentation<\/a>, the value of the PC register when the exception happened is stored under [pc + 0x18]. Copy that value into the Disassembly window (prefix it with 0x):<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/08-disasm3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-11\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/tutorials\/arm\/stm32\/fpu\/08-disasm3.png\" alt=\"08-disasm3\" width=\"698\" height=\"600\" \/><\/a>In this example the exception was caused by the <strong> vcvt.f32.f64<\/strong> instruction that is not supported on STM32F4 devices due to lack of 64-bit floating point support. Use a more recent toolchain to support double properly. Our <a href=\"http:\/\/gnutoolchains.com\/arm-eabi\/\"> toolchains<\/a> starting from gcc 4.9.1 include a fix that resolves the <strong>double <\/strong>handling for cortex devices in hardware FP mode.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use the hardware floating-point module present on STM32F4 devices. We will demonstrate the use of<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16],"tags":[53,66,61],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/128"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=128"}],"version-history":[{"count":1,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/128\/revisions"}],"predecessor-version":[{"id":1063,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/128\/revisions\/1063"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=128"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}