Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
maxd-nordic committed Jun 20, 2024
1 parent bb6cd83 commit fb52a57
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 53 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,26 @@ jobs:
run: |
cp $(pwd)/nrf/applications/connectivity_bridge/build/dfu_application.zip $(pwd)/thingy91x-oob/app/build/hello.nrfcloud.com-${{ env.VERSION }}-thingy91x-nrf53-dfu.zip
- name: Build nRF91 BL Update
if: env.BUILD_BL_UPDATE == 'true'
working-directory: thingy91x-oob
run: |
west twister -T . --test app/app.build.bootloader_update -v -p thingy91x/nrf9151/ns --inline-logs
- name: Build nRF53 BL Update
if: env.BUILD_BL_UPDATE == 'true'
working-directory: thingy91x-oob
run: |
cat scripts/connectivity_bridge_extra_sample.yaml >> ../nrf/applications/connectivity_bridge/sample.yaml
west twister -T ../nrf/applications/connectivity_bridge --test applications.connectivity_bridge.bootloader_update -v -p thingy91x/nrf5340/cpuapp --inline-logs
- name: Copy BL Update Artifacts
if: env.BUILD_BL_UPDATE == 'true'
working-directory: thingy91x-oob
run: |
cp twister-out/thingy91x_nrf9151_ns/app/app.build.bootloader_update/dfu_mcuboot.zip thingy91x-oob/app/build/hello.nrfcloud.com-${{ env.VERSION }}-nrf91-bootloader.zip
cp twister-out.1/thingy91x_nrf5340_cpuapp/applications.connectivity_bridge.bootloader_update/dfu_mcuboot.zip thingy91x-oob/app/build/hello.nrfcloud.com-${{ env.VERSION }}-nrf53-bootloader.zip
- name: Rename artifacts
working-directory: thingy91x-oob/app/build
run: |
Expand Down
18 changes: 15 additions & 3 deletions .github/workflows/on_target.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ jobs:
build:
uses: ./.github/workflows/build.yml

test:
name: Test
needs: build
runs-on: self-hosted
Expand All @@ -21,6 +20,7 @@ jobs:
volumes:
- /dev:/dev:rw
- /run/udev:/run/udev
- /opt/setup-jlink:/opt/setup-jlink
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -52,9 +52,21 @@ jobs:
run: |
pip install -r requirements.txt --break-system-packages
- name: Run tests
- name: Run UART output tests
working-directory: thingy91x-oob/tests/on_target
run: |
pytest -s -v tests --firmware-hex artifacts/hello.nrfcloud.com-${{ env.VERSION }}-thingy91x-debug-app.hex
pytest -s -v -m dut1 tests --firmware-hex artifacts/hello.nrfcloud.com-${{ env.VERSION }}-thingy91x-debug-app.hex
env:
SEGGER: ${{ secrets.SEGGER_DUT_1 }}

- name: Run DFU tests
working-directory: thingy91x-oob/tests/on_target
run: |
pytest -s -v -m dut2 tests
env:
SEGGER_NRF53: ${{ secrets.SEGGER_DUT_2_EXT_DBG }}
SEGGER_NRF91: ${{ secrets.SEGGER_DUT_2_NRF91 }}
UART_ID: ${{ secrets.UART_DUT_2 }}
NRF53_HEX_FILE: artifacts/hello.nrfcloud.com-${{ env.VERSION }}-thingy91x-nrf53-connectivity-bridge.hex
NRF91_HEX_FILE: artifacts/hello.nrfcloud.com-${{ env.VERSION }}-thingy91x-debug-app.hex
NRF91_APP_UPDATE_ZIP: artifacts/hello.nrfcloud.com-${{ env.VERSION }}-thingy91x-nrf91-dfu.zip
2 changes: 2 additions & 0 deletions tests/on_target/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pytest
pyserial
termcolor
pyusb
imgtool
62 changes: 62 additions & 0 deletions tests/on_target/tests/test_serial_dfu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
##########################################################################################
# Copyright (c) 2024 Nordic Semiconductor
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
##########################################################################################

import pytest
import time
import os
from utils.flash_tools import flash_device, reset_device, recover_device, setup_jlink, dfu_device
from utils.uart import Uart
from tests.conftest import t91x_board
import sys
sys.path.append(os.getcwd())
from utils.logger import get_logger

def wait_until_uart_available(name, timeout_seconds=60):
base_path = "/dev/serial/by-id"
while timeout_seconds > 0:
try:
serial_paths = [os.path.join(base_path, entry) for entry in os.listdir(base_path)]
for path in sorted(serial_paths):
if name in path:
break
except (FileNotFoundError, PermissionError) as e:
logger.error(e)
time.sleep(1)
timeout_seconds -= 1

@pytest.fixture(scope="function")
def t91x_dfu():
SEGGER_NRF53 = os.getenv('SEGGER_NRF53')
SEGGER_NRF91 = os.getenv('SEGGER_NRF91')
CONNECTIVITY_BRIDGE_UART = os.getenv('UART_ID')
NRF53_HEX_FILE = os.getenv('NRF53_HEX_FILE')
NRF91_HEX_FILE = os.getenv('NRF91_HEX_FILE')

setup_jlink(SEGGER_NRF53)
wait_until_uart_available(SEGGER_NRF91)
flash_device(hexfile=NRF91_HEX_FILE, serial=SEGGER_NRF91)
recover_device(serial=SEGGER_NRF53, core='Network')
recover_device(serial=SEGGER_NRF53, core='Application')
flash_device(hexfile=NRF53_HEX_FILE, serial=SEGGER_NRF53, extra_args=['--core', 'Network', '--options', 'reset=RESET_NONE,chip_erase_mode=ERASE_ALL,verify=VERIFY_NONE'])
flash_device(hexfile=NRF53_HEX_FILE, serial=SEGGER_NRF53, extra_args=['--options', 'reset=RESET_SYSTEM,chip_erase_mode=ERASE_ALL,verify=VERIFY_NONE'])
wait_until_uart_available(CONNECTIVITY_BRIDGE_UART)

return t91x_board()

@pytest.mark.dut2
def test_dfu(t91x_dfu):
# NRF91_BL_UPDATE_ZIP = os.getenv('NRF91_BL_UPDATE_ZIP')
NRF91_APP_UPDATE_ZIP = os.getenv('NRF91_APP_UPDATE_ZIP')

t91x_dfu.uart.stop()

# dfu_device(NRF91_BL_UPDATE_ZIP)
dfu_device(NRF91_APP_UPDATE_ZIP)

t91x_dfu.uart.start()

expected_lines = ["Firmware version 1", "Zephyr OS"]
t91x_dfu.uart.wait_for_str(expected_lines, timeout=60)
logger.info("Expected lines found")
2 changes: 1 addition & 1 deletion tests/on_target/tests/test_uart_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

TEST_TIMEOUT = 1 * 60


@pytest.mark.dut1
def test_program_board_and_check_uart(t91x_board, hex_file):
flash_device(os.path.abspath(hex_file))

Expand Down
52 changes: 45 additions & 7 deletions tests/on_target/utils/flash_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

SEGGER = os.getenv('SEGGER')

def reset_device():
logger.info(f"Resetting device, segger: {SEGGER}")
def reset_device(serial=SEGGER):
logger.info(f"Resetting device, segger: {serial}")
try:
result = subprocess.run(['nrfutil', 'device', 'reset', '--serial-number', SEGGER], check=True, text=True, capture_output=True)
result = subprocess.run(['nrfutil', 'device', 'reset', '--serial-number', serial], check=True, text=True, capture_output=True)
logger.info("Command output:")
logger.info(result.stdout)
logger.info("Command completed successfully.")
Expand All @@ -27,11 +27,39 @@ def reset_device():
logger.info(e.stderr)
raise

def flash_device(hexfile):
def flash_device(hexfile, serial=SEGGER, extra_args=[]):
# hexfile (str): Full path to file (hex or zip) to be programmed
logger.info(f"Flashing device, segger: {SEGGER}, firmware: {hexfile}")
logger.info(f"Flashing device, segger: {serial}, firmware: {hexfile}")
try:
result = subprocess.run(['nrfutil', 'device', 'program', '--firmware', hexfile, '--serial-number', SEGGER], check=True, text=True, capture_output=True)
result = subprocess.run(['nrfutil', 'device', 'program', *extra_args, '--firmware', hexfile, '--serial-number', serial], check=True, text=True, capture_output=True)
logger.info("Command completed successfully.")
except subprocess.CalledProcessError as e:
# Handle errors in the command execution
logger.info("An error occurred while flashing the device.")
logger.info("Error output:")
logger.info(e.stderr)
raise

reset_device(serial)

def recover_device(serial=SEGGER, core="Application"):
logger.info(f"Recovering device, segger: {serial}")
try:
result = subprocess.run(['nrfutil', 'device', 'recover', '--serial-number', serial, '--core', core], check=True, text=True, capture_output=True)
logger.info("Command completed successfully.")
except subprocess.CalledProcessError as e:
# Handle errors in the command execution
logger.info("An error occurred while recovering the device.")
logger.info("Error output:")
logger.info(e.stderr)
raise

def dfu_device(zipfile):
logger.info(f"Performing MCUBoot DFU, firmware: {zipfile}")
thingy91x_dfu = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'thingy91x-dfu.py')
# call thingy91x-dfu
try:
result = subprocess.run(['python3', thingy91x_dfu, '--image', zipfile], check=True, text=True, capture_output=True)
logger.info("Command output:")
logger.info(result.stdout)
logger.info("Command completed successfully.")
Expand All @@ -42,4 +70,14 @@ def flash_device(hexfile):
logger.info(e.stderr)
raise

reset_device()
def setup_jlink(serial):
# run command and check if it was successful
try:
result = subprocess.run(['/opt/setup-jlink/setup-jlink.bash', serial], check=True, text=True, capture_output=False)
logger.info("Command completed successfully.")
except subprocess.CalledProcessError as e:
# Handle errors in the command execution
logger.info("An error occurred while setting up JLink.")
logger.info("Error output:")
logger.info(e.stderr)
raise
42 changes: 0 additions & 42 deletions tests/on_target/utils/thingy91x_dfu.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
import serial.tools.list_ports
import os
import time
from west.commands import WestCommand
import west.log
from tempfile import TemporaryDirectory
from zipfile import ZipFile
import re
Expand Down Expand Up @@ -416,43 +414,3 @@ def main(args, reset_only, logging=default_logging):
)

main(args, reset_only=False, logging=default_logging)


class Thingy91XDFU(WestCommand):
def __init__(self):
super(Thingy91XDFU, self).__init__(
"thingy91x-dfu",
"Thingy:91 X DFU",
"Put Thingy:91 X in DFU mode and update using MCUBoot serial recovery.",
)

def do_add_parser(self, parser_adder):
parser = parser_adder.add_parser(
self.name, help=self.help, description=self.description
)
add_args_to_parser(parser)
parser.add_argument("--image", type=str, help="application update file",
default="build/dfu_application.zip")

return parser

def do_run(self, args, unknown_args):
main(args, reset_only=False, logging=west.log)

class Thingy91XReset(WestCommand):
def __init__(self):
super(Thingy91XReset, self).__init__(
"thingy91x-reset",
"Thingy:91 X Reset",
"Reset Thingy:91 X.",
)
def do_add_parser(self, parser_adder):
parser = parser_adder.add_parser(
self.name, help=self.help, description=self.description
)
add_args_to_parser(parser, default_chip="nrf91")

return parser

def do_run(self, args, unknown_args):
main(args, reset_only=True, logging=west.log)
11 changes: 11 additions & 0 deletions tests/on_target/utils/uart.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ def stop(self) -> None:
self._evt.set()
self._t.join()

def start(self) -> None:
# Start the UART thread after it has been stopped
self._evt = threading.Event()
self._writeq = queue.Queue()
self._t = threading.Thread(target=self._uart)
self._t.start()
self._selfdestruct = threading.Timer(
timeout , self.selfdestruct
)
self._selfdestruct.start()

def wait_for_str(
self, msgs: list, error_msg: str = "", timeout: int = DEFAULT_WAIT_FOR_STR_TIMEOUT
) -> None:
Expand Down

0 comments on commit fb52a57

Please sign in to comment.