ArduinoCore-mbed/mbed-os-to-arduino

414 lines
11 KiB
Bash
Executable File

#!/usr/bin/env bash
set -ef
check_tools () {
echo -n "Checking for prerequisites..."
if not hash jq &>/dev/null ; then
echo "Please, install jq."
exit 1
fi
if not hash rsync &>/dev/null ; then
echo "Please, install rsync."
exit 1
fi
echo " done."
}
mbed_new () {
echo -n "Creating MbedOS Application..."
#always work in /tmp
cd /tmp/
if [ ! -d mbed-os-program ]; then
mbed new mbed-os-program
fi
cd mbed-os-program
echo " done."
}
mbed_revision () {
echo -n "Checking out preferred 'mbed-os' version..."
if [ "$MBED_UPDATE" -eq 1 ]; then
echo -n " Updating to latest..."
set +e
mbed update
set -e
fi
if [ -n "$REMOTE_BRANCH" ]; then
echo -n " Checking out remote branch $REMOTE_BRANCH..."
# checkout the mbed-os version you prefer...
cd mbed-os
git checkout "$REMOTE_BRANCH"
cd ..
fi
if [ -n "$LOCAL_REPO" ]; then
echo -n " Linking local repo $LOCAL_REPO..."
# ... or link your local repo
if [ -d mbed-os ]; then
if [ ! -L mbed-os ]; then
rm -rf mbed-os
ln -s "$LOCAL_REPO" mbed-os
fi
fi
fi
echo " done."
}
create_mbed_program () {
echo -n "Setting up Mbed Application..."
rm -rf .mbedignore
mbed target "$BOARDNAME"
mbed toolchain GCC_ARM
cat > main.cpp << MAIN_C
#include "mbed.h"
int main() {}
MAIN_C
if [ ! -f "$ARDUINOVARIANT"/conf/mbed_app.json ]; then
echo "================================================"
echo "Please, consider creating a 'conf/mbed_app.json'"
echo "to avoid mbed-cli always recompile from scratch."
echo "================================================"
cat > mbed_app.json << MBED_APP
{
"macros": [
"MBED_HEAP_STATS_ENABLED=1",
"MBED_STACK_STATS_ENABLED=1",
"MBED_MEM_TRACING_ENABLED=1"
],
"target_overrides": {
"*": {
"platform.stdio-buffered-serial": true,
"platform.stdio-baud-rate": 115200,
"platform.default-serial-baud-rate": 115200,
"rtos.main-thread-stack-size": 32768
}
}
}
MBED_APP
fi
if [ -d "$ARDUINOVARIANT"/conf ]; then
find "$ARDUINOVARIANT"/conf/ -type f -exec cp -p '{}' . ';'
fi
echo " done."
}
apply_patches () {
if [ "$APPLY_PATCHES" -eq 1 ]; then
echo -n "Applying patches..."
if [ -d "$MBED_CORE_LOCATION"/patches ]; then
cd mbed-os
find "$MBED_CORE_LOCATION"/patches/ -type f -print0 | sort -z | xargs -t -0 -n1 git apply
cd -
fi
echo " done."
if [ "$RESTORE_GDB_INFO" -eq 1 ]; then
echo "Restoring gdb info (this increases libmbed binary size, not suitable for release)"
cd mbed-os
git checkout tools/profiles/develop.json
cd -
fi
fi
}
mbed_compile () {
echo -n "Compiling Mbed Application..."
if [ "$MBED_CLEAN" -eq 1 ]; then
echo -n "Cleaning..."
rm -rf BUILD
fi
PROFILE_FLAG=""
if [ x"$PROFILE" != x ]; then
if [ -f "$ARDUINOVARIANT/conf/profile/$PROFILE.json" ]; then
PROFILE_FLAG=--profile="$ARDUINOVARIANT"/conf/profile/$PROFILE.json
else
PROFILE_FLAG=--profile="${PROFILE}"
fi
export PROFILE=-${PROFILE^^}
fi
mbed compile $PROFILE_FLAG --source . -v \
| tee >(cat | grep 'Compile \[' >&2) | grep "Macros:" > "$BOARDNAME".macros.txt
echo " done."
}
generate_defines () {
echo -n "Generating defines..."
cut -f2 -d":" < "$BOARDNAME".macros.txt | tr ' ' '\n' | sed 's#\"#\\"#g' | sort > "$ARDUINOVARIANT"/defines.txt
echo "-DMBED_NO_GLOBAL_USING_DIRECTIVE=1" >> "$ARDUINOVARIANT"/defines.txt
MAJOR=$(echo $VERSION| cut -d'.' -f 1)
MINOR=$(echo $VERSION| cut -d'.' -f 2)
PATCH=$(echo $VERSION| cut -d'.' -f 3)
echo "-DCORE_MAJOR=$MAJOR" >> "$ARDUINOVARIANT"/defines.txt
echo "-DCORE_MINOR=$MINOR" >> "$ARDUINOVARIANT"/defines.txt
echo "-DCORE_PATCH=$PATCH" >> "$ARDUINOVARIANT"/defines.txt
if [ -f "$ARDUINOVARIANT"/variant.cpp ]; then
echo '-DUSE_ARDUINO_PINOUT' >> "$ARDUINOVARIANT"/defines.txt
fi
echo " done."
}
generate_includes () {
echo -n "Generating includes..."
find ./BUILD/"$BOARDNAME"/GCC_ARM${PROFILE}/ -type f -name '.include*' -print0 | xargs -0 cat \
| tr ' ' '\n' | tr -d '"' | sed -e 's#-I./mbed-os#-iwithprefixbefore/mbed#g' \
| sed '/^-I./d' | cat \
> "$ARDUINOVARIANT"/includes.txt
echo -n " copying to destination... "
cd mbed-os
cut -d'/' -f3- < "$ARDUINOVARIANT"/includes.txt | grep 'targets' \
| xargs -I{} find {} -maxdepth 2 -name '*.h' \
| xargs -I{} cp --parent {} "$ARDUINOCOREMBED"/
cd -
echo " done."
}
generate_flags () {
echo -n "Generating flags..."
for fl in c cxx ld; do
jq -r '.flags | .[] | select(. != "-MMD")' ./BUILD/"$BOARDNAME"/GCC_ARM${PROFILE}/.profile-${fl} \
> "$ARDUINOVARIANT"/${fl}flags.txt
if [[ $ARDUINOVARIANT == *PORTENTA* ]]; then
echo "Patching '-fno-exceptions' flag for $ARDUINOVARIANT/${fl}flags.txt"
sed -i '/-fno-exceptions/d' "$ARDUINOVARIANT"/${fl}flags.txt
set +e
HAS_OPENAMP_SECTION=`grep openamp_section "$ARDUINOVARIANT"/linker_script.ld`
set -e
if [ x"$HAS_OPENAMP_SECTION" == x ]; then
echo "Adding OpenAMP section to $ARDUINOVARIANT/linker_script.ld"
OPENAMP_SECTION=".openamp_section (NOLOAD) : {\n \
. = ABSOLUTE(0x38000000);\n \
*(.resource_table)\n \
} >RAM_D3 AT > FLASH\n \
.pdm_section (NOLOAD) : {\n \
. = ABSOLUTE(0x3800FC00);\n \
*(.pdm_buffer)\n \
} > RAM_D3\n"
if [[ $ARDUINOVARIANT == *PORTENTA*M7* ]]; then
OPENAMP_SECTION="${OPENAMP_SECTION} \
_dtcm_lma = __etext + SIZEOF(.data);\n \
.dtcm : AT(_dtcm_lma) {\n \
_sdtcm = .;\n \
*(.dtcm*)\n \
_edtcm = .;\n \
} > DTCMRAM"
fi
sed -i "s?.heap (COPY):?${OPENAMP_SECTION}\n .heap (COPY):?g" $ARDUINOVARIANT/linker_script.ld
OPENAMP_REGIONS="__OPENAMP_region_start__ = 0x38000400;\n__OPENAMP_region_end__ = 0x38000400 + LENGTH(RAM_D3) - 1K;"
sed -i "s?ENTRY(Reset_Handler)?${OPENAMP_REGIONS}\nENTRY(Reset_Handler)?g" $ARDUINOVARIANT/linker_script.ld
fi
echo "Patching linker scripts"
sed -i 's/0x8100000/CM4_BINARY_START/g' "$ARDUINOVARIANT"/linker_script.ld
sed -i 's/LENGTH = 0x200000/LENGTH = CM4_BINARY_END - CM4_BINARY_START/g' "$ARDUINOVARIANT"/linker_script.ld
sed -i 's/LENGTH = 0x1c0000/LENGTH = CM4_BINARY_START - 0x8040000/g' "$ARDUINOVARIANT"/linker_script.ld
fi
if [[ $ARDUINOVARIANT == *NANO_RP2040* ]]; then
set +e
HAS_2NDSTAGE_SECTION=`grep second_stage_ota "$ARDUINOVARIANT"/linker_script.ld`
set -e
if [ x"$HAS_2NDSTAGE_SECTION" == x ]; then
echo "Adding second stage bootloader section to Nano RP2040 Connect"
SECOND_STAGE_SECTION=".second_stage_ota : {\n \
KEEP (*(.second_stage_ota))\n \
} > FLASH"
sed -i "s?.flash_begin?${SECOND_STAGE_SECTION}\n .flash_begin?g" $ARDUINOVARIANT/linker_script.ld
fi
fi
done
echo " done."
}
generate_libs () {
echo -n "Generating libs..."
tr ' ' '\n' < ./BUILD/"$BOARDNAME"/GCC_ARM${PROFILE}/.link_options.txt | grep "\.o" | grep -v "/main\.o" \
| xargs arm-none-eabi-ar rcs ./BUILD/mbed-core-"$BOARDNAME".a
cp ./BUILD/mbed-core-"$BOARDNAME".a "$ARDUINOVARIANT"/libs/libmbed.a
cp ./BUILD/"$BOARDNAME"/GCC_ARM${PROFILE}/.link_script.ld "$ARDUINOVARIANT"/linker_script.ld
cp ./BUILD/"$BOARDNAME"/GCC_ARM${PROFILE}/mbed_config.h "$ARDUINOVARIANT"/
sed -i "s/custom_mbedtls_config.h/conf\/custom_mbedtls_config.h/" $ARDUINOVARIANT/mbed_config.h
# TODO: discover needed libraries based on compile target
#find -L . -name 'lib*.a' -exec cp '{}' "$ARDUINOVARIANT"/libs/ ';'
echo " done."
}
copy_core_files () {
echo -n "Copying generic MbedOS headers to core... "
rsync -zar --exclude="targets/" --exclude="*TEST*/" --include="*/" --include="*.h" --exclude="*" \
mbed-os/ "$ARDUINOCOREMBED"/
rsync -zar --exclude="targets/" --exclude="*TEST*/" --include="*/" --include="mstd_*" --exclude="*" \
mbed-os/ "$ARDUINOCOREMBED"/
echo " done."
}
patch_mbed_h () {
echo -n "Patching 'mbed.h'..."
if [ x`uname` == xLinux ]; then
sed -i 's?#include "platform/mbed_version.h"?#include "platform/mbed_version.h"\n#include "mbed_config.h"?g' \
"$ARDUINOCOREMBED"/mbed.h
else
ed "$ARDUINOCOREMBED"/mbed.h >/dev/null <<EOF
/#include "platform\/mbed_version.h"/
a
#include "mbed_config.h"
.
wq
EOF
fi
echo " done."
}
patch_spi_h () {
echo -n "Patching SPI headers..."
mv "$ARDUINOCOREMBED"/drivers/include/drivers/SPI.h "$ARDUINOCOREMBED"/drivers/include/drivers/SPIMaster.h
for header in mbed.h connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512SPITransportDriver.h storage/blockdevice/COMPONENT_SPIF/include/SPIF/SPIFBlockDevice.h storage/blockdevice/COMPONENT_SD/include/SD/SDBlockDevice.h; do
sed -i.bak 's#drivers/SPI\.h#drivers/SPIMaster\.h#g' "$ARDUINOCOREMBED"/$header
rm "$ARDUINOCOREMBED"/$header.bak
done
echo " done."
}
#############
# MAIN LOOP #
#############
while getopts "cuagr:b:p:" opt; do
case $opt in
c ) export MBED_CLEAN=1 ;;
u ) export MBED_UPDATE=1 ;;
a ) export APPLY_PATCHES=1 ;;
g ) export RESTORE_GDB_INFO=1 ;;
r ) export LOCAL_REPO="$OPTARG" ;;
b ) export REMOTE_BRANCH="$OPTARG" ;;
p )
MBED_CORE_LOCATION="$(cd "$OPTARG" && pwd -P)"
export MBED_CORE_LOCATION ;;
* )
echo "Unknown parameter."
exit 1
;;
esac
done
# Done with processing all the starting flags with getopts...
shift $(( OPTIND - 1 ))
if [ $# -eq 0 ] ; then
echo "Usage: $(basename $0) [-c] [-u] [-r /path/to/local/repo] [-b mbed/remote/branch] [-p /mbed/core/location] [VARIANT1:BOARD1 VARIANT2:BOARD1 VARIANT3:BOARD3 ... ]"
echo
echo " -c clean Mbed application BUILD directory"
echo " -u update to latest mbed-os release"
echo " -a apply patches"
echo " -b specify remote mbed-os branch to checkout"
echo " -r specify local mbed-os directory to link"
echo " -p specify local mbed core directory (defaults to PWD)"
echo
echo "Example:"
echo " $(basename $0) -a ARDUINO_NANO33BLE:ARDUINO_NANO33BLE CHALLENGE_PMC_R2DX:ARDUINO_NANO33BLE"
exit 0
fi
declare -A VARIANT_BOARDS
TUPLES=( "$@" )
for tuple in "${TUPLES[@]}"; do
OLD_IFS="$IFS"
IFS=":"
set -- $tuple
VARIANT_BOARDS[$1]="$2"
IFS="$OLD_IFS"
done
export MBED_CORE_LOCATION=${MBED_CORE_LOCATION:-$PWD}
export MBED_CLEAN=${MBED_CLEAN:-0}
export MBED_UPDATE=${MBED_UPDATE:-0}
export APPLY_PATCHES=${APPLY_PATCHES:-0}
export RESTORE_GDB_INFO=${RESTORE_GDB_INFO:-0}
export LOCAL_REPO=${LOCAL_REPO:-""}
export REMOTE_BRANCH=${REMOTE_BRANCH:-""}
echo
echo MBED_CLEAN=$MBED_CLEAN
echo MBED_UPDATE=$MBED_UPDATE
echo APPLY_PATCHES=$APPLY_PATCHES
echo RESTORE_GDB_INFO=$RESTORE_GDB_INFO
echo LOCAL_REPO="$LOCAL_REPO"
echo REMOTE_BRANCH="$REMOTE_BRANCH"
echo MBED_CORE_LOCATION="$MBED_CORE_LOCATION"
echo
for variant in ${!VARIANT_BOARDS[*]}; do
echo "VARIANT=$variant BOARD=${VARIANT_BOARDS[$variant]}"
done
check_tools
mbed_new
mbed_revision
for VARIANT in ${!VARIANT_BOARDS[*]}; do
export BOARDNAME="${VARIANT_BOARDS[$variant]}"
export ARDUINOVARIANT="$MBED_CORE_LOCATION"/variants/"$VARIANT"
export ARDUINOCOREMBED="$MBED_CORE_LOCATION"/cores/arduino/mbed
if [ -d "$ARDUINOVARIANT" ]; then
mkdir -p "$ARDUINOVARIANT"/libs
fi
if [ -d "$ARDUINOVARIANT"/conf/profile ]; then
export PROFILE="custom"
fi
create_mbed_program
apply_patches
mbed_compile
generate_defines
generate_includes
generate_libs
generate_flags
done
copy_core_files
patch_mbed_h
patch_spi_h
echo
echo "[$(basename $0)] MbedOS core generation ended succesfully."
echo
# TODO
# - Add include path for rpc library to envie
#
exit 0
##################
# Using Arduino as an mbed library
#
# echo -e "arduino/cores/arduino/main.cpp\n arduino/cores/arduino/mbed/\narduino/libraries/" > .mbedignore
# #add ARDUINO_AS_MBED_LIBRARY=1 to macros section in mbed_app.json
# echo "https://github.com/arduino/ArduinoCore-mbed#bf6e64771ebe20285b0364756dff856ebbc679dc" > arduino.lib