Best practice for building firmware using Yocto - yocto

I have a working Yocto build system based on the rocko branch that is generating images for an ARM-based target board. One of the chips on this board is a small ARM-based micro-controller that is separate to the main CPU. It needs to be loaded with a firmware image that I have to build.
It would be easy to make a recipe to build this microcontroller firmware. It requires an ARM cross compiler and then some special compiler options to control the code generation (for cortex-m4 + thumb etc). The trouble is, if I setup a normal recipe, it will assume that I'm building something for the target ARM architecture, which is a different type of ARM needing different code generation options. I can of course have the firmware Makefile override the cross-compile environment that is provided for the target system and have the Makefile just produce the binary firmware image.
But this will result in a package that is nominally for the target ARM architecture, but which contains a binary blob intended to be flashed onto a chip on the target board.
So my question is, how should I make a recipe for firmware that will execute on a totally different architecture to the MACHINE that the yocto build is ultimately for?
It seems like I need to create a recipe that builds specially for the micro-controller and is therefore different in some way to normal target recipes.

Multiconfig may help you. One of the use case is that you want to build image for board which consists of FPGA and ARM core, this is somehow similar to your use case.
Quoting release notes of morty (2.2), it was introduced there:
Basic support for multi-configuration builds. For example, this enables building for more than one MACHINE at a time, which may be useful if you have a board with two separate SoCs on it, each with their own OS, but you want to target both in the same build.
I didn't try it yet, but the documentation for rocko is here: https://www.yoctoproject.org/docs/2.4/mega-manual/mega-manual.html#platdev-building-targets-with-multiple-configurations
You basically define two machine configuration files, define them in BBMULTICONFIG variable and run bitbake with multiconfig:<configuration>: prefix for target when needed.

You need to create a bbclass, that will change the necessary variables for you, and inherit it in your recipe. Let's take as an example nativesdk.bbclass. Your newarch.bbclass file will look something like:
CLASSOVERRIDE = "class-newarch"
PACKAGE_ARCH = "newarch"
PACKAGE_ARCHS += "newarch"
TARGET_ARCH = "newarch"
TARGET_CC_ARCH = "newarch"
TARGET_LD_ARCH = "newarch"
TARGET_AS_ARCH = "newarch"
TARGET_CPPFLAGS = "..."
TARGET_CFLAGS = "..."
TARGET_CXXFLAGS = "..."
TARGET_LDFLAGS = "..."
CPPFLAGS = "..."
CFLAGS = "..."
CXXFLAGS = "..."
LDFLAGS = "..."

Related

How does VARIABLE_*_something works? in Yocto

I'm trying to build my own yocto_meta-layer based on the imx6ulevk and in ./meta-fsl-bsp-release/imx/meta-sdk/conf/distro/include/fsl-imx-preferred-env.inc I found something weird:
PREFERRED_PROVIDER_virtual/kernel_mx6ul = "linux-imx"
PREFERRED_PROVIDER_virtual/kernel_mx6sll = "linux-imx"
PREFERRED_PROVIDER_virtual/kernel_mx7 = "linux-imx"
So i was wondering what does the last *_word (i.e. PREFERRED_PROVIDER_virtual/kernel_*) means?
a) Does it is a way to set a virtual/kernel parser depending on the machine?
b) If [a] is yes, how do i know which name to put? or what part of the machine_name.conf i need to choose?
PREFERRED_PROVIDER_<recipe-name>_<machine-name> means this variable applies to mentioned recipe AND the respective MACHINE only. This is a common sighting in distro layers. In this particular case, the freescale layer is telling bitbake which Linux kernel recipe to choose depending on the MACHINE you either set in local.conf or pass via command line. More info here.
So the answer to a) is yes.
The answer to b) is that you should not bother with changing the PREFERRED_PROVIDER for the Linux kernel unless you really know what you're doing (i.e, writing a kernel recipe from scratch). Even if you have a custom board you're unlikely to change the virtual/kernel provider. You'd likely want to follow the BSP maintainer's recommendation. What you need to do is set a proper MACHINE, and the bitbake will take care of the rest.
For example if your MACHINE is mx6ul, invoking bitbake virtual/kernel is the same as bitbake linux-imx. The former is best practice, as you call that in Yocto regardless of the machine.
I'm afraid reading the docs is the best way to fully grasp Yocto. The good thing is that it's documented really well. You'd probably want to start from the development manual and the bitbake link above, before diving into the mega manual.
The suffix underscore '_' followed by a string means that the variable, PREFERRED_PROVIDER_virtual/kernel in this case is "overridden". bitbake will use this assignment when the OVERRIDES variable contains that particular string, such as "imx6ul".
Many times, if not all, the SoC architecture is set in the MACHINEOVERRIDES variable in the machine.conf, to define what the SoC is on the board. That consequently gets assigned to OVERRIDES in some yocto/bitbake recipe elsewhere.
The Conditional Syntax (Overrides) section in the bitbake manual [1] specifically talks about how this affects the variable expansion.
a.) If we were being strict with the terminology used by Yocto, it would be no. The "machine" per-se correlates to a board, such as "imx6ulevk". The overrides you have there more generally pertain to an SoC architecture (a chip). You may have many boards running the imx6ul for example. In this case it would pertain to all "machines" running that particular SoC (as defined by your machine in MACHINEOVERRIDES).
b.) Anything appearing in the colon delimited OVERRIDES variable is fair game. You can use the machine name because Yocto does in fact append the MACHINE name to it as well. But it doesn't really make sense to do that because you have a dedication machine.conf file for you to make a hard definition such as PREFERRED_PROVIDER_virtual/kernel = "something" if you really want a machine/board specific kernel selection. NXP did this in their distro layer to apply to many machines (aka boards) all at once.
Hint: to see what these variables expand out to, run bitbake -e virtual/kernel
These overrides are one of the most powerful features of bitbake. For example if you want to override the source revision of you linux-imx kernel build you can put something like SRCREV_pn-linux-imx = "something" in your local.conf. See if you can grep the recipe sources to find out how this works!
References:
[1] https://www.yoctoproject.org/docs/1.6/bitbake-user-manual/bitbake-user-manual.html#conditional-syntax-overrides

Upgrading (overriding) an entire recipe in a custom layer

I have a custom layer in project. This gets shared with colleagues.
My distro (poky) it uses a older version of alsa. This gets downloaded on initial setup of the build area. I would like to 'replace' that version of alsa with a later version and do this within my custom layer, so that they don't have to edit/replace recipes in poky.
What's the best way to do this? If I just download the newer recipe and include it in my layer (matching the file system names) will it automatically use the later version or is there something else I need to do?
The way you proceeded is the right way, you should add new recipes/bbappend files on your own layer(s), you shouldn't modify Yocto's base layers nor third-party layers by default. Nevertheless, since you want to add a newer version of an existing recipe, you should keep in mind that:
You have to check the priority of your own layer and the priority of the layer that contains the original recipe. Yocto will pick the recipe of the higher priority layer, no matter if it is a newer version or not (ignoring PV). For further information, search for BBFILE_PRIORITY in the Yocto Project Reference Manual. (You can also see a list of all configured layers along with their priorities with the command bitbake-layers show-layers)
In the case of both layers having the same priority, Yocto will build the recipe with the highest PV (you can check/set this value inside your recipe or in its filename recipename_pv.bb). Alternatively, if you wish to select another version rather than the one that is being currently built, you can just set the variable PREFERRED_VERSION_recipename = desiredPV in your distro.conf or local.conf file.

How to add xvisor support in to yocto

I am currently working on Yocto, want to integrate xvisor hypervisor into Yocto.
I wrote a recipe for xvisor, but how can I tell to the system like I am doing for
linux and uboot using PREFERRED_PROVIDER_virtual/kernel and PREFERRED_PROVIDER_u-boot
I tried with PREFERRED_PROVIDER_virtual/xvisor, but it is not taking.
How to compile the code, i.e do_compile()
According to Yocto Documentations PREFERRED_PROVIDER's usage is as below.
If multiple recipes provide an item, this variable determines which recipe should be given preference.You should always suffix the variable with the name of the provided item, and you should set it to the PN of the recipe to which you want to give precedence.
You simply cannot use PREFERRED_PROVIDERS_virtual/xvisor unless meta-virtualization layer is added.
If you want to add hypervisor support, you have to use meta-virtualization layer in your yoctobuild.
Reference to start with

Can I make an image select a machine

I have some images that are only relevant on a particular platform (let's say some are only for intel core and others are only for sabrelite).
Is it possible that the image automatically sets the MACHINE variable for the build, independently of the local.conf ?
If not, can I at least make the image refuse to build for other machines ?
I tried to do some googling but of course "yocto image selects machine" or similar requests only return generic Yocto tutorials.
Thanks.
No, an image can't influence which machine you're building for.
Background: In OpenEmbedded the concepts of a machine, an image, and a distro iare supposed to be orthogonal to each other. I.e. any image should be buildable for any combination of distro and machine. (Of course, that might not always be true in practice though).
You can make the image refuse to build by setting
COMPATIBLE_MACHINE = "macha"
in your image recipe.
Another idea, if the images are pretty similar, would be to only install the machine specific packages if the image is being built for the correct machine. This can easily be done by:
IMAGE_INSTALL_append_macha = " package1 package2"
Note the leading space in the string. (_append doesn't prepend your string with a space).
This latter part, is what is normally done. Restricting an image to a particular machine is something that's rarely done, at least in public layers.
Note: macha is the imagined name of the machine.
To add packages depending on machine, you could use the python function base_contains or base-conditional. E.G. bitbake-how-to-add-package-depending-on-machine
There is COMPATIBLE_MACHINE = " " for input in the recipe to check for compatible machine.
building-yocto-image-for-dragonboard-410c-how-to-build-chromium

Workflow for writing ARM assembly code on the iphone

I would like to begin writing ARM assembler and running it on the iPhone.
This is not with the intent of using in an app to be released to the app store - Basically I would like to solve problems on ProjectEuler using ARM and the iPhone, just for hobby and educational purposes.
How can I go about doing this? I have not been able to come up with a way get a project running using any hand written arm.
I haven't been able to find any information about how to write assembly code specifically for the iPhone, but like the other people said here, you can either:
1) write inline asm statements in C/C++/ObjC code, or
2) write standalone assembly functions in a '.s' file and simply add it in your XCode sources, or
3) write standalone assembly functions for an external assembler such as NASM. You write assembly code in a '.s' file and generate a '.o' object file using NASM and link the object file with your project in XCode.
So if you are just trying to write a few assembly instructions then inline assembler would be the easiest way, but if you plan on writing several assembly functions then I'd recommend a standalone assembly file. And if you plan on writing many assembly functions with macros and want cross-platform compatibility, etc, then I'd recommend using NASM to compile your assembly code into an object file. Because I am using the XCode gcc assembler and it is quite lacking compared to NASM. You can get NASM for free at http://www.nasm.us/
Once you have setup your assembler environment, you need to learn how to write ARM Assembly code! Because the iPhone (and many other portable devices and smartphones) use the ARM instruction set. There is a very good but old intro to ARM assembly at http://www.coranac.com/tonc/text/asm.htm.
When it comes to assembly programming, the official instruction set reference manual is usually the main source of information for everything you will write, so you should go to the ARM website and download the ARM and Thumb-2 Quick Reference Card (6 pages long) as well as the 2 full documents for your exact CPU.
For example, the iPhone 3GS and iPhone 4 both have an ARMv7-A Cortex-A8 CPU, so you can download the ARM Architecture Reference Manual ARMv7-A and ARMv7-R Edition (2000 pages long) that tells you exactly which instructions are available and exactly how they work, and the Cortex™-A8 Technical Reference Manual that explains the instruction timing, etc for your specific CPU.
You can use gcc to make asm inlines with __asm__, or just get a gnu as for arm and write code in separate files. You should have no problems with later linking them up to your project, but I'd suggest you to use c/Objective-C code to wrap up your asm stubs, as writing the whole iPhone application in assembler is somewhat hard (you need to be pretty good in ObjC runtime internals).
You might be interested in using custom Makefiles, however Xcode projects should be sufficient for most of the taks too.
Note also that there is nothing wrong with including assembly in app store submissions. It's only using frameworks that are not public they frown on.
They don't care how the binary is generated as long as it works, looks decently OK, and follows the aforementioned rule.
So, here is a quick description of how to actually include ARM asm code into an Xcode project, this is tested in Xcode versions up to 4.3. For my specific project, I wanted to define a function in ASM code saved with a filename like "decode_arm.s". I already have a C implementation of the same function that gets compiled when run under the simulator, so the conditional cpp logic here ensures that the ARM ASM code is only compiled into the project when actually compiling for the device.
// This file implements the following C functions for the ARM platform.
// Both ARM6 and ARM7 devices are supported by this implementation.
//
// maxvid_decode_c4_sample16()
#if defined(__arm__)
# define COMPILE_ARM 1
# if defined(__thumb__)
# define COMPILE_ARM_THUMB_ASM 1
# else
# define COMPILE_ARM_ASM 1
# endif
#endif
#if defined(COMPILE_ARM)
# define USE_GENERATED_ARM_ASM 1
#endif // COMPILE_ARM
#if defined(USE_GENERATED_ARM_ASM)
.section __TEXT,__text,regular
.section __TEXT,__textcoal_nt,coalesced
.section __TEXT,__const_coal,coalesced
.section __TEXT,__picsymbolstub4,symbol_stubs,none,16
.text
.align 2
.globl _maxvid_decode_c4_sample16
.private_extern _maxvid_decode_c4_sample16
_maxvid_decode_c4_sample16:
# args = 0, pretend = 0, frame = 0
# frame_needed = 1, uses_anonymous_args = 0
stmfd sp!, {r4, r5, r6, r7, lr}
add r7, sp, #12
stmfd sp!, {r8, r10, r11}
(ASM CODE HERE)
ldmfd sp!, {r8, r10, r11}
ldmfd sp!, {r4, r5, r6, r7, pc}
.subsections_via_symbols
#else
// No-op when USE_GENERATED_ARM_ASM is not defined
#endif