Official Blog of Silicon Labs

    Publish
     
      • Adding Micrium OS on a Flex Gecko

        Janos Magasrevy | 06/159/2018 | 06:05 PM

        This blog should serve as a guide to adding Micrium OS on a Flex Gecko and get at least one task running on the device.

        I will now share with you my experience while going through this exercise.

        Getting Started

        I decided to perform a clean installation of Simplicity Studio in order to avoid conflicts inflicted by software updates over time. After installing the tool, before even attempting to add anything, I first had to make sure that I had the necessary SDKs. Here's what I installed:

        • 32-bit MCU SDK - 5.5.0.0
        • Micrium OS - 5.4.0
        • Flex SDK - 2.3.0.0

        I then mounted a Flex Gecko, EFR32FG12 in my case, onto a Wireless Started Kit Mainboard (BRD4001A). After that, I connected it to the PC using the provided USB cable.

        Simplicity Studio recognized a Flex Gecko connected to a WSTK and displayed the link to examples from the Flex SDK (see Figure 1).

        Figure 1 - Initial Setup Validation

         

        Loading a Basic Flex SDK Example

        As a starting point, I decided to go with the "RAIL: Simple RAIL without HAL" example from the Flex SDK.

        You can find this by expanding the list of projects under the "Silicon Labs Flex SDK Examples" link:

        Figure 2 - Flex SDK Examples Link

         

        Then find and click the example shown in Figure 3 to add it to your workspace:

        Figure 3 - RAIL: Simple RAIL without HAL Example

         

        After the example loads on your workspace, you might get a notice as shown in Figure 4. Just click "OK".

        Figure 4 - Auto upgrade notice

         

        You will then be presented with simple_rail_without_hal.isc opened where you can configure RAIL. In my case, I left everything in its default values and simply clicked on "Generate" as shown in Figure 5.

        Figure 5 - RAIL Project Configuration

         

        At this point, you should now be set with a basic Flex Gecko example that builds and runs. However, I did find that the default project settings have compiler optimization set to "Optimize for size (-Os)" which will eventually make debugging the project rather difficult. Therefore, I switched optimizations to "None (-O0)".

        Figure 6 - Compiler Optimizations

         

        Adding Micrium OS to the Workspace

        Now that you have a basic Flex Gecko example that builds and runs, let's go ahead and start adding the Micrium OS source files into the workspace.

        First, locate the Micrium OS directory, it should be in:

        C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.3\platform\micrium_os

         

        Now drag and drop the "micrium_os" folder into your project (simple_rail_without_hal) in Simplicity Studio. When doing this, make sure that you have "Copy files and folders" selected before clicking "OK" as shown in Figure 7.

        Figure 7 - Adding Micrium OS Folder to Project

         

        You will then have to remove all the unnecessary files that get added with Micrium OS (this was tedious).

        Here's how your "micrium_os" folder should end up looking:

        Figure 8 - Micrium OS Necessary Files

         

        Finally, the compiler needs to know where to look for the header files so we have to add two compiler include paths to the project settings:

        "${workspace_loc:/${ProjName}/micrium_os}"
        "${workspace_loc:/${ProjName}/micrium_os/cfg}"
        Figure 9 - Micrium OS Compiler Include Paths

         

        Configuring Micrium OS

        Now that you have Micrium OS as part of your project, let's go ahead and make some minor adjustments to the default Micrium OS configuration.

        1. Open rtos_description.h located in your project under "micrium_os/cfg/"
        2. Replace the contents of the file with one below:
        /*
        *********************************************************************************************************
        *                                             EXAMPLE CODE
        *********************************************************************************************************
        * Licensing:
        *   The licensor of this EXAMPLE CODE is Silicon Laboratories Inc.
        *
        *   Silicon Laboratories Inc. grants you a personal, worldwide, royalty-free, fully paid-up license to
        *   use, copy, modify and distribute the EXAMPLE CODE software, or portions thereof, in any of your
        *   products.
        *
        *   Your use of this EXAMPLE CODE is at your own risk. This EXAMPLE CODE does not come with any
        *   warranties, and the licensor disclaims all implied warranties concerning performance, accuracy,
        *   non-infringement, merchantability and fitness for your application.
        *
        *   The EXAMPLE CODE is provided "AS IS" and does not come with any support.
        *
        *   You can find user manuals, API references, release notes and more at: https://doc.micrium.com
        *
        *   You can contact us at: https://www.micrium.com
        *********************************************************************************************************
        */
        
        /*
        *********************************************************************************************************
        *
        *                                           RTOS DESCRIPTION
        *
        *                                      CONFIGURATION TEMPLATE FILE
        *
        * File : rtos_description.h
        *********************************************************************************************************
        */
        
        /*
        *********************************************************************************************************
        *********************************************************************************************************
        *                                               MODULE
        *********************************************************************************************************
        *********************************************************************************************************
        */
        
        #ifndef  _RTOS_DESCRIPTION_H_
        #define  _RTOS_DESCRIPTION_H_
        
        
        /*
        *********************************************************************************************************
        *********************************************************************************************************
        *                                             INCLUDE FILES
        *********************************************************************************************************
        *********************************************************************************************************
        */
        
        #include  <common/include/rtos_opt_def.h>
        
        
        /*
        *********************************************************************************************************
        *********************************************************************************************************
        *                                       ENVIRONMENT DESCRIPTION
        *********************************************************************************************************
        *********************************************************************************************************
        */
        
        #define  RTOS_CPU_SEL                                       RTOS_CPU_SEL_ARM_V7_M
        
        #define  RTOS_TOOLCHAIN_SEL                                 RTOS_TOOLCHAIN_GNU
        
        #define  RTOS_INT_CONTROLLER_SEL                            RTOS_INT_CONTROLLER_ARMV7_M
        
        
        /*
        *********************************************************************************************************
        *********************************************************************************************************
        *                                       RTOS MODULES DESCRIPTION
        *********************************************************************************************************
        *********************************************************************************************************
        */
        
                                                                        /* ---------------------- KERNEL ---------------------- */
        #define  RTOS_MODULE_KERNEL_AVAIL
        
        
        /*
        *********************************************************************************************************
        *********************************************************************************************************
        *                                             MODULE END
        *********************************************************************************************************
        *********************************************************************************************************
        */
        
        #endif                                                          /* End of rtos_description.h module include.            */
        

         

        Modifying main.c

        We'll be making modifications to the default main.c generated by the "RAIL: Simple RAIL without HAL" example.

        Micrium OS requires the following include paths in main.c so go ahead and add them as shown below:

        #include  <cpu/include/cpu.h>
        #include  <kernel/include/os.h>
        #include  <common/include/common.h>
        #include  <common/include/rtos_utils.h>
        #include  <common/source/kal/kal_priv.h>  /* Private file, use should be limited */

         

        We'll be modifying main.c to initialize Micrium OS and create a start task. For that, you'll need to specify a task stack size and a priority. We typically do this by defining them as constants and passing those in the call to OSTaskCreate().

        The start task also requires its own Stack and Task Control Block (OS_TCB) as well as its function prototype. Therefore, add the following to main.c:

        #define  START_TASK_PRIO              21u
        #define  START_TASK_STK_SIZE         512u
                                                                        
        static  CPU_STK  StartTaskStk[START_TASK_STK_SIZE];  /* Start Task Stack. */
        static  OS_TCB   StartTaskTCB;                       /* Start Task TCB.   */
        
        static  void  StartTask (void  *p_arg);

         

        Here's the body of the StartTask function where the kernel tick gets initialize and as well as the Common module. Note that the function includes an infinite loop at the end with a time delay of 1 second. This is done to yield CPU time to other tasks that are or will eventually run on your system. You can copy and paste the following in your main.c:

        static  void  StartTask (void  *p_arg)
        {
          RTOS_ERR    err;
          CPU_INT32U  cpu_freq;
          CPU_INT32U  cnts;
        
          /* Prevent compiler warning. */
          PP_UNUSED_PARAM(p_arg);                                     
        
          /* Determine SysTick reference freq. */
          cpu_freq =  SystemCoreClockGet();
          /* Cal. SysTick counts between two OS tick interrupts. */
          cnts     = (cpu_freq / (CPU_INT32U)KAL_TickRateGet());
        
          /* Init uC/OS periodic time src (SysTick). */
          OS_CPU_SysTickInit(cnts);
        
        #if (OS_CFG_STAT_TASK_EN == DEF_ENABLED)
          /* Initialize CPU Usage. */
          OSStatTaskCPUUsageInit(&err);
          /* Check error code. */
          APP_RTOS_ASSERT_DBG((RTOS_ERR_CODE_GET(err) == RTOS_ERR_NONE), ;);
        #endif
        
        #ifdef CPU_CFG_INT_DIS_MEAS_EN
          /* Initialize interrupts disabled measurement. */
          CPU_IntDisMeasMaxCurReset();
        #endif
        
          /* Call common module initialization example. */
          Common_Init(&err);
          APP_RTOS_ASSERT_CRITICAL(err.Code == RTOS_ERR_NONE, ;);
        
          while (DEF_ON) {
        	  /* Delay Start Task execution for 1000 OS Ticks from now. */
              OSTimeDly(1000, OS_OPT_TIME_DLY, &err);
              /* Check error code. */
              APP_RTOS_ASSERT_DBG((RTOS_ERR_CODE_GET(err) == RTOS_ERR_NONE), ;);
          }
        }

         

        Finally, let's modify main() to initialize the CPU, re-assign interrupt handlers as kernel-aware, initialize the kernel, create the Start Task, and start the OS. Here's how main() should end up looking:

        int main(void)
        {
          uint32_t vtorAddress = SCB->VTOR;
          CPU_FNCT_VOID * vtor = (CPU_FNCT_VOID *)vtorAddress;
          RTOS_ERR  err;
        
          CPU_Init();
        
          /* Re-assign previous interrupt handlers as kernel-aware */
          for (uint32_t i = CPU_INT_EXT0; i < CPU_INT_EXT0 + EXT_IRQ_COUNT; i++) {
            CPU_IntSrcHandlerSetKA(i, vtor[i]);
          }
        
          /* Initialize the Kernel. */
          OSInit(&err);
          /* Check error code. */
          APP_RTOS_ASSERT_DBG((RTOS_ERR_CODE_GET(err) == RTOS_ERR_NONE), 1);
        
          /* Create the Start Task. */
          OSTaskCreate(&StartTaskTCB,
                       "Start Task",
                        StartTask,
                        DEF_NULL,
                        START_TASK_PRIO,
                       &StartTaskStk[0],
                       (START_TASK_STK_SIZE / 10u),
                        START_TASK_STK_SIZE,
                        0u,
                        0u,
                        DEF_NULL,
                       (OS_OPT_TASK_STK_CLR),
                       &err);
          /* Check error code. */
          APP_RTOS_ASSERT_DBG((RTOS_ERR_CODE_GET(err) == RTOS_ERR_NONE), 1);
        
          /* Start the kernel. */
          OSStart(&err);
          /* Check error code. */
          APP_RTOS_ASSERT_DBG((RTOS_ERR_CODE_GET(err) == RTOS_ERR_NONE), 1);
        
          return (1);
        }

         

        You are now set to build and run the project. You can put a breakpoint on the Start Task inside the while loop and notice that you'll be hitting that every second (or as specified by the delay you configure in OSTimeDly()).

        Please do understand that this is a very basic guide that resembles more a hack rather than an official solution from Silicon Labs. Hopefully, Micrium OS can be part of the Flex SDK in the future, but in the meantime, this is a start.

        I hope this was useful to you. Feel free to post any comments or questions regarding this blog post.

      • Simplify Low-Power, Cloud-Connected Development

        Lance Looper | 02/54/2018 | 08:24 AM

        For the upcoming Embedded World tradeshow in Nuremberg, Germany, the Silicon Labs MCU team is showing off some unique ways to ease the challenges of developing cloud-connected applications. The demo consists of the EFM32 Giant Gecko 11 MCU, which is running Micrium OS and connects to Amazon Web Services via the new XBee3 cellular module from Digi International.

         

        This particular demo is quite simple – a closed-loop system with an MCU monitoring a temp sensor and controlling a fan. However, the real-world use cases that these building blocks and tools can scale to serve are much more profound.

        For example, many smart city applications including bridge sensors, parking meters, waste management sensors, and others often consist of portable sensor devices that require seamless long-range connectivity to the cloud. They may be battery powered with user demands of 10+ year battery life. They may have lots of sensor inputs and extra features like button inputs and local displays. Finally, they might need to be designed quickly, but with a long field-upgradeable lifetime in mind. These are the types of applications that this demo speaks to, with Micrium OS, Giant Gecko 11, and Digi’s XBee3.

        Micrium OS is running on the MCU and helps modularize the application functions. It’s helping the MCU maintain communication with the cellular module, monitor the temp sensor, drive the TFT display, and update control settings when local push buttons are pressed. By using Micrium, these various pieces can easily be divided and coded in parallel without having to worry about any messy integration at the end. In fact, this is exactly what the Embedded World demo team did – three different development teams in three different cities built the demo, and Micrium was the underlying glue that made it seamlessly come together.

        Another challenge being addressed here is the connectivity piece. As devices are now adding wireless connectivity, there are lots of hurdles to clear: RF design in some cases, FCC certifications, understanding wireless networking, security, and more. Not only does Silicon Labs offer homegrown, low power SoCs and modules, but now Digi helps add simple cellular connectivity. The Digi XBee3 is a plug-and-play NB-IoT module that has built-in security and is pin-compatible with 3G and LTE-M modules. It’s programmable via MicroPython and comes pre-certified so developers can focus more on the application itself.

        This brings us to the developer’s main focus, the application. The Giant Gecko 11 is a new 32-bit energy friendly microcontroller from Silicon Labs, and our the most capable yet. It helps simplify complex, cloud-connected applications with its large on-chip memory (2MB/512kB), lots of flexible sensor interfaces, SW and pin compatibility with other EFM32 MCUs, and unique low power capability to help prolong battery life. For example, not only does Giant Gecko 11 allow for autonomous analog and sensing in “Stop Mode” (1.6 uA), but it also has Octal SPI interface for external data logging, which could be used to reduce cellular transmission duty cycling.

        There is one more unique offering in this demo. Considering that cellular connectivity might not be the solution for all IoT applications, the SW compatibility of Giant Gecko 11 and all EFM32s with Silicon Labs Wireless Geckos makes it easy to migrate to another wireless SoC or module, if needed. For example, some use cases and markets may use NB-IoT (such as this demo), while others might need their own proprietary sub-GHz solution (Flex Gecko).

        For more information about what we’re doing at Embedded World, click here: https://www.silabs.com/products/wireless/internet-of-things.