clean up makefile

- rename target sd -> flash-sd, mbr -> flash-mbr, dfu-flash -> flash-dfu
- update readme
- clean up python script, add multiprocess build
This commit is contained in:
hathach 2022-07-12 20:40:57 +07:00
parent 597dc6f0a9
commit 6c0bb9d8ec
5 changed files with 132 additions and 235 deletions

View file

@ -7,6 +7,7 @@
# - SD_HEX : to bootloader hex binary # - SD_HEX : to bootloader hex binary
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# local customization
-include Makefile.user -include Makefile.user
SDK_PATH = lib/sdk/components SDK_PATH = lib/sdk/components
@ -37,7 +38,7 @@ OUT_NAME = $(BOARD)_bootloader-$(GIT_VERSION)
MERGED_FILE = $(OUT_NAME)_$(SD_NAME)_$(SD_VERSION) MERGED_FILE = $(OUT_NAME)_$(SD_NAME)_$(SD_VERSION)
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# Tool configure # Tool Configure
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# Toolchain commands # Toolchain commands
@ -208,39 +209,46 @@ ASM_SRC = $(NRFX_PATH)/mdk/gcc_startup_$(MCU_SUB_VARIANT).S
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# src # src
IPATH += src IPATH += \
IPATH += src/boards src \
IPATH += src/boards/$(BOARD) src/boards \
IPATH += src/cmsis/include src/boards/$(BOARD) \
IPATH += src/usb src/cmsis/include \
IPATH += $(TUSB_PATH) src/usb \
$(TUSB_PATH)
# nrfx # nrfx
IPATH += $(NRFX_PATH) IPATH += \
IPATH += $(NRFX_PATH)/mdk $(NRFX_PATH) \
IPATH += $(NRFX_PATH)/hal $(NRFX_PATH)/mdk \
IPATH += $(NRFX_PATH)/drivers/include $(NRFX_PATH)/hal \
IPATH += $(NRFX_PATH)/drivers/src $(NRFX_PATH)/drivers/include \
$(NRFX_PATH)/drivers/src
IPATH += $(SDK11_PATH)/libraries/bootloader_dfu/hci_transport # sdk11 for cdc/ble dfu
IPATH += $(SDK11_PATH)/libraries/bootloader_dfu IPATH += \
IPATH += $(SDK11_PATH)/drivers_nrf/pstorage $(SDK11_PATH)/libraries/bootloader_dfu/hci_transport \
IPATH += $(SDK11_PATH)/ble/common $(SDK11_PATH)/libraries/bootloader_dfu \
IPATH += $(SDK11_PATH)/ble/ble_services/ble_dfu $(SDK11_PATH)/drivers_nrf/pstorage \
IPATH += $(SDK11_PATH)/ble/ble_services/ble_dis $(SDK11_PATH)/ble/common \
$(SDK11_PATH)/ble/ble_services/ble_dfu \
$(SDK11_PATH)/ble/ble_services/ble_dis
IPATH += $(SDK_PATH)/libraries/timer # later sdk with updated drivers
IPATH += $(SDK_PATH)/libraries/scheduler IPATH += \
IPATH += $(SDK_PATH)/libraries/crc16 $(SDK_PATH)/libraries/timer \
IPATH += $(SDK_PATH)/libraries/util $(SDK_PATH)/libraries/scheduler \
IPATH += $(SDK_PATH)/libraries/hci/config $(SDK_PATH)/libraries/crc16 \
IPATH += $(SDK_PATH)/libraries/uart $(SDK_PATH)/libraries/util \
IPATH += $(SDK_PATH)/libraries/hci $(SDK_PATH)/libraries/hci/config \
IPATH += $(SDK_PATH)/drivers_nrf/delay $(SDK_PATH)/libraries/uart \
$(SDK_PATH)/libraries/hci \
$(SDK_PATH)/drivers_nrf/delay
# Softdevice # SoftDevice
IPATH += $(SD_PATH)/$(SD_FILENAME)_API/include IPATH += \
IPATH += $(SD_PATH)/$(SD_FILENAME)_API/include/nrf52 $(SD_PATH)/$(SD_FILENAME)_API/include \
$(SD_PATH)/$(SD_FILENAME)_API/include/nrf52
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# Compiler Flags # Compiler Flags
@ -278,9 +286,6 @@ CFLAGS += \
# Suppress warning caused by SDK # Suppress warning caused by SDK
CFLAGS += -Wno-unused-parameter -Wno-expansion-to-defined CFLAGS += -Wno-unused-parameter -Wno-expansion-to-defined
# TinyUSB tusb_hal_nrf_power_event
CFLAGS += -Wno-cast-function-type
# Nordic Softdevice SDK header files contains inline assembler that has # Nordic Softdevice SDK header files contains inline assembler that has
# broken constraints. As a result the IPA-modref pass, introduced in gcc-11, # broken constraints. As a result the IPA-modref pass, introduced in gcc-11,
# is able to "prove" that arguments to wrapper functions generated with # is able to "prove" that arguments to wrapper functions generated with
@ -332,6 +337,7 @@ LIBS += -lm -lc
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# Assembler flags # Assembler flags
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
ASFLAGS += $(CFLAGS) ASFLAGS += $(CFLAGS)
#function for removing duplicates in a list #function for removing duplicates in a list
@ -356,7 +362,7 @@ INC_PATHS = $(addprefix -I,$(IPATH))
# BUILD TARGETS # BUILD TARGETS
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
.PHONY: all clean flash dfu-flash sd gdbflash gdb .PHONY: all clean flash dfu-flash flash-dfu flash-sd flash-mbr gdbflash gdb
# default target to build # default target to build
all: $(BUILD)/$(OUT_NAME).out $(BUILD)/$(OUT_NAME)_nosd.hex $(BUILD)/update-$(OUT_NAME)_nosd.uf2 $(BUILD)/$(MERGED_FILE).hex $(BUILD)/$(MERGED_FILE).zip all: $(BUILD)/$(OUT_NAME).out $(BUILD)/$(OUT_NAME)_nosd.hex $(BUILD)/update-$(OUT_NAME)_nosd.uf2 $(BUILD)/$(MERGED_FILE).hex $(BUILD)/$(MERGED_FILE).zip
@ -431,7 +437,9 @@ copy-artifact: $(BIN)
@$(CP) $(BUILD)/$(MERGED_FILE).hex $(BIN) @$(CP) $(BUILD)/$(MERGED_FILE).hex $(BIN)
@$(CP) $(BUILD)/$(MERGED_FILE).zip $(BIN) @$(CP) $(BUILD)/$(MERGED_FILE).zip $(BIN)
#------------------- Flash target ------------------- #--------------------------------------
# Flash Target
#--------------------------------------
check_defined = \ check_defined = \
$(strip $(foreach 1,$1, \ $(strip $(foreach 1,$1, \
@ -440,29 +448,29 @@ __check_defined = \
$(if $(value $1),, \ $(if $(value $1),, \
$(error Undefined make flag: $1$(if $2, ($2)))) $(error Undefined make flag: $1$(if $2, ($2))))
# erase chip
erase:
@echo Erasing flash
$(call FLASH_ERASE_CMD)
# Flash the compiled # Flash the compiled
flash: $(BUILD)/$(OUT_NAME)_nosd.hex flash: $(BUILD)/$(OUT_NAME)_nosd.hex
@echo Flashing: $(notdir $<) @echo Flashing: $(notdir $<)
$(call FLASH_CMD,$<) $(call FLASH_CMD,$<)
erase:
@echo Erasing flash
$(call FLASH_ERASE_CMD)
# flash SD only # flash SD only
sd: flash-sd:
@echo Flashing: $(SD_HEX) @echo Flashing: $(SD_HEX)
$(call FLASH_NOUICR_CMD,$(SD_HEX)) $(call FLASH_NOUICR_CMD,$(SD_HEX))
# flash MBR only # flash MBR only
mbr: flash-mbr:
@echo Flashing: $(MBR_HEX) @echo Flashing: $(MBR_HEX)
$(call FLASH_NOUICR_CMD,$(MBR_HEX)) $(call FLASH_NOUICR_CMD,$(MBR_HEX))
#------------------- Flash with NRFUTIL via DFU ------------------- # dfu with adafruit-nrfutil using CDC interface
dfu-flash: flash-dfu
# dfu using CDC interface flash-dfu: $(BUILD)/$(MERGED_FILE).zip
dfu-flash: $(BUILD)/$(MERGED_FILE).zip
@:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0)
$(NRFUTIL) --verbose dfu serial --package $< -p $(SERIAL) -b 115200 --singlebank --touch 1200 $(NRFUTIL) --verbose dfu serial --package $< -p $(SERIAL) -b 115200 --singlebank --touch 1200

View file

@ -121,45 +121,18 @@ both bootloader and the Nordic SoftDevice, you can freely upgrade/downgrade to a
You should only continue if you are looking to develop bootloader for your own. You should only continue if you are looking to develop bootloader for your own.
You must have have a J-Link available to "unbrick" your device. You must have have a J-Link available to "unbrick" your device.
Prerequisites ### Prerequisites
- ARM GCC - ARM GCC
To install for macos
```bash
brew tap ArmMbed/homebrew-formulae
brew install arm-none-eabi-gcc
brew link --overwrite arm-none-eabi-gcc # if a prior version was present
```
- Nordic's [nRF5x Command Line Tools](https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Command-Line-Tools) - Nordic's [nRF5x Command Line Tools](https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Command-Line-Tools)
- [Python IntelHex](https://pypi.org/project/IntelHex/) - [Python IntelHex](https://pypi.org/project/IntelHex/)
To build: ### Build:
``` ```
make BOARD=feather_nrf52840_express all make BOARD=feather_nrf52840_express all
``` ```
To flash the bootloader with JLink:
```
make BOARD=feather_nrf52840_express flash
```
To upgrade the bootloader using DFU Serial via port /dev/ttyACM0
```
make BOARD=feather_nrf52840_express SERIAL=/dev/ttyACM0 dfu-flash
```
To flash SoftDevice (and chip erase):
```
make BOARD=feather_nrf52840_express sd
```
For the list of supported boards, run `make` without `BOARD=` : For the list of supported boards, run `make` without `BOARD=` :
``` ```
@ -169,9 +142,41 @@ Supported boards are: feather_nrf52840_express feather_nrf52840_express pca10056
Makefile:90: *** BOARD not defined. Stop Makefile:90: *** BOARD not defined. Stop
``` ```
### Flash
To flash the bootloader (without softdevice/mbr) using JLink:
```
make BOARD=feather_nrf52840_express flash
```
If you are using pyocd as debugger, add `FLASHER=pyocd` to make command:
```
make BOARD=feather_nrf52840_express FLASHER=pyocd flash
```
To upgrade the bootloader using DFU Serial via port /dev/ttyACM0
```
make BOARD=feather_nrf52840_express SERIAL=/dev/ttyACM0 flash-dfu
```
To flash SoftDevice (will also erase chip):
```
make BOARD=feather_nrf52840_express flash-sd
```
To flash MBR only
```
make BOARD=feather_nrf52840_express flash-mbr
```
### Common makefile problems ### Common makefile problems
#### 1. `arm-none-eabi-gcc`: No such file or directory #### `arm-none-eabi-gcc`: No such file or directory
If you get the following error ... If you get the following error ...
@ -190,7 +195,7 @@ $ make CROSS_COMPILE=/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi- B
For other compile errors, check the gcc version with `arm-none-eabi-gcc --version` to insure it is at least 9.x. For other compile errors, check the gcc version with `arm-none-eabi-gcc --version` to insure it is at least 9.x.
#### 2. `ModuleNotFoundError: No module named 'intelhex'` #### `ModuleNotFoundError: No module named 'intelhex'`
Install python-intelhex with Install python-intelhex with
@ -198,8 +203,7 @@ Install python-intelhex with
pip install intelhex pip install intelhex
``` ```
#### `make: nrfjprog: No such file or directory`
#### 3. `make: nrfjprog: No such file or directory`
Make sure that `nrfjprog` is available from the command-line. This binary is Make sure that `nrfjprog` is available from the command-line. This binary is
part of Nordic's nRF5x Command Line Tools. part of Nordic's nRF5x Command Line Tools.

View file

@ -1,78 +1,73 @@
import os import os
import shutil
import glob import glob
import sys import sys
import subprocess import subprocess
import time import time
from multiprocessing import Pool
subprocess.run("rm -rf _build/", shell=True)
subprocess.run("rm -rf bin/", shell=True)
SUCCEEDED = "\033[32msucceeded\033[0m" SUCCEEDED = "\033[32msucceeded\033[0m"
FAILED = "\033[31mfailed\033[0m" FAILED = "\033[31mfailed\033[0m"
success_count = 0
fail_count = 0
exit_status = 0
build_format = '| {:32} | {:18} | {:5} | {:6} | {:6} |' build_format = '| {:32} | {:18} | {:5} | {:6} | {:6} |'
build_separator = '-' * 74 build_separator = '-' * 74
# All supported boards
all_boards = []
for entry in os.scandir("src/boards"):
if entry.is_dir():
all_boards.append(entry.name)
all_boards.sort()
#sha, version = build_info.get_version_info()
total_time = time.monotonic()
print(build_separator)
print(build_format.format('Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM'))
print(build_separator)
for board in all_boards:
bin_directory = "bin/{}/".format(board)
os.makedirs(bin_directory, exist_ok=True)
def build_board(board):
start_time = time.monotonic() start_time = time.monotonic()
make_result = subprocess.run("make -j 4 BOARD={} all".format(board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) make_result = subprocess.run("make -j BOARD={} all".format(board), shell=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
build_duration = time.monotonic() - start_time build_duration = time.monotonic() - start_time
flash_size = "-" flash_size = "-"
sram_size = "-" sram_size = "-"
succeeded = 0
if make_result.returncode == 0: if make_result.returncode == 0:
success = SUCCEEDED succeeded = 1
success_count += 1
out_file = glob.glob('_build/build-{}/*.out'.format(board))[0] out_file = glob.glob('_build/build-{}/*.out'.format(board))[0]
size_output = subprocess.run('size {}'.format(out_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") size_output = subprocess.run('size {}'.format(out_file), shell=True, stdout=subprocess.PIPE).stdout.decode(
"utf-8")
size_list = size_output.split('\n')[1].split('\t') size_list = size_output.split('\n')[1].split('\t')
flash_size = int(size_list[0]) flash_size = int(size_list[0])
sram_size = int(size_list[1]) + int(size_list[2]) sram_size = int(size_list[1]) + int(size_list[2])
else:
exit_status = make_result.returncode
success = FAILED
fail_count += 1
for entry in os.scandir("_build/build-{}".format(board)): print(build_format.format(board, SUCCEEDED if succeeded else FAILED, "{:.2f}s".format(build_duration), flash_size,
for extension in ["zip", "hex", "uf2"]: sram_size))
if entry.name.endswith(extension):
if ("nosd" in entry.name) or ("s140" in entry.name) or ("s132" in entry.name):
shutil.copy(entry.path, bin_directory)
print(build_format.format(board, success, "{:.2f}s".format(build_duration), flash_size, sram_size))
if make_result.returncode != 0: if make_result.returncode != 0:
print(make_result.stdout.decode("utf-8")) print(make_result.stdout.decode("utf-8"))
# Build Summary return succeeded
total_time = time.monotonic() - total_time
print(build_separator)
print("Build Sumamary: {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, total_time))
print(build_separator)
sys.exit(exit_status)
if __name__ == '__main__':
# remove build folder first
subprocess.run("rm -rf _build/", shell=True)
# All supported boards
all_boards = []
for entry in os.scandir("src/boards"):
if entry.is_dir():
all_boards.append(entry.name)
all_boards.sort()
print(build_separator)
print(build_format.format('Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM'))
print(build_separator)
success_count = 0
total_time = time.monotonic()
with Pool(processes=os.cpu_count()) as pool:
success_count = sum(pool.map(build_board, all_boards))
total_time = time.monotonic() - total_time
fail_count = len(all_boards) - success_count
# Build Summary
print(build_separator)
print(
"Build Summary: {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, total_time))
print(build_separator)
sys.exit(fail_count)

View file

@ -1,76 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
`adafruit_adabot`
====================================================
TODO(description)
* Author(s): Scott Shawcroft
"""
import os
import requests
def _fix_url(url):
if url.startswith("/"):
url = "https://api.github.com" + url
return url
def _fix_kwargs(kwargs):
api_version = "application/vnd.github.scarlet-witch-preview+json;application/vnd.github.hellcat-preview+json"
if "headers" in kwargs:
if "Accept" in kwargs["headers"]:
kwargs["headers"]["Accept"] += ";" + api_version
else:
kwargs["headers"]["Accept"] = api_version
else:
kwargs["headers"] = {"Accept": "application/vnd.github.hellcat-preview+json"}
if "ADABOT_GITHUB_ACCESS_TOKEN" in os.environ and "auth" not in kwargs:
access_token = os.environ["ADABOT_GITHUB_ACCESS_TOKEN"]
if "params" in kwargs:
kwargs["params"]["access_token"] = access_token
else:
kwargs["params"] = {"access_token": access_token}
if "timeout" not in kwargs:
kwargs["timeout"] = 30
return kwargs
def get(url, **kwargs):
response = requests.get(_fix_url(url), **_fix_kwargs(kwargs))
remaining = int(response.headers["X-RateLimit-Remaining"])
if remaining % 100 == 0:
print(remaining, "requests remaining this hour")
return response
def post(url, **kwargs):
return requests.post(_fix_url(url), **_fix_kwargs(kwargs))
def put(url, **kwargs):
return requests.put(_fix_url(url), **_fix_kwargs(kwargs))
def patch(url, **kwargs):
return requests.patch(_fix_url(url), **_fix_kwargs(kwargs))
def delete(url, **kwargs):
return requests.delete(_fix_url(url), **_fix_kwargs(kwargs))

View file

@ -1,34 +0,0 @@
#! /usr/bin/env python3
import os
import os.path
import sys
import uritemplate
import glob
sys.path.append("adabot")
import github_requests as github
exit_status = 0
filepaths = list(glob.iglob('../bin/*/*', recursive=True))
filepaths.sort()
for full_filename in filepaths:
filename = os.path.basename(full_filename)
url_vars = {}
url_vars["name"] = filename
url = uritemplate.expand(os.environ["UPLOAD_URL"], url_vars)
headers = {"content-type": "application/octet-stream"}
print(url)
with open(full_filename, "rb") as f:
response = github.post(url, data=f, headers=headers)
if not response.ok:
if response.status_code == 422 and response.json().get("errors", [{"code":""}])[0]["code"] == "already_exists":
print("File already uploaded. Skipping.")
continue
print("Upload of {} failed with {}.".format(filename, response.status_code))
print(response.text)
sys.exit(response.status_code)
sys.exit(exit_status)