{"id":6911,"date":"2020-10-26T07:16:34","date_gmt":"2020-10-26T14:16:34","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=6911"},"modified":"2020-10-26T07:16:34","modified_gmt":"2020-10-26T14:16:34","slug":"customizing-embedded-projects-with-stand-alone-frameworks","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/arm\/cmake\/standalone\/frameworks\/","title":{"rendered":"Customizing Embedded Projects with Stand-Alone Frameworks"},"content":{"rendered":"<p>This tutorial shows how to customize Advanced CMake-based Embedded Projects by creating stand-alone embedded frameworks. Stand-alone frameworks are forked versions of the vendor-supplied frameworks (such as the STM32 USB library) that can be used in place of the original frameworks. This allows keeping one or more patched versions of the commonly used libraries under source control, while otherwise relying on the original BSP packages installed by VisualGDB.<\/p>\n<p>We will start by creating a basic USB device project for the STM32F4Discovery board. It will follow the default project layout referencing the shared STM32-specific files installed under the %LOCALAPPDATA% folder:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/struct1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6912\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/struct1.png\" alt=\"\" width=\"1274\" height=\"417\" \/><\/a>Then we will convert the USB library to a stand-alone framework, while keeping the references to the rest of the shared STM32 components:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/struct2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6913\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/struct2.png\" alt=\"\" width=\"1274\" height=\"609\" \/><\/a>Before you begin, install VisualGDB 5.5 or later.<\/p>\n<ol>\n<li>Start Visual Studio and locate the VisualGDB Embedded Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/01-newprj-3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6914\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/01-newprj-3.png\" alt=\"\" width=\"1024\" height=\"680\" \/><\/a><\/li>\n<li>Enter the name and location of the first project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/02-name-4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6915\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/02-name-4.png\" alt=\"\" width=\"1024\" height=\"680\" \/><\/a><\/li>\n<li>Make sure you have the <strong>Advanced CMake<\/strong> project subsystem selected on the <strong>Project Type<\/strong> page of the VisualGDB Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/03-cmake-5.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6916\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/03-cmake-5.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Select your toolchain and the target device. In this tutorial we will target the STM32F4Discovery board that uses the STM32F407VG chip:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/04-device-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6917\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/04-device-1.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>On the next page select the sample project you would like to clone. In this tutorial we will demonstrate the stand-alone frameworks based on the STM32 USB Framework, so we will use the USB Communication Device sample:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/05-comm.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6918\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/05-comm.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Finally, select the debug settings that work with your board and click &#8220;Finish&#8221; to create the project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/06-stlink-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6919\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/06-stlink-1.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>VisualGDB will generate a simple embedded application based on the <strong>USB Device<\/strong> sample. Note how aside from the application itself <span style=\"text-decoration: underline;\"><strong>(3)<\/strong><\/span>, the Solution Explorer shows the shared STM32 BSP <span style=\"text-decoration: underline;\"><strong>(1)<\/strong><\/span> that includes the STM32 USB Device Library <span style=\"text-decoration: underline;\"><strong>(2)<\/strong><\/span>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/prjstr.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6934\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/prjstr.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>Right-click on the project node (with CMake icon) in Solution Explorer and select &#8220;VisualGDB Project Properties&#8221;. Note how the project explicitly references the STM32 USB Device Library:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/07-usb.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6920\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/07-usb.png\" alt=\"\" width=\"953\" height=\"702\" \/><\/a>This reference makes sure that VisualGDB will automatically locate the USB device library inside the STM32 BSP, and will link it together with the project.<\/li>\n<li>Open the <strong>usbd_cdc.c<\/strong> file from the <strong>STM32 USB Device Library<\/strong> framework. See how it is located under <strong>%LOCALAPPDATA%\\VisualGDB\\EmbeddedBSPs<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/08-cdc.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6921\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/08-cdc.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>Although we could technically patch this file to modify its functionality, the changes would never make it into our source control, and would be overwritten next time the STM32 BSP is reinstalled. Instead, we will now convert the <strong>STM32 USB Device Library<\/strong> into a stand-alone framework, so that we could easily make changes to it. Click the &#8220;Convert to a Stand-alone Framework&#8221; command from the framework context menu:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/09-standalone.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6922\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/09-standalone.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>VisualGDB will ask for the name, location, and a few other parameters of the new framework. Make sure you enter the following values:<br \/>\n<table style=\"border-collapse: collapse; width: 100%;\" border=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 33.3333%;\">Parameter<\/td>\n<td style=\"width: 33.3333%;\">Meaning<\/td>\n<td style=\"width: 33.3333%;\">Value<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%;\">Framework ID<\/td>\n<td style=\"width: 33.3333%;\">Used to distinguish the framework from other frameworks. Ignored for stand-alone frameworks until you include it into an exported BSP. Otherwise, must be unique within the exported BSP, but can collide with frameworks from other BSPs.<\/td>\n<td style=\"width: 33.3333%;\">Leave default<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%;\">Framework Name<\/td>\n<td style=\"width: 33.3333%;\">User-friendly framework name shown in Solution Explorer.<\/td>\n<td style=\"width: 33.3333%;\">Leave default<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%;\">Short Library Name<\/td>\n<td style=\"width: 33.3333%;\">Name of the underlying CMake library. Used in CMake statements. Shorter names recomended.<\/td>\n<td style=\"width: 33.3333%;\">USBFramework<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%;\">Framework Location<\/td>\n<td style=\"width: 33.3333%;\">Directory where the framework will be placed.<\/td>\n<td style=\"width: 33.3333%;\">Choose a location under source control.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/10-files.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6923\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/10-files.png\" alt=\"\" width=\"786\" height=\"657\" \/><\/a>Cloning a framework will preserve its configurable options (e.g. ability to choose between CDC, HID and other USB device classes). Normally, VisualGDB will try to leave out the files that are not directly involved in building (e.g. configuration file templates). This works with the STM32 USB Device Library, but may break frameworks the use implicit dependencies. If the cloned framework fails to build, select &#8220;<strong>Copy: All files from the original folder<\/strong>&#8221; instead.<\/li>\n<li>VisualGDB will copy the framework contents into the new directory and will update the <strong>CMakeLists.txt<\/strong> file:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/16-cmake.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6929\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/16-cmake.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a>Note how the framework reference explicitly specifies the short name and the relative path to the framework directory. If you want to move the framework to a new location, simply update the <strong>import_framework()<\/strong> statement accordingly. If you do any changes manually, make sure that the name in <strong>target_link_libraries()<\/strong> matches the <strong>NAME<\/strong> in <strong>import_framework()<\/strong>.<\/li>\n<li>Go to the definition of <strong>VCP_write()<\/strong> and use CodeJumps to quickly locate <strong>USBD_CDC_TransmitPacket()<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/11-moved.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6924\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/11-moved.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>See how it is now located in <strong>usb_cdc.c<\/strong> file under the source control:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/12-packet.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6925\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/12-packet.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>We will now edit the framework to support simple statistics counting. Add the following code to usbd_cdc.h:\n<pre class=\"\">typedef struct\r\n{\r\n    int ReceivedPackets, TransmittedPackets;\r\n} CDCStatistics;\r\n\r\nextern CDCStatistics g_CDCStatistics;<\/pre>\n<p>Then, instantiate <strong>g_CDCStatistics<\/strong> in usbd_cdc.c:<\/p>\n<pre class=\"\">CDCStatistics g_CDCStatistics;<\/pre>\n<p>Finally, update <strong>USD_CDC_TransmitPacket()<\/strong> and <strong>USBD_CDC_ReceivePacket()<\/strong> to increase the counters in the statistics structure:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/13-stats.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6926\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/13-stats.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>Update the loop in the main source file to print the statistics:\n<pre class=\"\">for (;;)\r\n{\r\n\tif (VCP_read(&amp;byte, 1) != 1)\r\n\t\tcontinue;\r\n\r\n        char buffer[128];\r\n        sprintf(buffer, \"\\r\\nYou typed '%c'. Received %d packets, sent %d packets\\r\\n\",\r\n                byte, g_CDCStatistics.ReceivedPackets, g_CDCStatistics.TransmittedPackets);\r\n\r\n        VCP_write(buffer, strlen(buffer));\r\n}<\/pre>\n<p>Then, press F5 to run the program. You can observe the real-time packet counts via <strong>Debug-&gt;Windows-&gt;Live Watch<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/14-live.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6927\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/14-live.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>Right-click on the project node and open the Serial Terminal (VisualGDB Custom Edition) or use <a href=\"https:\/\/sysprogs.com\/SmarTTY\/\">SmarTTY<\/a> to connect to the virtual serial port provided by the application. Try typing some characters in it and observe how the packet counts change in <strong>Live Watch<\/strong> and are shown in the output:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/15-updated.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6928\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/15-updated.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>You can reference the stand-alone framework from another project by removing the original USB framework reference from the <strong>find_bsp()<\/strong> statement and manually adding the <strong>import_framework()<\/strong> statement to <strong>CMakeLists.txt<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/21-ext.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6935\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/21-ext.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>Then, use the <strong>Add-&gt;Add Reference<\/strong> command in Solution Explorer to reference the framework from specific application targets:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/22-refs.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6936\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/10\/22-refs.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<\/ol>\n<p>You can find the source code for the project shown in this tutorial in our <a href=\"https:\/\/github.com\/sysprogs\/tutorials\/tree\/master\/visualgdb\/ARM\/CMake\/StandaloneFrameworkDemo\">Github repository<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to customize Advanced CMake-based Embedded Projects by creating stand-alone embedded frameworks. Stand-alone frameworks are forked versions<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[222],"tags":[223,61,71],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/6911"}],"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=6911"}],"version-history":[{"count":2,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/6911\/revisions"}],"predecessor-version":[{"id":6939,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/6911\/revisions\/6939"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=6911"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=6911"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=6911"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}