6. Platform

The MicroEJ platform for i.MX RT595 EVK Rev. C1 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 i.MX RT595 EVK Rev. C1 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)}"];
}

6.1. MicroUI Drawings

MicroUI provides several basic shapes rendering (pixel-oriented). MicroEJ platform for i.MX RT595 EVK Rev. C1 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  

6.2. VG Lite Library

The i.MX RT595 EVK Rev. C1 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.

6.2.1. Native Implementation

The VGLite foundation library is implemented over the vg_lite native library which uses the GCNanoLiteV GPU of the i.MX RT595 EVK Rev. C1.

Note

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

6.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.

6.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 boundig box.
  • VectorFontPainter.drawCharNative(...): draws a character.
  • VectorFont.charWidthNative(...): computes the width (in pixels) of the character boundig box.
  • LinearGradient.initNative(...): allocates a new gradient in memory.
  • LinearGradient.closeNative(...): closes the gradient resource.

6.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).

6.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.

6.4. Power Management

The MicroEJ platform for i.MX RT595 EVK Rev. C1 has been optimized to consume few power when the MicroEJ application is in pause. In other words, as soon as the MicroEJ application is not doing any work (drawings, calculations, etc.), the MicroEJ platform enters in low power mode.

Note

The power optimizations only concern CPU consumption. Peripherals like display have not been managed and keep consuming power when the CPU is sleeping.

6.4.1. Power Modes

i.MX RT595 provides several power optimization modes: Active, Sleep, Deep sleep, Deep power down, and Full deep power-down. The MicroEJ platform for i.MX RT595 EVK Rev. C1 is using the Deep sleep mode. This mode considers:

  • To statically power off the peripherals that are never used (including never used memory banks),
  • To switch to Sleep when RTOS is idle,
  • To configure which peripherals and memory banks have to be maintained active during deep sleep,
  • To determine the wake-up source(s),
  • To reduce external PMIC VDDCORE voltage level while in Deep sleep mode.

6.4.2. Implementation

Power optimizations are integrated into FreeRTOS by using the tickless idle mode (see https://www.freertos.org/low-power-tickless-rtos.html). In this mode, FreeRTOS idle task can stop the tick interrupt and place the system in sleep mode. The tick interrupt is stopped for an estimated idle time that corresponds to the time to the next programmed event (e.g., time of the next programmed timer).

According to that estimated idle time and the power management context, the system is placed in Active, Sleep, or Deep sleep modes.

  • in Active mode, the tick interrupt is not suspended, and the system is kept alive. This mode is selected when the low power feature is disabled.
  • in Sleep mode, the tick interrupt is suspended, and the system enters in standard sleep mode. No peripheral is switched off, and the external PMIC keeps the VDDCORE unchanged. This mode is selected if some system peripherals manage tasks (i.e., GPU computation, FrameBuffer DMA transfer, etc.).
  • in Deep sleep mode, the tick interrupt is suspended, and the system enters in deep sleep mode. Memory banks are partially switched off (data is still retained), clocks are stopped, the system is clocked on a low-power clock and the external PMIC automatically switches to provide a lower VDDCORE.

In Sleep and Deep sleep modes, the system can be waked up by the buttons, capacitive screen touch, or an internal counter interrupt (that will trigger once the estimated idle time is reached).

Note

Initiating a debugger connection in Deep sleep mode is impossible; thus, detecting a debugger connection has been wired as a wake-up source. This brings the limitation that in debug mode, the system will not enter Deep Sleep mode but only Sleep mode when the FreeRTOS is in the idle task.

6.4.3. Application

The existing application provides three watchfaces. The Sport and Flower watchfaces continuously update the watch screen, and the system never enters in tickless idle mode (continuous animation).

The FlowerLP watchface has been developed only to refresh the screen every second. This watchface can be used to observe the impact of the tickless idle mode on power consumption.

The following chart displays the current consumption on VDDCORE while switching from the Flower watchface to the FlowerLP watchface.

../_images/current_consumption_VDDCORE.png

Note

The chart shows the general trend. The power consumption was measured on a particular i.MX RT595 EVK Rev. C1 board; it may differ between several boards. Please refer to NXP RT595 Electrical Characteristics for further information on power consumption figures.

6.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).

6.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.

6.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 FeatureInputStream:

  1. Open Java file com.microej.Demo.
  2. Comment the call to startFeatureInputStream() in main method.
  3. 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

6.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, a symbol must be updated to deactivate the associated useless memory banks to improve the low-power consumption.

  1. Open linker file /mimxrt595_freertos-bsp/projects/microej/iar/MIMXRT595Sxxxx_cm33_flash.icf.
  2. Look for symbol m_ram_end.
  3. Change its value: m_data_end instead of m_fo_end.
  4. Save the linker 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.