mbed-os

Fork of mbed-os by erkin yucel

Committer:
xuaner
Date:
Thu Jul 20 14:26:57 2017 +0000
Revision:
1:3deb71413561
Parent:
0:f269e3021894
mbed_os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 # Adding and configuring mbed targets
elessair 0:f269e3021894 2
elessair 0:f269e3021894 3 mbed uses JSON as a description language for its build targets. The JSON description of mbed targets can be found in `tools/targets.json`. To better understand how a target is defined, we'll use this example (taken from `targets.json`):
elessair 0:f269e3021894 4
elessair 0:f269e3021894 5 ```
elessair 0:f269e3021894 6 "TEENSY3_1": {
elessair 0:f269e3021894 7 "inherits": ["Target"],
elessair 0:f269e3021894 8 "core": "Cortex-M4",
elessair 0:f269e3021894 9 "extra_labels": ["Freescale", "K20XX", "K20DX256"],
elessair 0:f269e3021894 10 "OUTPUT_EXT": "hex",
elessair 0:f269e3021894 11 "is_disk_virtual": true,
elessair 0:f269e3021894 12 "supported_toolchains": ["GCC_ARM", "ARM"],
elessair 0:f269e3021894 13 "post_binary_hook": {
elessair 0:f269e3021894 14 "function": "TEENSY3_1Code.binary_hook",
elessair 0:f269e3021894 15 "toolchains": ["ARM_STD", "ARM_MICRO", "GCC_ARM"]
elessair 0:f269e3021894 16 },
elessair 0:f269e3021894 17 "device_name": "MK20DX256xxx7",
elessair 0:f269e3021894 18 "detect_code": ["0230"]
elessair 0:f269e3021894 19 ```
elessair 0:f269e3021894 20
elessair 0:f269e3021894 21 The definition of the target called **TEENSY3_1** is a JSON object. The properties in the object are either "standard" (understood by the mbed build system) or specific to the target.
elessair 0:f269e3021894 22
elessair 0:f269e3021894 23 # Standard properties
elessair 0:f269e3021894 24
elessair 0:f269e3021894 25 This section lists all the properties that are known to the mbed build system. Unless specified otherwise, all properties are optional.
elessair 0:f269e3021894 26
elessair 0:f269e3021894 27 ## inherits
elessair 0:f269e3021894 28
elessair 0:f269e3021894 29 The description of a mbed target can "inherit" from one of more descriptions of other targets. When a target **A** inherits from another target **B** (**A** is the _child_ of **B** and **B** is the _parent_ of **A**), it automatically "borrows" all the definitions of properties from **B** and can modify them as needed (if you're familiar with Python, this is very similar with how class inheritance works in Python). In our example above, `TEENSY3_1` inherits from `Target` (most mbed targets inherit from `Target`). This is how `Target` is defined:
elessair 0:f269e3021894 30
elessair 0:f269e3021894 31 ```
elessair 0:f269e3021894 32 "Target": {
elessair 0:f269e3021894 33 "core": null,
elessair 0:f269e3021894 34 "default_toolchain": "ARM",
elessair 0:f269e3021894 35 "supported_toolchains": null,
elessair 0:f269e3021894 36 "extra_labels": [],
elessair 0:f269e3021894 37 "is_disk_virtual": false,
elessair 0:f269e3021894 38 "macros": [],
elessair 0:f269e3021894 39 "detect_code": [],
elessair 0:f269e3021894 40 "public": false
elessair 0:f269e3021894 41 }
elessair 0:f269e3021894 42 ```
elessair 0:f269e3021894 43
elessair 0:f269e3021894 44 Since `TEENSY3_1` inherits from `Target`:
elessair 0:f269e3021894 45
elessair 0:f269e3021894 46 - `core` is a property defined both in `TEENSY3_1` and `Target`. Since `TEENSY3_1` redefines it, the value of `core` for `TEENSY3_1` will be `Cortex-M4`.
elessair 0:f269e3021894 47 - `default_toolchain` is not defined in `TEENSY3_1`, but since it is defined in `Target`, `TEENSY3_1` borrows it, so the value of `default_toolchain` for `TEENSY3_1` will be `ARM`.
elessair 0:f269e3021894 48
elessair 0:f269e3021894 49 A target can add properties that don't exist in its parent(s). For example, `OUTPUT_EXT` is defined in `TEENSY3_1`, but doesn't exist in `Target`.
elessair 0:f269e3021894 50
elessair 0:f269e3021894 51 It's possible to inherit from more than one target. For example:
elessair 0:f269e3021894 52
elessair 0:f269e3021894 53 ```
elessair 0:f269e3021894 54 "ImaginaryTarget": {
elessair 0:f269e3021894 55 "inherits": ["Target", "TEENSY3_1"]
elessair 0:f269e3021894 56 }
elessair 0:f269e3021894 57 ```
elessair 0:f269e3021894 58
elessair 0:f269e3021894 59 In this case, `ImaginaryTarget` inherits the properties of both `Target` and `TEENSY3_1`, so:
elessair 0:f269e3021894 60
elessair 0:f269e3021894 61 - the value of `ImaginaryTarget.default_toolchain` will be `ARM` (from `Target`)
elessair 0:f269e3021894 62 - the value of `ImaginaryTarget.OUTPUT_EXT` will be `hex` (from `TEENSY3_1`).
elessair 0:f269e3021894 63 - the value of `ImaginaryTarget.core` will be `null` (from `Target`, since that's the first parent of `ImaginaryTarget` that defines `core`).
elessair 0:f269e3021894 64
elessair 0:f269e3021894 65 Avoid using multiple inheritance for your targets if possible, since it can get pretty tricky to figure out how a property is inherited if multiple inheritance is used. If you have to use multiple inheritance, keep in mind that the mbed target description mechanism uses the old (pre 2.3) Python mechanism for finding the method resolution order:
elessair 0:f269e3021894 66
elessair 0:f269e3021894 67 - look for the property in the current target.
elessair 0:f269e3021894 68 - if not found, look for the property in the first target's parent, then in the parent of the parent and so on.
elessair 0:f269e3021894 69 - if not found, look for the property in the rest of the target's parents, relative to the current inheritance level.
elessair 0:f269e3021894 70
elessair 0:f269e3021894 71 For more details about the Python method resolution order, check for example [this link](http://makina-corpus.com/blog/metier/2014/python-tutorial-understanding-python-mro-class-search-path).
elessair 0:f269e3021894 72
elessair 0:f269e3021894 73 ## core
elessair 0:f269e3021894 74
elessair 0:f269e3021894 75 The name of the ARM core used by the target.
elessair 0:f269e3021894 76
elessair 0:f269e3021894 77 Possible values: `"Cortex-M0"`, `"Cortex-M0+"`, `"Cortex-M1"`, `"Cortex-M3"`, `"Cortex-M4"`, `"Cortex-M4F"`, `"Cortex-M7"`, `"Cortex-M7F"`, `"Cortex-A9"`
elessair 0:f269e3021894 78
elessair 0:f269e3021894 79 ## public
elessair 0:f269e3021894 80
elessair 0:f269e3021894 81 Some mbed targets might be defined solely for the purpose of serving as an inheritance base for other targets (as opposed to being used to build mbed code). When such a target is defined, its description must have the `public` property set to `false` to prevent the mbed build system from considering it as a build target. An example is the `Target` target shown in a previous paragraph.
elessair 0:f269e3021894 82
elessair 0:f269e3021894 83 If `public` is not defined for a target, it defaults to `true`.
elessair 0:f269e3021894 84
elessair 0:f269e3021894 85 Note that unlike other target properties, **the value of `public` is not inherited from a parent to its children**.
elessair 0:f269e3021894 86
elessair 0:f269e3021894 87 ## macros, macros_add, macros_remove
elessair 0:f269e3021894 88
elessair 0:f269e3021894 89 The macros in this list will be defined when compiling mbed code. The macros can be defined with or without a value. For example, the declaration `"macros": ["NO_VALUE", "VALUE=10"]` will add these definitions to the compiler's command line: `-DNO_VALUE -DVALUE=10`.
elessair 0:f269e3021894 90
elessair 0:f269e3021894 91 When target inheritance is used, it's possible to alter the values of `macros` in inherited targets without re-defining `macros` completely:
elessair 0:f269e3021894 92
elessair 0:f269e3021894 93 - an inherited target can use `macros_add` to add its own macros.
elessair 0:f269e3021894 94 - an inherited target can use `macros_remove` to remove macros defined by its parents.
elessair 0:f269e3021894 95
elessair 0:f269e3021894 96 For example, in this configuration:
elessair 0:f269e3021894 97
elessair 0:f269e3021894 98 ```
elessair 0:f269e3021894 99 "TargetA": {
elessair 0:f269e3021894 100 "macros": ["PARENT_MACRO1", "PARENT_MACRO2"]
elessair 0:f269e3021894 101 },
elessair 0:f269e3021894 102 "TargetB": {
elessair 0:f269e3021894 103 "inherits": ["TargetA"],
elessair 0:f269e3021894 104 "macros_add": ["CHILD_MACRO1"],
elessair 0:f269e3021894 105 "macros_remove": ["PARENT_MACRO2"]
elessair 0:f269e3021894 106 }
elessair 0:f269e3021894 107 ```
elessair 0:f269e3021894 108
elessair 0:f269e3021894 109 the value of `TargetB.macros` will be `["PARENT_MACRO1", "CHILD_MACRO1"]`.
elessair 0:f269e3021894 110
elessair 0:f269e3021894 111 ## extra_labels, extra_labels_add, extra_labels_remove
elessair 0:f269e3021894 112
elessair 0:f269e3021894 113 The list of **labels** defines how the build system looks for sources, libraries, include directories and any other additional files that are needed at compile time. `extra_labels` can be used to make the build system aware of additional directories that must be scanned for such files.
elessair 0:f269e3021894 114
elessair 0:f269e3021894 115 If target inheritance is used, it's possible to alter the values of `extra_labels` using `extra_labels_add` and `extra_labels_remove`. This is similar to the `macros_add` and `macros_remove` mechanism described in the previous paragraph.
elessair 0:f269e3021894 116
elessair 0:f269e3021894 117 ## features, features_add, features_remove
elessair 0:f269e3021894 118
elessair 0:f269e3021894 119 The list of **features** defines what hardware a device has.
elessair 0:f269e3021894 120 This allows allowing mbed, libraries, or application source code to select between different implementations of drivers based on hardware availability, to selectively compile drivers for only the hardware that exists, or to test only the tests that apply to a particular platform.
elessair 0:f269e3021894 121
elessair 0:f269e3021894 122 If target inheritance is used, it's possible to alter the values of `features` using `features_add` and `features_remove`. This is similar to the `macros_add` and `macros_remove` mechanism described in the previous two paragraphs.
elessair 0:f269e3021894 123
elessair 0:f269e3021894 124 ## supported_toolchains
elessair 0:f269e3021894 125
elessair 0:f269e3021894 126 This is the list of toolchains that can be used to compile code for the target. The known toolchains are `ARM`, `uARM`, `GCC_ARM`, `GCC_CR`, `IAR`.
elessair 0:f269e3021894 127
elessair 0:f269e3021894 128 ## default_toolchain
elessair 0:f269e3021894 129
elessair 0:f269e3021894 130 The name of the toolchain that will be used by default to compile this target (if another toolchain is not specified). Possible values are `ARM` or `uARM`.
elessair 0:f269e3021894 131
elessair 0:f269e3021894 132 ## post_binary_hook
elessair 0:f269e3021894 133
elessair 0:f269e3021894 134 Some mbed targets require specific actions for generating a binary image that can be flashed to the target. If that's the case, these specific actions can be specified using the `post_binary_hook` property and custom Python code. For the `TEENSY3_1` target above, the definition of `post_binary_hook` looks like this:
elessair 0:f269e3021894 135
elessair 0:f269e3021894 136 ```
elessair 0:f269e3021894 137 "post_binary_hook": {
elessair 0:f269e3021894 138 "function": "TEENSY3_1Code.binary_hook",
elessair 0:f269e3021894 139 "toolchains": ["ARM_STD", "ARM_MICRO", "GCC_ARM"]
elessair 0:f269e3021894 140 }
elessair 0:f269e3021894 141 ```
elessair 0:f269e3021894 142
elessair 0:f269e3021894 143 Following this definition, the build system will call the function `binary_hook` in the `TEENSY3_1Code` class after the initial binary image for the target is generated. The definition of the `TEENSY3_1Code` class **must** exist in the *targets.py* file. Since `toolchains` is also specified, `binary_hook` will only be called if the toolchain used for compiling the code is either `ARM_STD`, `ARM_MICRO` or `GCC_ARM`. Note that specifying `toolchains` is optional: if it's not specified, the hook will be called no matter what toolchain is used.
elessair 0:f269e3021894 144
elessair 0:f269e3021894 145 As for the `binary_hook` code, this is how it looks in *targets.py*:
elessair 0:f269e3021894 146
elessair 0:f269e3021894 147 ```
elessair 0:f269e3021894 148 class TEENSY3_1Code:
elessair 0:f269e3021894 149 @staticmethod
elessair 0:f269e3021894 150 def binary_hook(t_self, resources, elf, binf):
elessair 0:f269e3021894 151 from intelhex import IntelHex
elessair 0:f269e3021894 152 binh = IntelHex()
elessair 0:f269e3021894 153 binh.loadbin(binf, offset = 0)
elessair 0:f269e3021894 154
elessair 0:f269e3021894 155 with open(binf.replace(".bin", ".hex"), "w") as f:
elessair 0:f269e3021894 156 binh.tofile(f, format='hex')
elessair 0:f269e3021894 157 ```
elessair 0:f269e3021894 158
elessair 0:f269e3021894 159 In this case, it converts the output file (`binf`) from binary format to Intel HEX format.
elessair 0:f269e3021894 160
elessair 0:f269e3021894 161 The hook code can look quite different between different targets. Take a look at the other classes in *targets.py* for more examples of hook code.
elessair 0:f269e3021894 162
elessair 0:f269e3021894 163 ## device_name
elessair 0:f269e3021894 164
elessair 0:f269e3021894 165 This property is used to pass necessary data for exporting the mbed code to various 3rd party tools and IDEs.
elessair 0:f269e3021894 166
elessair 0:f269e3021894 167 This is possible because the device name corresponds to a field in publicly hosted CMSIS packs. These packs hold target properties. [This](http://www.keil.com/pack/Keil.Kinetis_K20_DFP.pdsc) is the pdsc that contains TEENSY_31 device (MK20DX256xxx7). The device information begins on line 156. The dname (device name) field on line 156 directly corresponds to that in the Uvision5 IDE target selection window. Beginning on line 15 of `tools/export/uvision/uvision.tmpl`, target information from these packs is used to generate valid Uvision5 projects. If the device name is not found, we use a generic ARM CPU target in Uvision5.
elessair 0:f269e3021894 168 `tools/export/iar/iar_definitions.json` utilizes this device name to store information necessary to set the target in an IAR project.
elessair 0:f269e3021894 169