Skip to content

Commit d3e07c0

Browse files
author
maclobdell
committed
add new tutorial, more detailed than previous attempts
1 parent 814cef6 commit d3e07c0

File tree

1 file changed

+258
-0
lines changed

1 file changed

+258
-0
lines changed

docs/porting/custom-target-porting.md

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
# Porting Mbed OS to a custom board
2+
3+
When designing a custom board based on an existing Mbed Enabled board, you will likely need to make configuration and software changes to adapt Mbed OS to run on your new board. This is often called a software 'port'. The necessary changes may include adaptations for the unique design choices you have made for your new board, such as clocking, pin connections, and peripheral usage. This can often be accomplished by adding configuration and source files to an Mbed OS-based application project without the need to modify files within Mbed Os itself. If you don't plan to push your changes to the upstream Mbed Os repository, this simplifies your software configuration management by allowing you to keep your new files separate.
4+
5+
Mbed OS supports target inheritance, which allows you to extend an existing microcontroller (MCU) target and just add additional software and configurations required for your board. If you are using Mbed OS version 5.8 and later, you have the ability to add a file named `custom_target.json` to your project, which can store your custom target configurations without the need to modify `targets.json`.
6+
7+
This tutorial provides a quick overview on how to create a custom port using `custom_target.json`. Not all possible aspects of this process are covered. For detailed information covering all the ways you can configure targets, go to [adding and configuring targets](../reference/adding-and-configuring-targets.html).
8+
9+
## Extending an existing MCU target configuration
10+
11+
As an example, consider a situation in which you are creating a new board based on an existing Mbed Enabled board. For this tutorial, consider a new board called `ImaginaryBoard` that is based on [DISCO-L475VG-IOT01A](https://os.mbed.com/platforms/ST-Discovery-L475E-IOT01A/).
12+
13+
`ImaginaryBoard` shares most of the same features of DISCO-L475VG-IOT01A, but it does not use `AnalogOut`, `AnalogIn`, `CAN`, `USB` and some pins are connected differently on the new board.
14+
15+
Assuming you have Mbed Command Line Interface (CLI) installed, follow these steps to make the port.
16+
17+
1. (Optional) Create a new Mbed program (e.g. mbed-os-imaginary-port)
18+
19+
If you don't already have an Mbed program on your computer, at a command terminal, run this Mbed CLI command.
20+
21+
```
22+
mbed new --program mbed-os-imaginary-port
23+
24+
```
25+
This command will import 'mbed-os' from the [official Mbed OS source repository](https://github.com/armmbed/mbed-os) into a new directory called 'mbed-os-imaginary-port'.
26+
27+
Now change directories into your new project.
28+
29+
```
30+
cd mbed-os-imaginary-port
31+
```
32+
33+
1. Create a new file named `custom_targets.json` at the same level as the `mbed-os` directory.
34+
35+
Inspect the contents of `mbed-os/targets/targets.json`. For this example, search for `DISCO_L475VG_IOT01A`.
36+
37+
Copy the contents from the `DISCO_L475VG_IOT01A` section into your `custom_targets.json` file. Be sure to include brackets `{ }` sorrounding the content.
38+
39+
Then make changes for your board. For example, after making changes, the full contents look like this:
40+
41+
```
42+
{
43+
"IMAGINARYBOARD": {
44+
"components_add": ["QSPIF", "FLASHIAP"],
45+
"inherits": ["FAMILY_STM32"],
46+
"core": "Cortex-M4F",
47+
"extra_labels_add": ["STM32L4", "STM32L475xG", "STM32L475VG"],
48+
"config": {
49+
"clock_source": {
50+
"help": "Mask value : USE_PLL_HSE_EXTC (need HW patch) | USE_PLL_HSE_XTAL (need HW patch) | USE_PLL_HSI | USE_PLL_MSI",
51+
"value": "USE_PLL_MSI",
52+
"macro_name": "CLOCK_SOURCE"
53+
},
54+
"lpticker_lptim": {
55+
"help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer",
56+
"value": 1
57+
}
58+
},
59+
"overrides": { "lpticker_delay_ticks": 4 },
60+
"detect_code": ["1234"],
61+
"macros_add": [
62+
"MBED_TICKLESS",
63+
"MBED_SPLIT_HEAP"
64+
],
65+
"device_has_add": [
66+
"CRC",
67+
"TRNG",
68+
"FLASH",
69+
"QSPI",
70+
"MPU"
71+
],
72+
"device_has_remove": [
73+
"ANALOGIN",
74+
"I2CSLAVE",
75+
"I2C_ASYNCH"
76+
],
77+
"release_versions": ["2", "5"],
78+
"device_name": "STM32L475VG",
79+
"bootloader_supported": true
80+
}
81+
}
82+
```
83+
84+
Let's review the changes one by one.
85+
86+
- The board name was changed from `DISCO_L475VG_IOT01A` to `IMAGINARYBOARD` so the board can be uniquely identified.
87+
88+
- The `detect_code` was changed from `0764` to `1234`. The `detect_code` is a unique number that identifies the board to the Mbed OS test tools. This number is typically built into the debug interface.
89+
90+
- The `macros_add` section was changed to remove `USBHOST_OTHER` because USB is not used on the new board.
91+
92+
- The `device_has_add` section was changed to not add the `ANALOGOUT`, `CAN`, `USBDEVICE` drivers because those features are not used on the new board.
93+
94+
- A new section, `device_has_remove`, was added. This removes `ANALOGIN`, `I2CSLAVE`, and `I2C_ASYNCH` drivers because these features are also not used. The reason why `device_has_remove` is used in this case is because the board is inheriting from the MCU Family configuration `FAMILY_STM32`, which has those drivers added by default.
95+
96+
All the other configurations for the board are inherited from the MCU Family configuration called `FAMILY_STM32`.
97+
98+
Here are some other typical changes that might be needed.
99+
100+
- (Optional) You can also use `device_has_add` to add additional drivers.
101+
102+
<span class="notes">**Note:** If you choose to add a driver, you may have to provide the driver implementation if it is not already available for your hardware.</span>
103+
104+
- (Optional) Similarly, you can use `features_add`, `features_remove`, `components_add`, `components_remove`, `macros_add` and `macros_remove` to add/remove configurations.
105+
106+
## Configuring the target code directories
107+
108+
In some cases, the target source code directories follow a similar structure as the target configuration, but they could have a few more levels.
109+
110+
For example, in the `mbed-os/targets` folder, the target directories for DISCO_L475VG_IOT01A follow this pattern:
111+
112+
```
113+
mbed-os
114+
|_targets
115+
|_TARGET_STM <- MCU VENDOR
116+
| |_TARGET_STM32L4 <- MCU FAMILY
117+
| |_TARGET_STM32L475xG <- MCU
118+
| |_TARGET_DISCO_L475VG_IOT01A <- Board
119+
```
120+
121+
Boards typically inherit files that support the MCU, MCU family, and MCU vendor. When adding a new board, you need to add a new set of files for the board.
122+
123+
You may be wondering why there are more directory levels than target configuration levels. This is because many targets utilize the `extra_labels_add` feature in the target configuration. The following keywords `STM32L4`, `STM32L475xG`, `STM32L475VG` resolve to `TARGET_STM32L4`, `TARGET_STM32L475xG`, `TARGET_STM32L475VG` respectively. With those labels applied, these directory names get included in the build for this target.
124+
125+
1. Create a new directory called `TARGET_IMAGINARYBOARD` at the top level of your project.
126+
127+
Your directory should look something like this:
128+
129+
```
130+
custom_target.json
131+
TARGET_IMAGINARYBOARD
132+
mbed-os
133+
.mbed
134+
mbed_settings.py
135+
mbed-os.lib
136+
```
137+
138+
1. Now place source files for the board.
139+
140+
Inspect the files at `mbed-os\targets\TARGET_STM\TARGET_STM32L4\TARGET_STM32L475xG\TARGET_DISCO_L475VG_IOT01A`. You should find the following files or similar.
141+
142+
`PeripheralNames.h`, `PeripheralPins.c`, `PinNames.h`, `system_clock.c`
143+
144+
Copy the files into your new `TARGET_IMAGINARYBOARD` directory.
145+
146+
The files provide these capabilities.
147+
148+
- `PeripheralNames.h` describes the available peripherals and their base addresses
149+
- `PeripheralPins.c` describes the available pins and their association with peripherals
150+
- `PinNames.h` sets macros for pins that define their function.
151+
- `system_clock.c` vendor specific file that initializes the system and sets up the clocks
152+
153+
1. Modify the files.
154+
155+
`PinNames.h` is the most common file to be edited. For our example, the ImaginaryBoard is using I2C but connected to different supported signals. Change the I2C pin macro definitions from:
156+
157+
```
158+
I2C_SCL = D15,
159+
I2C_SDA = D14,
160+
```
161+
162+
to
163+
164+
```
165+
I2C_SCL = PC_0,
166+
I2C_SDA = PC_1,
167+
```
168+
169+
This edit is mainly for convenience if your application code uses standard I2C pin names `I2C_SDA` and `I2C_SCL`.
170+
171+
You may also choose to add or remove peripherals, add or remove pins, or change the clock frequency by editing `PeripheralNames.h`, `PeripheralPins.c`, or `system_clock.c`. In our example, for simplicity, we will not edit these files.
172+
173+
1. (Optional) Add additional files.
174+
175+
If necessary, add additional source files for drivers or middleware you have implemented for the new board. In our example, we do not have any files to add.
176+
177+
1. (Optional) Add a simple application source file for testing.
178+
179+
To confirm the software builds for the new target, add a file named `main.cpp` with the following contents.
180+
181+
```
182+
#include "mbed.h"
183+
184+
DigitalOut led1(LED1);
185+
186+
int main()
187+
{
188+
while (true) {
189+
led1 = !led1;
190+
wait_ms(500);
191+
}
192+
}
193+
```
194+
195+
This will blink an led. Just make sure LED1 is defined for the board.
196+
197+
Your directory should now look something like this:
198+
199+
```
200+
main.cpp
201+
custom_target.json
202+
TARGET_IMAGINARYBOARD
203+
mbed-os
204+
.mbed
205+
mbed_settings.py
206+
mbed-os.lib
207+
```
208+
209+
1. Compile the project.
210+
211+
With the target configuration set and files added, it is ready to compile. Run the command:
212+
213+
```
214+
mbed compile -m IMAGINARYBOARD -t <toolchain>
215+
```
216+
217+
When successful, it compiles, links and generates a .bin file (or .hex file for some other boards).
218+
219+
For example, it will print to the screen:
220+
```
221+
Image: .\BUILD\IMAGINARYBOARD\GCC_ARM\mbed-os-imaginary-port.bin
222+
```
223+
224+
1. Program the board.
225+
226+
You can test this simple example using a `DISCO-L475VG-IOT01A`. If you actually created a `ImaginaryBoard` board, you could use that too.
227+
228+
<span class="notes">**Note:** Unless your board has an Mbed Enabled debug interface, you need a method of flashing the memory on your board. </span>
229+
230+
Since the `DISCO-L475VG-IOT01A` has a Mbed Enabled debug interface (STLink in this case), we can use drag-and-drop programming to flash the board.
231+
232+
Locate the binary file and drag it onto the disk drive name for the board (e.g. `DIS_L4IOT`).
233+
234+
After the file transfer is complete, press the reset button on the board. You should see the LED blinking.
235+
236+
1. (Optional) Run automated tests.
237+
238+
With an Mbed Enabled debug interface, you can also run the Mbed OS automated tests on your port. Since a new board has a new name that is unknown to the Mbed tools, you will need to tell the tools which `detect_code` to associate it to.
239+
240+
To do this, you can use the `mbedls` `mock` command option. In our case, we are testing with a `DISCO-L475VG-IOT01A`, which has a debug interface that exposes `0764` as its detect code. If you have a new board that is using a different detect_code, such as `1234`, then use that.
241+
242+
For the `ImaginaryBoard` based on `DISCO-L475VG-IOT01A`, run this command.
243+
244+
```
245+
mbedls --mock 0764:IMAGINARYBOARD
246+
```
247+
248+
<span class="notes">**Note:** Contact the Arm Mbed team to get a unique ID if you plan to have your board coexist with other Mbed Enabled boards while running automated tests.</span>
249+
250+
Now run the tests, with the following command.
251+
252+
```
253+
mbed test -m IMAGINARYBOARD -t <toolchain>
254+
```
255+
256+
The tests should start running.
257+
258+
Now you have successfully ported Mbed OS to a new board.

0 commit comments

Comments
 (0)