The ConnectCore 8M Nano is a surface mount device (SMD) module that must be assembled on user-designed carrier boards. Users often redesign carrier boards and may also offer multiple configuration options of those boards, thus reaching a wider market.
For example, your company designs a carrier board that goes to market as version 1. Later, you redesign the carrier board to add a new user button and some LEDs, and introduce a new power regulator. This becomes version 2. Your company decides to sell two different variants of version 2 in order to reach different markets. Carrier board ID=1 is fully populated. Carrier board ID=2 is the same board but with fewer components, as it does not assemble Ethernet, USB, or audio chip. Then you redesign the carrier board again to improve the layout and fix some issues with an external controller, moving some buttons and changing some GPIO lines in the process. This becomes version 3. Your company still creates two variants (ID=1, ID=2) of the board.
While certain changes to the design of the carrier board (different carrier board version) do not affect the software—for example, moving a button or a connector, some carrier board redesigns do require changes to the software—for example, enabling a GPIO that powers a new chip on the board.
Similarly, different variants of the same carrier board and version (different carrier board ID) may require changes to the software—for example, not enabling Ethernet PHY if you don’t assemble one.
For these reasons, it is convenient to store both the carrier board version and carrier board ID in non-volatile media. You can then add conditional code in the bootloader (or in the operating system) to make the same software run on different versions and variants of the carrier board.
Programming Board ID and Board version
For the ConnectCore 8M Nano Development Kit, Digi uses U-Boot’s protected environment to store the board’s version and ID.
Variable | Description | Flags |
---|---|---|
|
Carrier board ID |
write-once |
|
Carrier board version |
write-once |
Programming the carrier board version and/or ID is optional. However, Digi’s BSP in U-Boot and the Linux kernel may contain conditional code for the ConnectCore 8M Nano Development Kit and its different versions.
To program the board ID and board version you must set these variables in U-Boot:
=> setenv board_id <id>
=> setenv board_version <version>
Variables with write-once flag are protected after being set for the first time and will not be overwritten by They will also keep their value after updating U-Boot. |
Carrier board version and ID in U-Boot
Banner
Digi programs the board version and board ID of ConnectCore 8M Nano SOMs when assembled in Digi carrier boards:
-
The board version depends on the version of the PCB.
-
The board ID is assigned to each Digi product based on the SOM:
ConnectCore 8M Nano Development Kit does not have a predefined board ID |
The board version and the board ID appear in the U-Boot banner:
Board version 2, ID undefined
On stand-alone SOMs, Digi does not program these parameters and the U-Boot banner displays Undefined board version
and Undefined board ID
warning messages.
Environment variables
You can use board_id
and board_version
variables in scripts to perform different actions.
Boot script
Find an example on Digi Embedded Yocto U-Boot boot script in meta-digi layer.
Conditional programming based on carrier board version and/or ID
U-Boot
Digi’s U-Boot contains platform functions get_carrierboard_version()
and get_carrierboard_id()
which read the carrier board version and ID from the non-volatile media.
You can use these values to program conditional code in U-Boot, like in this example:
static void my_function(void)
{
unsigned int board_id = get_carrierboard_id();
unsigned int board_version = get_carrierboard_version();
if (board_id == 1) {
if (board_version == 1) {
/* do this */
} else if (board_version > 1) {
/* do that */
}
} else if (board_id == 2}
/* more differences */
}
}
Linux kernel
The carrier board version and ID are populated by U-Boot inside the device tree before the kernel boots. You can program conditional code by reading the board version and ID from the device tree properties, as in this example:
struct device_node *np = of_find_compatible_node(NULL, NULL,
"digi,ccimx8mn");
const char *board_version_str, *board_id_str;
int board_version;
int board_id;
if (!np)
return -EPERM;
if (of_property_read_string(np, "digi,carrierboard,version",
&board_version_str);
board_version = atoi(board_version_str);
if (of_property_read_string(np, "digi,carrierboard,id",
&board_id_str);
board_id= atoi(board_id_str);
/* Conditional code based on carrier board version and ID */
switch(board_id) {
case 1:
case 2:
/* code for carrier boards with ID 1 and 2 */
switch(board_version) {
case 0:
/* code for undefined board version */
break;
case 1:
/* code for carrier board version 1 */
break;
}
break;
default:
/* code for the rest of board IDs */
break;
}
From user space, you can read the carrier board version and ID from the device tree, which is exposed via the procfs:
# cat /proc/device-tree/digi,carrierboard,version
# cat /proc/device-tree/digi,carrierboard,id
You can use the value of these properties to program conditional code in scripts or applications.