Search |
How to run JavaScripts with JerryScript on mbed
IntroThis is a step-by-step tutorial to demonstrate how to build the mbed OS and JerryScript together into the STM32F4 and STM32F429ZI boards. At the end of this guide you will be able to run javascript code (with power of the JerryScript) on your STM32F4 boards under mbed OS. If you immerse yourself in JerryScript you can make awesome projects, for example the first Atari game, Pong. We used STM32F4 board, shield and Raspberryi Pi 2 and obviously some led matrices for this project. So you can build an infinite number of projects, tasks… There is endless possibilites…
JerryScript is a lightweight JavaScript engine intended to run on a very constrained devices such as microcontrollers:
The engine supports on-device compilation, execution and provides access to peripherals from JavaScript. If you want to know more about the JerryScript, check out its official project site. mbed OS is an operating system which is created for mbed compatible boards. It allows your C++ applications to run on these boards by providing APIs that you can use from your application to control the hardware. The system is designed specifically for constrained devices. So, it works behind the scenes to automatically make the most of the limited hardware and network resources available. This is the first native OS support for Thread connectivity standard (single-threaded and event-driven), first inclusion of BLE. If you want know more about the details, visit this link. Yotta is a software module system for mbed OS. It is responsible for assembling the software modules that your application needs and controlling the build system to make those modules available to you. We will get into the details of it later, but what you need to understand at this point is that mbed OS applications cannot be built without yotta. Yotta combines your application code with the mbed OS code-base and any other module that which might be needed. To tell yotta what your application needs, you have to add a list of dependencies to each new application. The easiest way to add this is to describe the component mbed-drivers as a dependency of your application. For more detailed information and guides you should check out the official guide of yotta. Now, you probably see what we are up to. No? Let’s get into the details! The mbed OS allows you to run your C++ application on your board. The JerryScript is a JavaScript engine implemented in C/C++. It means the JerryScript is able to run on your board under mbed OS. So, you can parse and run any JavaScript code on your board with extended hardware and network resources. There are so many people who do not want to (or do not know how to) implement an application in C++ language, but they already know how to implement an application in JavaScript language. So, there is a solution to run your JavaScript application, script, funny code on your own board with the help of JerryScript and mbed OS. DependenciesYotta (version: 0.13.0)Yotta is a tool that ARM team building at mbed to help themselves and others build better software for C-family languages by making it easier to share and re-use software modules.Yotta is not only a command line tool but also a culture of building software components that do one thing well, declare a clear interface, and can be re-used. Yotta installing link. There are Linux, Windows and Mac guide too on the yotta website. Let's see the Linux guide to install yotta to a computer. We use Ubuntu for all these tutorials. GCCIf yotta is available on your machine, then let's check your gcc in terminal with
command. The gcc version of 5.2.1 is the recommend, we have also used this. You need a cross toolchain for it. GCC is always configured to emit binaries for a specific target. So normally the gcc which is already available on Linux has the target "i486-linux-gnu". You can't cross-compile to an ARM target using this compiler. A toolchain is a set of distinct software development tools that are linked (or chained) together by specific stages such as GCC. Optionally, a toolchain may contain other tools such as a Debugger or a Compiler for a specific programming language, such as ,C++. Quite often, the toolchain used for embedded development is a cross toolchain, or more commonly known as a cross compiler. All the programs (like GCC) run on a host system of a specific architecture (such as x86) but produce binary code (executables) to run on a different architecture (e.g. ARM). This is called cross compilation and is the typical way of building embedded software. It is possible to compile natively, running gcc on your target. So you need to install another GCC configured for that target, then GCC and the other programs normally have a prefix indicating the target: In your case the prefix is arm-none-eabi, and then you call that GCC using arm-none-eabi-gcc. You can have multiple GCC installations, they do not interact:
NOTE: To remove installed toolchain, just input "sudo apt-get remove gcc-arm-none-eabi”. Cross-compiling in general situation (in our case this options will be configured in a makefile): In your Makefile you have to make sure that the cross-compiler is used. You could use $(CC) in your Makefile, and assign it like this:
Compiler flags for Cortex-M0 are -mcpu=cortex-m0 -mthumb -mfloat-abi=soft which is by convention assigned to CFLAGS
Then a (simple) rule to compile .c to .o looks like
If you do not have ARM GCC compiler installed and you don’t have APT package handling utility, please check out this site to download GCC 5.2.1 which was tested for building JerryScript for stm boards. GITGit allows groups of people to work on the same documents (often code) at the same time, and without stepping on each other's toes. It's a distributed version control system. So you will need to have git, you can install that with
command. There is some easy tutorial to learn about how to use it
FoldersIn this tutorial we will use the following folder abbreviations.
BoardsAs we mentioned earlier in this tutorial we will use a STM32F4 board. To fully support the board you have to install software packages and learn a little bit about its usage. ST-LINKFor the boards to flash files and binaries we use ST-LINK v2. It is a linux command line program. Here is a step-by-step guide how to download and use it for our microcontrollers: First of all, you need to install dependencies. In terminal, type
Now you need to create a directory where you install the ST-LINK. We have one more dependency, the pkg-config but it's already installed in most of GNU/Linux systems. Download and build the project/sources by the following steps:
And we are ready, now if you connected the board for your computer, use the st-flash binary to flashing data to the board. This is not a necessary step, unless you don’t want to test the st-link.
You can download the file.bin test from here (this is a zipped file). The 0x0800000 is a memory code address, need to put here the first instruction of the program because the processor of the board start running here, but if you working with other board it might be different. For your information: when you use st-flash command you should be in the folder where the st-flash binary exists or use absolute or relative path. This command will result the binaries flashing to the boards. After flashing process it is recommended to restart the device. Here is a trick that makes your life easier, put this command below to your .bashrc and you can use the ‘st-flash’ command everywhere in terminal.
Sometimes the tool drop the WARN src/stlink-common.c: unknown chip id!, you can solve this problem with this 3 simple steps:
Here is some picture of that:
MinicomLater if you want to benchmark your program, you have so many option. We used ‘minicom’. Minicom is a text-based serial communication program. It is used to talk to external devices such as mobile phones, microcontrollers. Install the program with
JerryScript (commit: 73a5fd7)Repository download & makeLet's start with the JerryScript repository. Now, you have to clone the JerryScript into your local repository:
After you cloned the source from github, build a release for linux, for check everything is ok.
Building about ~10-20 seconds, if everything finished with no error, let's enter to the targets folder.
This folder contains the target board specific codes. There are a few official targets and a tools folder. So, if you need a new target go ahead and turn the page! Create new targetsWe need to create new targets to use other boards, because mbed OS does not support too much board… yet. So, we build JerryScript for the STM32F429ZI and the STM32F4 boards.The first one is easier, because ARM supports this board. The second one is more difficult, because there is no support, but it is not impossible. Let’s start with the easier. New target for STM32F429ZILet's create a new target for STM32F429ZI board. We have a source repository for this board: here. Clone this repository into the current (jr/targets/) folder. The repository contains the source code for the target. Check readme for the details.
Now you have a new target source. Let's see what we’ve got in this repository.
Let's see in order the source folder:
New target for STM32F4This board is also supported, but more things have to be done with this compared to STM32F429ZI target. Fortunately they are just a few target specific dependency problems. Let’s fix this. First of all, you have to enter into your targets folder.
We have a separate repository for this target. So, you can simply clone our repository into this folder.
You have to enter the mbedstm32f4 folder:
Now, you have to select the yotta target. This board has not been supported yet (as I mentioned before), but there is an early target implementation for this. So, type the following command into the terminal:
Now, you have to add the main module to the yotta dependencies for mbed OS. This is the mbed-drivers module. So, just type the following command into the terminal:
This command will install the mbed-drivers module, and some other module for your target, e.g.: uvisor-lib, ualloc, cmisi-core, … if you want to know more about this modules, please visit the official mbed OS GitHub page. So, now you have an incorrect yotta dependency tree, because two board specific definitions are missing. You have to add the following modules:
Add them manually. These modules will define the missing headers. Let’s see the first module, the hal-st-stm32f407vg one. You have to enter the root of the mbed’s hal module.
Now, you have to open the mbed-hal-st-stm32f4 module json file. Open the module.json file with favorite editor, and you have to add the following lines to the targetDependencies block:
It should look like this:
Let’s see the second module. Go to the cmsis-core folder:
There is a module.json file again, which is describe some information for this module (like before). You have to open an editor this file. After you opened this, you have to add the following lines into the targetDependencies block:
it should look like:
After you finished, go back to the target root folder, and execute the update:
Note: if you run into a module version error after modified the modules tree, you have to check the mbed-hal-st-stm32f407vg module.json file’s dependencies block. The correct uvisor-lib version is “>=1.0.2”. It should look like this:
Now dependencies are fixed. If you want to compare STM32F4 and STM32F429ZI dependency tree, just go back to the ($TARGET) folder, and run the yotta ls command.
JerryScript & mbed buildHere is the tutorial to build JerryScript, end of the tutorial we make a little program which blinking the board’s leds. So, keep going on the tutorial. :) If the yotta, gcc and st-link are working fine, let's see how to build JerryScript for the board. There is a Makefile.mbedstm32f429i file in the cloned target source. You have to go back to the JerryScript root folder.
First, clean the build:
Then, you have to run the makefile with the jerry rule. The jerry rule * creates the build folder in the targets/mbedstm32f429i/ * builds the JerryScript to the build folder, JerryScript/build*** * copy the **jerry libraries into the targets/mbedstm32f429i/libjerry/
Let’s create the mbed binary. To achieve this you have to convert the JavaScript application (the main.js and the blink.js in the ($TARGET)/js/) to C language. This is gonna be easy, because there is a python script in the ($JERRY_TARGETS)/tools folder for this. This python script create a C header file which is contains your JavaScript code (without comment and whitespace) as String. You can use this script with the following command:
The C file will be generated at ($TARGET)/source folder as jerry_targetjs.h. Then you have to build yotta.
Or, you can do this manually: You have to enter the ($TARGET) folder.
Then you have to select the correct target for the yotta. Target descriptions allow yotta to compile the same code for different target platforms (different desktop operating systems, or different embedded devices). Each target description contains information both about how to run the compiler to compile (or cross-compile), and configuration information describing the hardware or environment that the target represents.
You are able to add some optional module to yotta. It is very easy, just type this into the terminal:
Help: The yotta modules list is available here. You can find a module by name, description or keywords. Then, you have to build the yotta manually with this command:
Note:The executable file is generated to ($JERRY_TARGETS)/($TARGET)/build/($YOTTA_TARGET)/source/jerry.bin. JerryScript flashing to the boardIf you want to test the application, you have to flash the binary to the board. If you configured the ST-LINK correctly, just type the following command into the terminal:
Or, if you do not want to do this, just pick the shorter way:
At this point, you have to wait until the led near the USB port stop blinking. When it is done reset the board and LED1 will blink in every seconds. How to blink program worksAll .js files in js folder are executed, with main.js in first order. The sysloop() function in main.js is called periodically in every 100msec via the jerry_loop() and the js_loop() functions from JerryScript engine.
The sysloop() then calls blink() in blink.js which blinks the LED in every second. Benchmark testsLet’s see in action the JerryScript and mBedOS together. Performance, code size and memory benchmark tests. PerformanceIf you are up to do some benchmarking, you have so many options, we used ‘minicom’ for this (what you already have installed if you read the ##Minicom article). We use an USB-TTL for the communication, so if you want to reproduce our process, you need to have a similar device. For STM32F4 board we connected the pin PA3 to TXD and the PA2 to RXD with breadboard jumper wire.
In the JerryScript folder ($TARGET)/yotta_target/stm32f4-disco-gcc/target.json file has the information for this. After you have connected your board to the pc enter
The result of these changes is to measure the time between the “Run rest of the .js files…” and “READY...“. Build the program with yotta and flash to the board with st-link. Now, turn on the minicom. Type ‘sudo minicom -s’ to the terminal. Configure serial port as follows:
You can leave other options as they are and quit from the options. So, you can do the following in minicom:
So, you can use the timestamps to calculate the running time difference between the first pc.printf() timestamp and second pc.printf() timestamp. SizeTo get the size of the binary files use a simple ‘size jerry’ command in terminal. The ‘jerry’ file next to the generated binary file in ($TARGET)/build/($YOTTA_TARGET)/source/. You will get the size statistic. e.g.:
MemoryThere are two options to measure and track the memory in our project. The first one is trace the mbed OS memory allocation, reallocation and free command results, and the second one is the JerryScript memory statistics. So, let’s see them in order: mbed OS memory traceIt is possible to turn on mbed OS builtin memory trace module. The ualloc module can be used for this, but you have to do some additional changes to enable. Let’s see how we did! Navigate to the yotta_targets folder. It assume the current folder is the JerryScript root folder.
Edit target.json:
You have to add the following lines into the config block. These lines will be turn on the memory trace in the ualloc module. This is a temporary solution, the ARM team really want to find a better way for this.
If you want to flash your program into the board, just follow the next few steps.
When you alloc, realloc or free a memory space, you will get a simple log message, or a simple error message if something is not okay. e.g.:
Note: If you do not receive the trace message when you running your program on the board, you have to check the ualloc module, it might be outdated or modified. Please check the ARM team ualloc module repository, and check the current state of this module. If your module is outdated, you have to update it! Just go to the ($TARGET) folder, and run the following command:
Or you can still change the source code of ualloc module manually :). JerryScript mem-statOkay, now let’s see how you can enable the memory statistic in JerryScript. This is a little bit longer than the mbed OS memory trace solution. First of all, navigate to the target folder. It assumes the current folder is the JerryScript root folder.
Edit Makefile.($TARGET):
You have to add the following option to the
It should look like:
You have to modify the jerry block too. You will find the jerry block around the 30th line. There is a make command with two arguments and ends with .external suffix. Change the .external suffix to the external-mem_stats. It should look like:
Then after the make command, there are three cp commands. You have to modify all of them. These cp command will copy the jerry core libs into our targets libjerry folder. In the first cp command, you have to change the external keyword to the external-mem_stats.
In the second and the third cp command, you have to do almost the same. Add the -mem_stats keyword after the lib$(TYPE).
When you finish, it should look like:
We have done with that! Now, we have to change something in the source files. This is the ($TARGET)/source folder.
Next, open the jerry_run.cpp file with an editor and modify the jerry_init flags in the jerry_init function. So, ...
There is a jerry_flag_t flags = JERRY_FLAG_EMPTY; command. Modify the JERRY_FLAG_EMPTY value to the JERRY_FLAG_MEM_STATS value.
Save and close the jerry_run.cpp file and open the main.cpp with an editor. In this file, you have to add the js_exit() call after the jerry_loop() call, because of the memory statistic does not show up by default. The memory statistic will run after the js engine stop working. We did the followings in the main.cpp:
Now, you have to go back to the JerryScript root folder and build jerry again!
If the Jerry build finished with no error, run js2c to convert your javascript code into c code, build yotta and flash the binary to your board!
So, when the js is finished with no error on your board, you will get a memory statistic report in the terminal! e.g.:
NOTE:
If the JerryScript memory statistic does not print any value, you have to go to the definition of the mem-stat printf (you will find this in EpilogueWe hope you like this guide! At first it may seem tough, but if you do every steps we mentioned it shouldn't be so hard to get involved in JerryScript and mbed OS. If you have any question or comment, just leave a comment below! |
Monthly archive
|
Gus (not verified) - 02/15/2019 - 01:34
Thanks for the article!
Are the any recent updates to running Jerryscript on STM32?
Post new comment