Skip to content

Create custom-target-porting.md #1130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions docs/porting/custom-target-porting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# Porting Mbed OS to a custom board

If you are designing a board similar to an existing Mbed Enabled board, you can use target inheritance to configure your board to meet your needs. You can extend an existing MCU port with a `custom_target.json` file and by adding source files that complete a port outside of `mbed-os`.

To do this, you need:

- The new board you are designing.
- Configuration details for the existing board.
- Experience using the command-line.

## Extending an existing MCU target configuration

As an example, consider a situation in which you are creating a new board based on an existing Mbed Enabled board. This tutorial considers a new board called ImaginaryBoard that is based on NRF52840.

ImaginaryBoard is the same as the standard NRF52840 development kit, but you want to remove some unused features, such as AnalogIn, and change the way some pins are connected.

1. Choose a board in Mbed OS that your board can inherit from.

If that existing board follows one of the recommended inheritance patterns, such as Family -> MCU -> Board, then it makes it simple to just inherit the MCU target information and add your own board information. In some cases, you may need to inherit a family or board and add or replace configurations accordingly.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maclobdell What's a family? Do we have more information about this?
I see we have https://os.mbed.com/docs/mbed-os/v5.13/reference/adding-and-configuring-targets.html, but it only talks about parents and children. Are there other family members?


In this example, there is an MCU target configuration in `mbed-os/targets/targets.json` that the new board can inherit from. It is called MCU_NRF52840.

Below is a short summary of the MCU target. For simplicity, areas have been omitted.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which areas?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maclobdell Can you answer this?


From `mbed-os/targets/targets.json`:

```
"MCU_NRF52840": {
"inherits": ["Target"],
"components_add": […],
"core": "Cortex-M4F",
"macros": […],
"features": […],
"device_has": […],
"extra_labels": […],
"config": {…},
"overrides": {…},
"OUTPUT_EXT": "hex",
"supported_toolchains": ["GCC_ARM", "ARM", "IAR"],
"public": false,
"detect_code": ["1101"],
"bootloader_supported": true
}
```

For reference, the standard NRF52840 development kit configuration is below. It inherits from the MCU target.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in the inheritance you introduced, this is a board, right? It's easier to use the same word here, I think.


```
"NRF52840_DK": {
"supported_form_factors": ["ARDUINO"],
"inherits": ["MCU_NRF52840"],
"release_versions": ["5"],
"device_name": "nRF52840_xxAA"
},
```

In this example, the new board is similar to the NRF52840 development kit.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this line really part of this bullet?


1. Instead of making edits within `mbed-os`, create a `custom_target.json` file, and put it in a directory alongside `mbed-os`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why, actually? How does that make my life easier?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maclobdell Can you answer this?


For example:

```
{
"IMAGINARYTARGET": {
"inherits": ["MCU_NRF52840"],
"release_versions": ["5"],
"device_name": "nRF52840_xxAA",
"detect_code": ["1234"],
"device_has_remove": ["ANALOGIN"],
“components_remove”: ["QSPI"]
}
}
```

The new board target configuration inherits the MCU target, then follows similar configurations to the development kit, including specifying it should build with Mbed OS 5. Also, it uses `device_name nRF52840_xxAA`, which matches the CMSIS pack for that device. The `detect_code` is a unique ID that identifies the board to the Mbed OS test tools.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand detect_code. Is it something I pick at random, or do I need to get that value from somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maclobdell Can you answer this?


<span class="notes">**Note:** Contact the Arm Mbed team to get a unique ID, especially if you plan to have your board coexist with other Mbed Enabled boards while running automated tests.</span>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, is that the detect_code? Then maybe break it out of line 72 so that it more clearly goes with a comment.


1. The new ImaginaryBoard board does not use AnalogIn, and it does not have a Quad SPI. Remove those.

1. AnalogIn is an Mbed OS HAL driver, which the MCU target added using `device_has`. Remove it with `device_has_remove`.
1. Similarly, the MCU target added QSPI using `components_add`. Remove it with `components_remove`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I maybe see a before and after of all this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maclobdell Can you answer this?


1. Add `device_has_remove` to disassociate the AnalogIn driver from your target.

1. (Optional) You can also use `device_has_add` to add additional drivers.

<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. Please see the drivers in the [Porting targets]../porting/porting-targets.html) section for more details.</span>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er... that's not a very detailed comment.

1. (Optional) Similarly, you can use `features_add`, `features_remove`, `components_add`, `components_remove`, `macros_add` and `macros_remove`.

## Configuring the code directory and folders

The target source code directory should follow a structure similar to that of the target configuration.

For example, in the `mbed-os/targets` folder, the directories follow this pattern:

```
mbed-os
|_targets
|_TARGET_NORDIC <- MCU VENDOR
| |_TARGET_NRF5x <- MCU FAMILY #1
| |_TARGET_NRF52 <- MCU FAMILY #2
| |_TARGET_MCU_NRF52840 <- MCU
| |_TARGET_NRF52840_DK <- Board
```

This example adds your own board, inherits files from the MCU Family and MCU folders and adds your own board files.

1. Create a new directory called `TARGET_IMAGINARYBOARD`. Place this folder at the top level of your project.

It should look something like this:

```
custom_target.json
TARGET_IMAGINARYBOARD
mbed-os
```

1. Now, place files for the board.

The following are typical files that are included for a board:

`device.h`, `PeripheralNames.h`, `PeripheralPins.c` and `PinNames.h`.

Some boards might also require files such as `mbed_overrides.c` or clock configuration files if they aren’t included at a higher level.

In the case of the NRF52840, a derivative board only requires `device.h` and `PinNames.h`:

- `device.h` provides device-specific includes.
- `PinNames.h` sets macros for pins that define their function.

1. Copy these files from `TARGET_NRF52840_DK` to `TARGET_IMAGINARYBOARD` and modify. For example, in `PinNames.h`, if the ImaginaryBoard is using I2C but connected to different signals than the NRF52840_DK, change the I2C pin macro defines from:

```
I2C_SDA0 = p26,
I2C_SCL0 = p27,
```

to

```
I2C_SDA0 = p46,
I2C_SCL0 = p47,
```

With the target configuration set and files added, it is ready to compile.

1. Using Mbed CLI, run the command:

```
mbed compile -m ImaginaryBoard -t <toolchain>
```

When successful, it compiles, links and generates a .bin or .hex file.

### Additional notes

- Many boards also use the `extra labels` configuration option to include directories in a build. Often this feature is used to include Family and MCU target directories instead of target inheritance.
- Unless your board has an Mbed Enabled debug interface, you need a method of flashing the memory on your board.

## Further reading

For more information about configuring boards, go to [adding and configuring targets](../reference/adding-and-configuring-targets.html).

### Todo:

- Need to test and confirm this is working for a few different platform types.
- What happens if you inherit a board config and provide a duplicate file such as PinNames.h?
- Need to test and make a note if macro add doesn’t work with macro remove in the same tree