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
#------------------------------------------------------------------------------
# local customization
-include Makefile.user
SDK_PATH = lib/sdk/components
@ -37,7 +38,7 @@ OUT_NAME = $(BOARD)_bootloader-$(GIT_VERSION)
MERGED_FILE = $(OUT_NAME)_$(SD_NAME)_$(SD_VERSION)
#------------------------------------------------------------------------------
# Tool configure
# Tool Configure
#------------------------------------------------------------------------------
# Toolchain commands
@ -208,39 +209,46 @@ ASM_SRC = $(NRFX_PATH)/mdk/gcc_startup_$(MCU_SUB_VARIANT).S
#------------------------------------------------------------------------------
# src
IPATH += src
IPATH += src/boards
IPATH += src/boards/$(BOARD)
IPATH += src/cmsis/include
IPATH += src/usb
IPATH += $(TUSB_PATH)
IPATH += \
src \
src/boards \
src/boards/$(BOARD) \
src/cmsis/include \
src/usb \
$(TUSB_PATH)
# nrfx
IPATH += $(NRFX_PATH)
IPATH += $(NRFX_PATH)/mdk
IPATH += $(NRFX_PATH)/hal
IPATH += $(NRFX_PATH)/drivers/include
IPATH += $(NRFX_PATH)/drivers/src
IPATH += \
$(NRFX_PATH) \
$(NRFX_PATH)/mdk \
$(NRFX_PATH)/hal \
$(NRFX_PATH)/drivers/include \
$(NRFX_PATH)/drivers/src
IPATH += $(SDK11_PATH)/libraries/bootloader_dfu/hci_transport
IPATH += $(SDK11_PATH)/libraries/bootloader_dfu
IPATH += $(SDK11_PATH)/drivers_nrf/pstorage
IPATH += $(SDK11_PATH)/ble/common
IPATH += $(SDK11_PATH)/ble/ble_services/ble_dfu
IPATH += $(SDK11_PATH)/ble/ble_services/ble_dis
# sdk11 for cdc/ble dfu
IPATH += \
$(SDK11_PATH)/libraries/bootloader_dfu/hci_transport \
$(SDK11_PATH)/libraries/bootloader_dfu \
$(SDK11_PATH)/drivers_nrf/pstorage \
$(SDK11_PATH)/ble/common \
$(SDK11_PATH)/ble/ble_services/ble_dfu \
$(SDK11_PATH)/ble/ble_services/ble_dis
IPATH += $(SDK_PATH)/libraries/timer
IPATH += $(SDK_PATH)/libraries/scheduler
IPATH += $(SDK_PATH)/libraries/crc16
IPATH += $(SDK_PATH)/libraries/util
IPATH += $(SDK_PATH)/libraries/hci/config
IPATH += $(SDK_PATH)/libraries/uart
IPATH += $(SDK_PATH)/libraries/hci
IPATH += $(SDK_PATH)/drivers_nrf/delay
# later sdk with updated drivers
IPATH += \
$(SDK_PATH)/libraries/timer \
$(SDK_PATH)/libraries/scheduler \
$(SDK_PATH)/libraries/crc16 \
$(SDK_PATH)/libraries/util \
$(SDK_PATH)/libraries/hci/config \
$(SDK_PATH)/libraries/uart \
$(SDK_PATH)/libraries/hci \
$(SDK_PATH)/drivers_nrf/delay
# Softdevice
IPATH += $(SD_PATH)/$(SD_FILENAME)_API/include
IPATH += $(SD_PATH)/$(SD_FILENAME)_API/include/nrf52
# SoftDevice
IPATH += \
$(SD_PATH)/$(SD_FILENAME)_API/include \
$(SD_PATH)/$(SD_FILENAME)_API/include/nrf52
#------------------------------------------------------------------------------
# Compiler Flags
@ -278,9 +286,6 @@ CFLAGS += \
# Suppress warning caused by SDK
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
# broken constraints. As a result the IPA-modref pass, introduced in gcc-11,
# is able to "prove" that arguments to wrapper functions generated with
@ -332,6 +337,7 @@ LIBS += -lm -lc
#------------------------------------------------------------------------------
# Assembler flags
#------------------------------------------------------------------------------
ASFLAGS += $(CFLAGS)
#function for removing duplicates in a list
@ -356,7 +362,7 @@ INC_PATHS = $(addprefix -I,$(IPATH))
# 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
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).zip $(BIN)
#------------------- Flash target -------------------
#--------------------------------------
# Flash Target
#--------------------------------------
check_defined = \
$(strip $(foreach 1,$1, \
@ -440,29 +448,29 @@ __check_defined = \
$(if $(value $1),, \
$(error Undefined make flag: $1$(if $2, ($2))))
# erase chip
erase:
@echo Erasing flash
$(call FLASH_ERASE_CMD)
# Flash the compiled
flash: $(BUILD)/$(OUT_NAME)_nosd.hex
@echo Flashing: $(notdir $<)
$(call FLASH_CMD,$<)
erase:
@echo Erasing flash
$(call FLASH_ERASE_CMD)
# flash SD only
sd:
flash-sd:
@echo Flashing: $(SD_HEX)
$(call FLASH_NOUICR_CMD,$(SD_HEX))
# flash MBR only
mbr:
flash-mbr:
@echo Flashing: $(MBR_HEX)
$(call FLASH_NOUICR_CMD,$(MBR_HEX))
#------------------- Flash with NRFUTIL via DFU -------------------
# dfu using CDC interface
dfu-flash: $(BUILD)/$(MERGED_FILE).zip
# dfu with adafruit-nrfutil using CDC interface
dfu-flash: flash-dfu
flash-dfu: $(BUILD)/$(MERGED_FILE).zip
@:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0)
$(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 must have have a J-Link available to "unbrick" your device.
Prerequisites
### Prerequisites
- 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)
- [Python IntelHex](https://pypi.org/project/IntelHex/)
To build:
### Build:
```
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=` :
```
@ -169,9 +142,41 @@ Supported boards are: feather_nrf52840_express feather_nrf52840_express pca10056
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
#### 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 ...
@ -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.
#### 2. `ModuleNotFoundError: No module named 'intelhex'`
#### `ModuleNotFoundError: No module named 'intelhex'`
Install python-intelhex with
@ -198,8 +203,7 @@ Install python-intelhex with
pip install intelhex
```
#### 3. `make: nrfjprog: No such file or directory`
#### `make: nrfjprog: No such file or directory`
Make sure that `nrfjprog` is available from the command-line. This binary is
part of Nordic's nRF5x Command Line Tools.

View file

@ -1,23 +1,49 @@
import os
import shutil
import glob
import sys
import subprocess
import time
subprocess.run("rm -rf _build/", shell=True)
subprocess.run("rm -rf bin/", shell=True)
from multiprocessing import Pool
SUCCEEDED = "\033[32msucceeded\033[0m"
FAILED = "\033[31mfailed\033[0m"
success_count = 0
fail_count = 0
exit_status = 0
build_format = '| {:32} | {:18} | {:5} | {:6} | {:6} |'
build_separator = '-' * 74
def build_board(board):
start_time = time.monotonic()
make_result = subprocess.run("make -j BOARD={} all".format(board), shell=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
build_duration = time.monotonic() - start_time
flash_size = "-"
sram_size = "-"
succeeded = 0
if make_result.returncode == 0:
succeeded = 1
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_list = size_output.split('\n')[1].split('\t')
flash_size = int(size_list[0])
sram_size = int(size_list[1]) + int(size_list[2])
print(build_format.format(board, SUCCEEDED if succeeded else FAILED, "{:.2f}s".format(build_duration), flash_size,
sram_size))
if make_result.returncode != 0:
print(make_result.stdout.decode("utf-8"))
return succeeded
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"):
@ -25,54 +51,23 @@ for entry in os.scandir("src/boards"):
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)
success_count = 0
total_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)
build_duration = time.monotonic() - start_time
with Pool(processes=os.cpu_count()) as pool:
success_count = sum(pool.map(build_board, all_boards))
flash_size = "-"
sram_size = "-"
if make_result.returncode == 0:
success = SUCCEEDED
success_count += 1
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_list = size_output.split('\n')[1].split('\t')
flash_size = int(size_list[0])
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)):
for extension in ["zip", "hex", "uf2"]:
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:
print(make_result.stdout.decode("utf-8"))
total_time = time.monotonic() - total_time
fail_count = len(all_boards) - success_count
# Build Summary
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 Summary: {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, total_time))
print(build_separator)
sys.exit(exit_status)
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)