7. Platform

The MicroEJ platform for MIMXRT595-EVK has been built against the MicroEJ Architecture for Cortex M33 (version 7.14.0) and the UI extension pack (version 13.0.5). This extension pack provides the library MicroUI-3.0, and this library has been designed:

  • to replace a set of basic shapes renderings using a GPU instead of using software algorithms;
  • to be extended by third-party UI libraries.

The MicroEJ platform for MIMXRT595-EVK provides some additional extended UI libraries to target the GCNanoLiteV GPU:

  • VGLite : This library exposes the VGLite APIs to draw Vector Graphics. It allows drawing paths with either plain color (opaque and transparent) or gradient. It also allows applying matrix transformations dynamically to the rendered paths (translation, scale, rotation, perspective).
  • VectorFont: This library allows to draw strings using TTF fonts. The rendered text can be filled with plain color or gradient. The text baseline can follow a line or a curve.
digraph structs { rankdir=LR node [shape=record]; struct3 [label="Application |{ {Widget|MWT|MicroUI}|{VGLite Util|VGLite} | VectorFont}| Platform | {Software Algorithms|Hardware (GPU)}"]; }

7.1. MicroUI Drawings

MicroUI provides several basic shapes rendering (pixel-oriented). MicroEJ platform for MIMXRT595-EVK overrides weak implementation (which performs the drawing in software) to use the GPU. The drawings are using the vg_lite APIs (i.e. vg_lite_blit, vg_lite_draw, …). The following functions are hardware accelerated (under the circumstances):

Shapes

  • UI_DRAWING_fillRectangle
  • UI_DRAWING_fillRoundRectangle
  • UI_DRAWING_fillCircle
  • UI_DRAWING_fillEllipse
  • UI_DRAWING_fillCircleArc
  • UI_DRAWING_fillEllipseArc
  • DW_DRAWING_drawThickFadedPoint (fade == 1)
  • DW_DRAWING_drawThickFadedLine (fade == 1)
  • DW_DRAWING_drawThickFadedCircle (fade == 1)
  • DW_DRAWING_drawThickFadedCircleArc (fade == 1)
  • DW_DRAWING_drawThickFadedEllipse (fade == 1)
  • DW_DRAWING_drawThickLine
  • DW_DRAWING_drawThickCircle
  • DW_DRAWING_drawThickEllipse
  • DW_DRAWING_drawThickCircleArc

Images

  • UI_DRAWING_drawImage (image not transparent)
  • DW_DRAWING_drawFlippedImage (full image and not transparent)
  • DW_DRAWING_drawRotatedImageNearestNeighbor (image not transparent)
  • DW_DRAWING_drawRotatedImageBilinear (image not transparent)
  • DW_DRAWING_drawScaledImageNearestNeighbor (image not transparent)
  • DW_DRAWING_drawScaledImageBilinear (image not transparent)

MicroUI manages several RAW formats. A subset of these RAW formats is supported by the VG Lite blit feature:

MicroUI RAW format Bits per pixel blit compatible format
ARGB8888 32 VG_LITE_RGBA8888
RGB888 24  
RGB565 16 VG_LITE_RGB565
ARGB1555 16 VG_LITE_RGBA5551
ARGB4444 16 VG_LITE_RGBA4444
A1 1  
A2 2  
A4 4 VG_LITE_A4
A8 8 VG_LITE_A8
C1 1  
C2 2  
C4 4  
AC11 2  
AC22 4  
AC44 8  
LARGB8888 8  
LRGB888 8  

7.2. VG Lite Library

The MIMXRT595-EVK provides a native and a simulator implementation of the VGLite foundation library.

Both of these implementation support:

  • The Vector Graphics APIs:
    • vg_lite_draw
    • vg_lite_draw_grad
  • All matrix transformations.

For more detail about the VG Lite foundation library, see VG Lite Library.

Note

Clipping is managed using the MicroUI GraphicsContext setClip API.

7.2.1. Native Implementation

The VGLite foundation library is implemented over the vg_lite native library which uses the GCNanoLiteV GPU of the MIMXRT595-EVK.

Note

When a clip is applied to a MicroUI GraphicsContext, it will be internally managed using vg_lite scissor APIs.

7.2.2. Simulator Implementation

The MIMXRT595-VEE-IAR83 Virtual Device uses the Desktop rendering vector capabilities to render the MicroUI API for SVG, OpenVG, TrueType.

Note

The virtual device runs over Java2D which support vector graphics via Path2D. The default Java2D rendering quality is used, and the following information is ignored:

  • VGLite path bounding box,
  • VGLite drawing quality.

Warning

The following blending algorithms are not supported.

  • VG_LITE_BLEND_SCREEN,
  • VG_LITE_BLEND_MULTIPLY,
  • VG_LITE_BLEND_ADDITIVE.

7.3. VectorFont Library

The VectorFont add-on library contains seven native methods which are implemented on board and simulator:

  • VectorFont.init(): initializes the FreeType library which is used.
  • VectorFont.loadTrueTypeFont(...): loads the font data from the file.
  • VectorFontPainter.drawStringNative(...): draws a string.
  • VectorFontPainter.drawStringArcNative(...): draws a curved string.
  • VectorFont.stringWidthNative(...): computes the width (in pixels) of the string bounding box.
  • VectorFontPainter.drawCharNative(...): draws a character.
  • VectorFont.charWidthNative(...): computes the width (in pixels) of the character bounding box.
  • LinearGradient.initNative(...): allocates a new gradient in memory.
  • LinearGradient.closeNative(...): closes the gradient resource.

7.3.1. Native Implementation

The VectorFont native methods have been implemented in the low-level LLVECTOR_FONT library. It is in charge of the drawing algorithms: for each string’s character to draw, the corresponding glyph is extracted using the FreeType library. A transformation matrix is computed for each glyph to determine the character size and position on the screen based on the glyph metrics. A renderer module for the FreeType engine, called ftvglite, has been developed to render glyphs with the VG Lite library. The transformation matrix and color information (alpha, gradient) to apply are set to the renderer.

digraph { node [shape = box]; LL [label="LLVECTOR_FONT"]; FT [label="FreeType"]; VG [label="ftvglite"] LL -> FT [label="character", fontsize=8]; LL -> VG [label="transformations,\ncolors", fontsize=8]; FT -> LL [label="metrics", fontsize=8]; FT -> VG [label="render", fontsize=8]; }

Note

The ftvglite renderer is based on Smooth rasterizer from the FreeType project. It has been modified to use VG Lite to render glyphs with the GPU.

Here is a summary of the LLVECTOR_FONT natives:

  • VectorFont.init(): is called at application startup. It initializes the FreeType library and sets the VG Lite renderer as the font renderer.
  • VectorFont.loadTrueTypeFont(...): loads a font file from the given path and returns a handle of the allocated object. The font is loaded by the FreeType engine. A loaded font cannot be deallocated.
  • VectorFontPainter.drawStringNative(...): draws a string loading each glyph character by character by FreeType library and rendering its outline with the VG Lite engine. Kerning information is used if available to compute character advance. VG Lite matrix implementation is used to compute transformations applied to each character (translation, rotation, scaling).
  • VectorFontPainter.drawStringArcNative(...): draws a string around a circular arc. It uses almost the same techniques as drawStringNative(...) except that the transformations applied to each character are different.
  • VectorFont.stringWidthNative(...): computes the string with the same algorithm as drawStringNative(...) but without rendering.
  • VectorFontPainter.drawCharNative(...): draws a character loading its glyph with FreeType library and rendering its outline with the VG Lite engine. VG Lite matrix implementation is used to compute transformations applied to the character (translation, rotation, scaling).
  • VectorFont.charWidthNative(...): computes the character with the same algorithm as drawCharNative(...) but without rendering.
  • LinearGradient.initNative(...): allocates a new VG Lite gradient in memory.
  • LinearGradient.closeNative(...): closes the gradient resource.

Note

FreeType is a free font engine written in C which supports many vector font formats. At the moment, the VectorFont the library only supports TrueType fonts (TTF).

7.3.2. Simulator

The implementation in the simulator relies on Java2D API, which natively supports TrueType fonts and gradient colors. The drawString methods (and the equivalent drawChars) directly use Graphics2D.drawChars from Java 2D API to render text. The curved text implementation follows the same algorithm as the C native implementation and uses the VG Lite Library implementation in the simulator to manage transformations. Antialiasing is enabled on text rendering for drawString and on global rendering for drawStringArc.

  • VectorFont.init(): does nothing on simulator.
  • VectorFont.loadTrueTypeFont(...): loads a font file from the given path and returns a handle of the allocated object. It creates a new java.awt.Font with the given size, stored in a map to be retrieved by its handle.
  • VectorFontPainter.drawStringNative(...): draws a string loading each glyph character by character directly using Graphics2D.drawChars from Java 2D API. Text antialiasing is set with RenderingHints.VALUE_TEXT_ANTIALIAS_ON.
  • VectorFontPainter.drawStringArcNative(...): draws a string around a circular arc. It uses almost the same techniques as drawStringNative(...) except that for each character, it extracts its shape and applies transformations with the transformation matrix from VG Lite Java API. The shape is then drawn with Graphics2D.fill. Antialiasing is applied to shapes (RenderingHints.VALUE_ANTIALIAS_ON).
  • VectorFont.stringWidthNative(...): computes the string width as the sum of all its characters’ width.
  • VectorFontPainter.drawCharNative(...): draws a character by extracting its shape and applying the given transformation matrix. The shape is then drawn with Graphics2D.fill. Antialiasing is applied to the shape (RenderingHints.VALUE_ANTIALIAS_ON).
  • VectorFont.charWidthNative(...): returns the character bounding box width.
  • LinearGradient.initNative(...): allocates a new instance of java.awt.LinearGradientPaint.
  • LinearGradient.closeNative(...): releases the gradient reference.

7.4. Network

7.4.1. Overview

The MicroEJ Platform provides a WiFi network service. It requires the connection of a Silicon Labs WF200 WiFi Expansion Kit (WF200 board) on the MIMXRT595-EVK board.

Once the WF200 board is connected to the MIMXRT595-EVK board, the MicroEJ application can use it.

The application uses the WiFi network service to connect an NTP server and update the watch date and time.

7.4.2. WF200 Board

The WF200 Expansion Kit board is developed by Silicon Labs.

It is connected to the MIMXRT595-EVK on the Non-Standard Arduino I/F connectors J27, J28, J29, J30 with a Nucleo Interposer board(v1.0 or v2.0). The Nucleo Interposer board can be requested from Silicon Labs with the WF200 board.

The NXP i.MX RT595 communicates with the WF200 devices using an SPI interface. The two switches on the WF200 board must be configured this way:

  • Power source select switch: On-Board LDO.
  • Host interface select switch: SPI.
../_images/WF200_board.png

NXP i.MX RT595 to WF200 signals connection table:

WF200 pin WF200 Rasp. Pi Conn. Nucleo Interposer V1.0 Nucleo Interposer V2.0 EVK RT595 RT595
SPI_MOSI 19 J6_14 J6_14 J28_4 PIO5_1
SPI_MISO 21 J6_12 J6_12 J28_5 PIO5_2
SPI_SCLK 23 J6_10 J6_10 J28_6 PIO5_3
SPI_CS 24 J6_16 J6_16 J28_3 PIO5_0
SPI_WIRQ 36 J6_18 J6_18 J28_2 PIO4_29
GPIO_WIRQ 31 J6_20 J6_20 J28_1 PIO4_28
GPIO_WUP 32 J4_4 J4_2 J27_7 PIO4_26
RESETn 33 J4_2 J4_1 J27_8 PIO4_27

The BSP automatically detects if a WF200 board is connected to the MIMXRT595-EVK board. If the WF200 board is not available, the FreeRTOS network tasks are not started, and the application behaves as if there was no network support.

If the MicroEJ Application does not use the network library, the MicroEJ Platform network code is not used (not linked in the binary file) even if a WF200 board is connected.

The WF200 connects a WiFi Access Point using credentials provided by the MicroEJ application.

7.4.3. Application

The MicroEJ Application uses a TimeService to define the date and time. The TimeService can be either a NetTimeService or the standard MicroEJ TimeService.

The NetTimeService requests the date and time to an NTP server. The standard MicroEJ Time Service requests the date and time from the MicroEJ Platform.

The NetTimeService induces a larger RAM size, a larger footprint, and extra MCU execution time. The application has been developed to isolate the NetTimeService in a dedicated module. If this module is not used (not included in the com.microej.demo.watch.vglite module.ivy file), the RAM size, FLASH size, MCU execution time are reduced.

The default NTP server is ntp.ubuntu.com:123. Any other NTP server can be used.

The WiFi Access Point credentials are hardcoded in the NetTimeService class. They have to be updated before running the MicroEJ Application.

7.4.4. Implementation

By default, the NetTimeService is enabled in the application. The WiFi Access Point credentials still need to be provided.

Default credentials can be used, but a WiFi Access Point must be created as explained in WiFi Default Access Point.

These steps must be followed to configure the NetTimeService in the application:

  1. Ensure that the com.microej.demo.watch.ntp project is imported into MicroEJ SDK.
  2. Ensure that the com.microej.demo.watch.ntp module dependency is included in the com.microej.demo.watch.vglite module.ivy file.
  3. Set the Access Point Credentials in the NetTimeService.java file.
  4. Set the NTP server in the NetTimeService.java file.
  5. Run Demo(Emb) launcher in MicroEJ SDK.
  6. Connect and configure the WF200 as explained in section WF200 Board.
  7. Build, link and deploy as usual.

On application startup, the connection to the WiFi Access point is performed, and if it is successful, an NTP request is made to the NTP server. It will update the date and time of the watchface. The watch hands are automatically moved to the new time position.

7.4.5. WiFi Default Access Point

The default WiFi Access Point SSID is RT595_demo, and this is a WPA2 type Access Point that requires the password MicroEJ_Corp.

This WiFi Access Point can be created using the HotSpot/Network sharing capability of an Android/IOS smartphone.

The following steps will create such Access Point:

  1. Open the Settings app.
  2. Select Wireless & Networks section.
  3. Choose Tethering & Portable Hotspot.
  4. Choose the Set Up WiFi Hotspot item to give the hotspot a name or SSID that must be RT595_demo.
  5. Select WPA2 as the security mode.
  6. Set password to MicroEJ_Corp.
  7. Enable the WiFi Hotspot.

Once this Access Point is enabled, the application should be able to connect it and update the time and date from an NTP server.

7.4.6. Limitations

Using the NetTimeService brings some limitations to the watch demo:

  • the boot time is increased as the MCU needs to initialize the WF200 device and the Network BSP stack.
  • The Network BSP stack induces regular activity to monitor the different Network application message boxes. It has some effects on power consumption, even with the FlowerLP watchface.
  • The watchfaces framerate could be slightly reduced during NTP requests.

7.4.7. Simulator

The simulator manages the MicroEJ Net library.

When the application runs on the simulator with the NetTimeService enabled, the WiFi Configuration mock windows pops up.

../_images/wifi_configuration_mock.png

A new WiFi Access Point can be registered and saved. It will be available after a restart of the simulator.

The WiFi Access Point configuration can also be manually modified from the wifi/wificonfig.properties file.

Warning

The simulator WiFi Configuration mock can not be used over a VPN network.

7.4.8. Disable Network

These steps must be followed to disable the NetTimeService in order to reduce the application footprint:

  1. Comment out the com.microej.demo.watch.ntp module in the com.microej.demo.watch.vglite module.ivy file.
  2. (Optional) Resize the core.memory.immortal.size to 256 in build/common.properties file then apply that modification in the launchers.
  3. Empty the Configuration -> Wi-Fi -> Wi-Fi configuration file field of the Demo (Sim) launcher.
  4. Run Demo(Emb) launcher in MicroEJ SDK.
  5. Build, link and deploy as usual.

7.5. Mono-Sandbox Firmware

The platform, the BSP, and the main application are designed to build a MicroEJ Multi-Sandbox Firmware (see Kernel Developer Guide). This chapter describes how to build a Mono-Sandbox Firmware instead of a Multi-Sandbox Firmware.

The main advantage is to reduce the RAM footprint. Indeed the Multi-Sandbox Firmware requires some large buffers (see Limitations). Consequently, the required memory banks must remain active, which prevents reducing the power consumption (see Power Management).

Note

The Mono-Sandbox Firmware format prevents installing additional watchfaces during the main application execution (see Compile Additional Watchface).

7.5.1. Mono-Sandbox Platform

A Mono-Sandbox Firmware can be built against a Multi-Sandbox Platform. However, a Multi-Sandbox Platform requires implementing the low-level API of the Multi-Sandbox module (LLKERNEL_impl.h), which becomes useless in the case of Mono-Sandbox Firmware.

  1. Open properties file /mimxrt595_freertos-configuration/module.properties.
  2. Look for the property com.microej.platformbuilder.module.multi.enabled.
  3. Change its value to false.
  4. Rebuild the platform (see Platform Build).

Note

The Mono-Sandbox Platform stubs the Kernel & Features library. A RuntimeException is thrown when a Kernel & Features API is called. However, this is not critical; the application will keep running.

7.5.2. Mono-Sandbox Application

The wearable application and the watchfaces have been designed to be Multi-Sandbox compatible using Kernel & Features library. This chapter does not describe how to remove the Kernel & Features library dependency: the application can run even if Kernel & Features API’s implementation throws some exceptions at runtime.

Run the main application on the simulator of the new platform (see Build the Demo). An exception is thrown on application startup; however, the application keeps running.

=============== [ Initialization Stage ] ===============
=============== [ Converting fonts ] ===============
=============== [ Converting images ] ===============
=============== [ Launching on Simulator ] ===============
Exception in thread "FeatureFinalizer" java.lang.RuntimeException
   at java.lang.Throwable.fillInStackTrace(Throwable.java:82)
   at java.lang.Throwable.<init>(Throwable.java:32)
   at java.lang.Exception.<init>(Exception.java:14)
   at java.lang.RuntimeException.<init>(RuntimeException.java:14)
   at com.is2t.kf.KernelNatives.getNextStoppedFeatureToUpdate(KernelNatives.java:167)
   at com.is2t.kf.FeatureFinalizer.run(FeatureFinalizer.java:38)
   at java.lang.Thread.runWrapper(Thread.java:387)
Waiting for an application to be available
[WF Registry] Adding SportWatchface
[WF Registry] Adding FlowerWatchface
[WF Registry] Adding FlowerLPWatchface
[WF Registry] Starting SportWatchface

To prepare the compatibility with the Mono-Sandbox BSP, the main application must be very slightly modified. It consists to not call the automatic features loader/installer service FeatureLoaderService:

  1. Open Java file com.microej.Demo.

  2. Comment the FeatureLoaderService registration in the kernelServiceRegistry. The import block is automatically updated (the imports com.microej.demo.watch.util.services.FeatureLoaderService and com.microej.service.FeatureLoaderServiceImpl are removed) :

    // [...]
    import com.nxp.rt595.util.PowerManagementHelper;
    import com.microej.demo.watch.util.services.ActivityService;
    import com.microej.demo.watch.util.services.HeartRateService;
    // [...]
    import com.microej.service.DefaultTimeService;
    import com.microej.service.HeartRateServiceImpl;
    // [...]
    
    public static void main(String[] args) {
       // [...]
       kernelServiceRegistry.register(PowerService.class, new PowerServiceImpl());
       kernelServiceRegistry.register(StepsService.class, new StepsServiceImpl());
       kernelServiceRegistry.register(ActivityService.class, new ActivityServiceImpl());
       // kernelServiceRegistry.register(FeatureLoaderService.class, new FeatureLoaderServiceImpl());
       // [...]
    }
    
  3. Open Java file com.nxp.rt595.util.PowerManagementHelper.

  4. Comment the lines with startService(FeatureLoaderService.class); and stopService(FeatureLoaderService.class);. The import block is automatically updated (the import com.microej.demo.watch.util.services.FeatureLoaderService is removed) :

// [...]
import com.microej.demo.watch.util.KernelServiceRegistry;
import com.microej.demo.watch.util.services.ActivityService;
import com.microej.demo.watch.util.services.HeartRateService;
import com.microej.demo.watch.util.services.NotificationService;
// [...]

private static void applyPerfProfile(int profile) {

   // Start/Stop services depending of profile
   switch (profile) {
   case PERF_PROFILE_MAX_PERFS:

      startService(StepsService.class);
      startService(HeartRateService.class);
      startService(PowerService.class);
      startService(NotificationService.class);
      startService(ActivityService.class);
      //startService(FeatureLoaderService.class);
      break;

   case PERF_PROFILE_POWER_SAVING:

      stopService(StepsService.class);
      stopService(HeartRateService.class);
      stopService(PowerService.class);
      stopService(NotificationService.class);
      stopService(ActivityService.class);
      //stopService(FeatureLoaderService.class);
      break;

   default:
      throw new IllegalArgumentException();
   }

   // [...]
}
  1. Build the application as usual.

If these steps are not performed, some errors will occur during the IAR linker step:

Error[Li005]: no definition for "Java_com_microej_kernel_FeatureInputStream_isFeatureAvailable" [referenced from [...]\mimxrt595_freertos-bsp\
projects\microej\platform\lib\microejapp.o]
Error[Li005]: no definition for "Java_com_microej_kernel_FeatureInputStream_init" [referenced from [...]\mimxrt595_freertos-bsp\projects\microej\
platform\lib\microejapp.o]
Error[Li005]: no definition for "Java_com_microej_kernel_FeatureInputStream_readIntoArray" [referenced from [...]\mimxrt595_freertos-bsp\
projects\microej\platform\lib\microejapp.o]
Error[Li005]: no definition for "Java_com_microej_kernel_FeatureInputStream_closeFeature" [referenced from [...]\mimxrt595_freertos-bsp\
projects\microej\platform\lib\microejapp.o]
Error while running Linker

7.5.3. Mono-Sandbox BSP

As described in BSP Architecture, the kf group in the IAR project implements the low-level APIs of Multi-Sandbox Firmware and the automatic features loader/installer FeatureInputStream.

First, disable these useless low-level API implementations:

  1. Open IAR project.
  2. Right-click on group source / kf.
  3. Open the Options... window.
  4. Check Exclude from build.
  5. Click on OK.

Multi-Sandbox Firmware’s large buffers are now useless. IAR does not allocate these buffers during the linker step because there are not referenced in the BSP. However, the ram partition used are still powered on by default . The lowpower/src/power_manager.c must be updated to improve the low-power consumption.

Some calls to the feature loader bsp API must also be commented out.

  1. Open linker file /mimxrt595_freertos-bsp/projects/microej/lowpower/src/power_manager.c.
  2. Comment out all calls to set_ram_partitions_power() with &m_fo_start, &m_fo_end or &m_kf_start, &m_kf_end arguments.
  3. Comment out calls to USART_Feature_Loader_Enable(); and USART_Feature_Loader_Disable();.
  4. Save the power_manager.c file.

Finally, build the BSP as usual and deploy the application on board. The same exception than the simulator is thrown; the application ignores it and keeps running.