Revamp deploy.py
Now the script supports more flashing methods: - JLink (with tockloader) - OpenOCD (with tockloader) - pyOCD - Nordic DFU - none (will produce an IntelHex file) Also merged the contributions from: - Yihui Xiong to support the Makerdiary USB dongle board - Dennis Geurts to support Nordic DFU Doc updated accordingly. Imported 2 patches for Tock kernel: - 06-add-set_vector_table_offset.patch (upstream tock/tock#1579) - 07-nrf52-bootloader.patch (upstream tock/tock#1681)
This commit is contained in:
@@ -1,7 +0,0 @@
|
|||||||
# Target configuration for the CTAP2 app on the nRF52840 chip
|
|
||||||
[target.thumbv7em-none-eabi]
|
|
||||||
rustflags = [
|
|
||||||
"-C", "link-arg=-Tnrf52840dk_layout.ld",
|
|
||||||
"-C", "relocation-model=static",
|
|
||||||
"-D", "warnings",
|
|
||||||
]
|
|
||||||
23
README.md
23
README.md
@@ -19,8 +19,9 @@ successfully tested on the following boards:
|
|||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
|
|
||||||
This project is proof-of-concept and a research platform. It's still under
|
This project is **proof-of-concept and a research platform**. It is **NOT**
|
||||||
development and as such comes with a few limitations:
|
meant for a day to day usage. It's still under development and as such comes
|
||||||
|
with a few limitations:
|
||||||
|
|
||||||
### FIDO2
|
### FIDO2
|
||||||
|
|
||||||
@@ -53,25 +54,17 @@ For a more detailed guide, please refer to our
|
|||||||
./setup.sh
|
./setup.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
2. If Tock OS is already installed on your board, move to the next step.
|
2. Next step is to install Tock OS as well as the OpenSK application on your
|
||||||
Otherwise, just run one of the following commands, depending on the board
|
board (**Warning**: it will erase the locally stored credentials). Run:
|
||||||
you have:
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Nordic nRF52840-DK board
|
# Nordic nRF52840-DK board
|
||||||
./deploy.py os --board=nrf52840_dk
|
./deploy.py --board=nrf52840dk --opensk
|
||||||
# Nordic nRF52840-Dongle
|
# Nordic nRF52840-Dongle
|
||||||
./deploy.py os --board=nrf52840_dongle
|
./deploy.py --board=nrf52840_dongle --opensk
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Next step is to install/update the OpenSK application on your board
|
3. On Linux, you may want to avoid the need for `root` privileges to interact
|
||||||
(**Warning**: it will erase the locally stored credentials). Run:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
./deploy.py app --opensk
|
|
||||||
```
|
|
||||||
|
|
||||||
4. On Linux, you may want to avoid the need for `root` privileges to interact
|
|
||||||
with the key. For that purpose we provide a udev rule file that can be
|
with the key. For that purpose we provide a udev rule file that can be
|
||||||
installed with the following command:
|
installed with the following command:
|
||||||
|
|
||||||
|
|||||||
30
boards/nrf52840_dongle_dfu/Cargo.toml
Normal file
30
boards/nrf52840_dongle_dfu/Cargo.toml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
[package]
|
||||||
|
name = "nrf52840_dongle_dfu"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
|
||||||
|
build = "build.rs"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = "abort"
|
||||||
|
lto = false
|
||||||
|
opt-level = "z"
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
|
lto = true
|
||||||
|
opt-level = "z"
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
path = "../../third_party/tock/boards/nordic/nrf52840_dongle/src/main.rs"
|
||||||
|
name = "nrf52840_dongle_dfu"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
components = { path = "../../third_party/tock/boards/components" }
|
||||||
|
cortexm4 = { path = "../../third_party/tock/arch/cortex-m4" }
|
||||||
|
capsules = { path = "../../third_party/tock/capsules" }
|
||||||
|
kernel = { path = "../../third_party/tock/kernel" }
|
||||||
|
nrf52840 = { path = "../../third_party/tock/chips/nrf52840" }
|
||||||
|
nrf52dk_base = { path = "../../third_party/tock/boards/nordic/nrf52dk_base" }
|
||||||
4
boards/nrf52840_dongle_dfu/build.rs
Normal file
4
boards/nrf52840_dongle_dfu/build.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=layout.ld");
|
||||||
|
println!("cargo:rerun-if-changed=../../third_party/tock/boards/kernel_layout.ld");
|
||||||
|
}
|
||||||
10
boards/nrf52840_dongle_dfu/layout.ld
Normal file
10
boards/nrf52840_dongle_dfu/layout.ld
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x00001000, LENGTH = 188K
|
||||||
|
prog (rx) : ORIGIN = 0x00030000, LENGTH = 832K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
|
||||||
|
}
|
||||||
|
|
||||||
|
MPU_MIN_ALIGN = 8K;
|
||||||
|
|
||||||
|
INCLUDE ../../third_party/tock/boards/kernel_layout.ld
|
||||||
26
boards/nrf52840_mdk_dfu/Cargo.toml
Normal file
26
boards/nrf52840_mdk_dfu/Cargo.toml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
[package]
|
||||||
|
name = "nrf52840_mdk_dfu"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Yihui Xiong <yihui.xiong@hotmail.com>"]
|
||||||
|
build = "build.rs"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = "abort"
|
||||||
|
lto = false
|
||||||
|
opt-level = "z"
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
|
lto = true
|
||||||
|
opt-level = "z"
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
components = { path = "../../third_party/tock/boards/components" }
|
||||||
|
cortexm4 = { path = "../../third_party/tock/arch/cortex-m4" }
|
||||||
|
capsules = { path = "../../third_party/tock/capsules" }
|
||||||
|
kernel = { path = "../../third_party/tock/kernel" }
|
||||||
|
nrf52840 = { path = "../../third_party/tock/chips/nrf52840" }
|
||||||
|
nrf52dk_base = { path = "../../third_party/tock/boards/nordic/nrf52dk_base" }
|
||||||
4
boards/nrf52840_mdk_dfu/build.rs
Normal file
4
boards/nrf52840_mdk_dfu/build.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=layout.ld");
|
||||||
|
println!("cargo:rerun-if-changed=../../third_party/tock/boards/kernel_layout.ld");
|
||||||
|
}
|
||||||
10
boards/nrf52840_mdk_dfu/layout.ld
Normal file
10
boards/nrf52840_mdk_dfu/layout.ld
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x00001000, LENGTH = 188K
|
||||||
|
prog (rx) : ORIGIN = 0x00030000, LENGTH = 832K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
|
||||||
|
}
|
||||||
|
|
||||||
|
MPU_MIN_ALIGN = 8K;
|
||||||
|
|
||||||
|
INCLUDE ../../third_party/tock/boards/kernel_layout.ld
|
||||||
65
boards/nrf52840_mdk_dfu/src/io.rs
Normal file
65
boards/nrf52840_mdk_dfu/src/io.rs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
use core::fmt::Write;
|
||||||
|
use core::panic::PanicInfo;
|
||||||
|
use cortexm4;
|
||||||
|
use kernel::debug;
|
||||||
|
use kernel::debug::IoWrite;
|
||||||
|
use kernel::hil::led;
|
||||||
|
use kernel::hil::uart::{self, Configure};
|
||||||
|
use nrf52840::gpio::Pin;
|
||||||
|
|
||||||
|
use crate::CHIP;
|
||||||
|
use crate::PROCESSES;
|
||||||
|
|
||||||
|
struct Writer {
|
||||||
|
initialized: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
static mut WRITER: Writer = Writer { initialized: false };
|
||||||
|
|
||||||
|
impl Write for Writer {
|
||||||
|
fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
|
||||||
|
self.write(s.as_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IoWrite for Writer {
|
||||||
|
fn write(&mut self, buf: &[u8]) {
|
||||||
|
let uart = unsafe { &mut nrf52840::uart::UARTE0 };
|
||||||
|
if !self.initialized {
|
||||||
|
self.initialized = true;
|
||||||
|
uart.configure(uart::Parameters {
|
||||||
|
baud_rate: 115200,
|
||||||
|
stop_bits: uart::StopBits::One,
|
||||||
|
parity: uart::Parity::None,
|
||||||
|
hw_flow_control: false,
|
||||||
|
width: uart::Width::Eight,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for &c in buf {
|
||||||
|
unsafe {
|
||||||
|
uart.send_byte(c);
|
||||||
|
}
|
||||||
|
while !uart.tx_ready() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
#[no_mangle]
|
||||||
|
#[panic_handler]
|
||||||
|
/// Panic handler
|
||||||
|
pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! {
|
||||||
|
// The nRF52840 Dongle LEDs (see back of board)
|
||||||
|
const LED1_PIN: Pin = Pin::P0_23;
|
||||||
|
let led = &mut led::LedLow::new(&mut nrf52840::gpio::PORT[LED1_PIN]);
|
||||||
|
let writer = &mut WRITER;
|
||||||
|
debug::panic(
|
||||||
|
&mut [led],
|
||||||
|
writer,
|
||||||
|
pi,
|
||||||
|
&cortexm4::support::nop,
|
||||||
|
&PROCESSES,
|
||||||
|
&CHIP,
|
||||||
|
)
|
||||||
|
}
|
||||||
123
boards/nrf52840_mdk_dfu/src/main.rs
Normal file
123
boards/nrf52840_mdk_dfu/src/main.rs
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
//! Tock kernel for the Makerdiary nRF52840 MDK USB dongle.
|
||||||
|
//!
|
||||||
|
//! It is based on nRF52840 SoC (Cortex M4 core with a BLE transceiver) with
|
||||||
|
//! many exported I/O and peripherals.
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
use kernel::component::Component;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use kernel::{debug, debug_gpio, debug_verbose, static_init};
|
||||||
|
use nrf52840::gpio::Pin;
|
||||||
|
use nrf52dk_base::{SpiPins, UartChannel, UartPins};
|
||||||
|
|
||||||
|
// The nRF52840 MDK USB Dongle LEDs
|
||||||
|
const LED1_R_PIN: Pin = Pin::P0_23;
|
||||||
|
const LED1_G_PIN: Pin = Pin::P0_22;
|
||||||
|
const LED1_B_PIN: Pin = Pin::P0_24;
|
||||||
|
|
||||||
|
// The nRF52840 Dongle button
|
||||||
|
const BUTTON_PIN: Pin = Pin::P0_18;
|
||||||
|
const BUTTON_RST_PIN: Pin = Pin::P0_02;
|
||||||
|
|
||||||
|
const UART_RTS: Pin = Pin::P0_21;
|
||||||
|
const UART_TXD: Pin = Pin::P0_20;
|
||||||
|
const UART_CTS: Pin = Pin::P0_03;
|
||||||
|
const UART_RXD: Pin = Pin::P0_19;
|
||||||
|
|
||||||
|
const SPI_MOSI: Pin = Pin::P0_05;
|
||||||
|
const SPI_MISO: Pin = Pin::P0_06;
|
||||||
|
const SPI_CLK: Pin = Pin::P0_07;
|
||||||
|
|
||||||
|
/// UART Writer
|
||||||
|
pub mod io;
|
||||||
|
|
||||||
|
// State for loading and holding applications.
|
||||||
|
// How should the kernel respond when a process faults.
|
||||||
|
const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic;
|
||||||
|
|
||||||
|
// Number of concurrent processes this platform supports.
|
||||||
|
const NUM_PROCS: usize = 8;
|
||||||
|
|
||||||
|
// RAM to be shared by all application processes.
|
||||||
|
#[link_section = ".app_memory"]
|
||||||
|
static mut APP_MEMORY: [u8; 0x3C000] = [0; 0x3C000];
|
||||||
|
|
||||||
|
static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] =
|
||||||
|
[None, None, None, None, None, None, None, None];
|
||||||
|
|
||||||
|
// Static reference to chip for panic dumps
|
||||||
|
static mut CHIP: Option<&'static nrf52840::chip::Chip> = None;
|
||||||
|
|
||||||
|
/// Dummy buffer that causes the linker to reserve enough space for the stack.
|
||||||
|
#[no_mangle]
|
||||||
|
#[link_section = ".stack_buffer"]
|
||||||
|
pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
|
||||||
|
|
||||||
|
/// Entry point in the vector table called on hard reset.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn reset_handler() {
|
||||||
|
// Loads relocations and clears BSS
|
||||||
|
nrf52840::init();
|
||||||
|
|
||||||
|
let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&PROCESSES));
|
||||||
|
// GPIOs
|
||||||
|
let gpio = components::gpio::GpioComponent::new(board_kernel).finalize(
|
||||||
|
components::gpio_component_helper!(
|
||||||
|
&nrf52840::gpio::PORT[Pin::P0_04],
|
||||||
|
&nrf52840::gpio::PORT[Pin::P0_05],
|
||||||
|
&nrf52840::gpio::PORT[Pin::P0_06],
|
||||||
|
&nrf52840::gpio::PORT[Pin::P0_07],
|
||||||
|
&nrf52840::gpio::PORT[Pin::P0_08]
|
||||||
|
),
|
||||||
|
);
|
||||||
|
let button = components::button::ButtonComponent::new(board_kernel).finalize(
|
||||||
|
components::button_component_helper!((
|
||||||
|
&nrf52840::gpio::PORT[BUTTON_PIN],
|
||||||
|
capsules::button::GpioMode::LowWhenPressed,
|
||||||
|
kernel::hil::gpio::FloatingState::PullUp
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
|
let led = components::led::LedsComponent::new().finalize(components::led_component_helper!(
|
||||||
|
(
|
||||||
|
&nrf52840::gpio::PORT[LED1_R_PIN],
|
||||||
|
capsules::led::ActivationMode::ActiveLow
|
||||||
|
),
|
||||||
|
(
|
||||||
|
&nrf52840::gpio::PORT[LED1_G_PIN],
|
||||||
|
capsules::led::ActivationMode::ActiveLow
|
||||||
|
),
|
||||||
|
(
|
||||||
|
&nrf52840::gpio::PORT[LED1_B_PIN],
|
||||||
|
capsules::led::ActivationMode::ActiveLow
|
||||||
|
)
|
||||||
|
));
|
||||||
|
let chip = static_init!(nrf52840::chip::Chip, nrf52840::chip::new());
|
||||||
|
CHIP = Some(chip);
|
||||||
|
|
||||||
|
nrf52dk_base::setup_board(
|
||||||
|
board_kernel,
|
||||||
|
BUTTON_RST_PIN,
|
||||||
|
&nrf52840::gpio::PORT,
|
||||||
|
gpio,
|
||||||
|
LED1_R_PIN,
|
||||||
|
LED1_G_PIN,
|
||||||
|
LED1_B_PIN,
|
||||||
|
led,
|
||||||
|
UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD)),
|
||||||
|
&SpiPins::new(SPI_MOSI, SPI_MISO, SPI_CLK),
|
||||||
|
&None,
|
||||||
|
button,
|
||||||
|
true,
|
||||||
|
&mut APP_MEMORY,
|
||||||
|
&mut PROCESSES,
|
||||||
|
FAULT_RESPONSE,
|
||||||
|
nrf52840::uicr::Regulator0Output::V3_0,
|
||||||
|
false,
|
||||||
|
&Some(&nrf52840::usbd::USBD),
|
||||||
|
chip,
|
||||||
|
);
|
||||||
|
}
|
||||||
587
deploy.py
587
deploy.py
@@ -20,6 +20,7 @@ from __future__ import division
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import collections
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
@@ -32,10 +33,115 @@ from tockloader import tbfh
|
|||||||
from tockloader import tockloader as loader
|
from tockloader import tockloader as loader
|
||||||
from tockloader.exceptions import TockLoaderException
|
from tockloader.exceptions import TockLoaderException
|
||||||
|
|
||||||
# This structure allows us in the future to also support out-of-tree boards.
|
PROGRAMMERS = frozenset(("jlink", "openocd", "pyocd", "nordicdfu", "none"))
|
||||||
|
|
||||||
|
# This structure allows us to support out-of-tree boards as well as (in the
|
||||||
|
# future) more achitectures.
|
||||||
|
OpenSKBoard = collections.namedtuple(
|
||||||
|
"OpenSKBoard",
|
||||||
|
[
|
||||||
|
# Location of the Tock board (where the Makefile file is
|
||||||
|
"path",
|
||||||
|
# Targeted architecture (e.g. thumbv7em-none-eabi)
|
||||||
|
"arch",
|
||||||
|
# Size of 1 page of flash memory
|
||||||
|
"page_size",
|
||||||
|
# Flash address at which the kernel will be written
|
||||||
|
"kernel_address",
|
||||||
|
# Set to None is padding is not required for the board
|
||||||
|
"padding_address",
|
||||||
|
# Linker script to produce a working app for this board
|
||||||
|
"app_ldscript",
|
||||||
|
# Flash address at which the app should be written
|
||||||
|
"app_address",
|
||||||
|
# Target name for flashing the board using pyOCD
|
||||||
|
"pyocd_target",
|
||||||
|
# The cfg file in OpenOCD board folder
|
||||||
|
"openocd_board",
|
||||||
|
# Options to tell Tockloader how to work with OpenOCD
|
||||||
|
# Default: []
|
||||||
|
"openocd_options",
|
||||||
|
# Dictionnary specifying custom commands for OpenOCD
|
||||||
|
# Default is an empty dict
|
||||||
|
# Valid keys are: program, read, erase
|
||||||
|
"openocd_commands",
|
||||||
|
# Interface to use with JLink (e.g. swd, jtag, etc.)
|
||||||
|
"jlink_if",
|
||||||
|
# Device name as supported by JLinkExe
|
||||||
|
"jlink_device",
|
||||||
|
# Whether Nordic DFU flashing method is supported
|
||||||
|
"nordic_dfu",
|
||||||
|
])
|
||||||
|
|
||||||
SUPPORTED_BOARDS = {
|
SUPPORTED_BOARDS = {
|
||||||
"nrf52840_dk": "third_party/tock/boards/nordic/nrf52840dk",
|
"nrf52840dk":
|
||||||
"nrf52840_dongle": "third_party/tock/boards/nordic/nrf52840_dongle"
|
OpenSKBoard(
|
||||||
|
path="third_party/tock/boards/nordic/nrf52840dk",
|
||||||
|
arch="thumbv7em-none-eabi",
|
||||||
|
page_size=4096,
|
||||||
|
kernel_address=0,
|
||||||
|
padding_address=0x30000,
|
||||||
|
app_ldscript="nrf52840dk_layout.ld",
|
||||||
|
app_address=0x40000,
|
||||||
|
pyocd_target="nrf52840",
|
||||||
|
openocd_board="nordic_nrf52840_dongle.cfg",
|
||||||
|
openocd_options=[],
|
||||||
|
openocd_commands={},
|
||||||
|
jlink_if="swd",
|
||||||
|
jlink_device="nrf52840_xxaa",
|
||||||
|
nordic_dfu=False,
|
||||||
|
),
|
||||||
|
"nrf52840_dongle":
|
||||||
|
OpenSKBoard(
|
||||||
|
path="third_party/tock/boards/nordic/nrf52840_dongle",
|
||||||
|
arch="thumbv7em-none-eabi",
|
||||||
|
page_size=4096,
|
||||||
|
kernel_address=0,
|
||||||
|
padding_address=0x30000,
|
||||||
|
app_ldscript="nrf52840dk_layout.ld",
|
||||||
|
app_address=0x40000,
|
||||||
|
pyocd_target="nrf52840",
|
||||||
|
openocd_board="nordic_nrf52840_dongle.cfg",
|
||||||
|
openocd_options=[],
|
||||||
|
openocd_commands={},
|
||||||
|
jlink_if="swd",
|
||||||
|
jlink_device="nrf52840_xxaa",
|
||||||
|
nordic_dfu=False,
|
||||||
|
),
|
||||||
|
"nrf52840_dongle_dfu":
|
||||||
|
OpenSKBoard(
|
||||||
|
path="boards/nrf52840_dongle_dfu",
|
||||||
|
arch="thumbv7em-none-eabi",
|
||||||
|
page_size=4096,
|
||||||
|
kernel_address=0x1000,
|
||||||
|
padding_address=0x30000,
|
||||||
|
app_ldscript="nrf52840dk_layout.ld",
|
||||||
|
app_address=0x40000,
|
||||||
|
pyocd_target="nrf52840",
|
||||||
|
openocd_board="nordic_nrf52840_dongle.cfg",
|
||||||
|
openocd_options=[],
|
||||||
|
openocd_commands={},
|
||||||
|
jlink_if="swd",
|
||||||
|
jlink_device="nrf52840_xxaa",
|
||||||
|
nordic_dfu=True,
|
||||||
|
),
|
||||||
|
"nrf52840_mdk_dfu":
|
||||||
|
OpenSKBoard(
|
||||||
|
path="boards/nrf52840_mdk_dfu",
|
||||||
|
arch="thumbv7em-none-eabi",
|
||||||
|
page_size=4096,
|
||||||
|
kernel_address=0x1000,
|
||||||
|
padding_address=0x30000,
|
||||||
|
app_ldscript="nrf52840dk_layout.ld",
|
||||||
|
app_address=0x40000,
|
||||||
|
pyocd_target="nrf52840",
|
||||||
|
openocd_board="nordic_nrf52840_dongle.cfg",
|
||||||
|
openocd_options=[],
|
||||||
|
openocd_commands={},
|
||||||
|
jlink_if="swd",
|
||||||
|
jlink_device="nrf52840_xxaa",
|
||||||
|
nordic_dfu=True,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
# The STACK_SIZE value below must match the one used in the linker script
|
# The STACK_SIZE value below must match the one used in the linker script
|
||||||
@@ -50,9 +156,9 @@ APP_HEAP_SIZE = 90000
|
|||||||
|
|
||||||
def get_supported_boards():
|
def get_supported_boards():
|
||||||
boards = []
|
boards = []
|
||||||
for name, root in SUPPORTED_BOARDS.items():
|
for name, props in SUPPORTED_BOARDS.items():
|
||||||
if all((os.path.exists(os.path.join(root, "Cargo.toml")),
|
if all((os.path.exists(os.path.join(props.path, "Cargo.toml")),
|
||||||
os.path.exists(os.path.join(root, "Makefile")))):
|
(props.app_ldscript and os.path.exists(props.app_ldscript)))):
|
||||||
boards.append(name)
|
boards.append(name)
|
||||||
return tuple(set(boards))
|
return tuple(set(boards))
|
||||||
|
|
||||||
@@ -79,9 +185,23 @@ def info(msg):
|
|||||||
message=msg))
|
message=msg))
|
||||||
|
|
||||||
|
|
||||||
|
def assert_mandatory_binary(binary):
|
||||||
|
if not shutil.which(binary):
|
||||||
|
fatal(("Couldn't find {} binary. Make sure it is installed and "
|
||||||
|
"that your PATH is set correctly.").format(binary))
|
||||||
|
|
||||||
|
|
||||||
|
def assert_python_library(module):
|
||||||
|
try:
|
||||||
|
__import__(module)
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
fatal(("Couldn't load python3 module {name}. "
|
||||||
|
"Try to run: pip3 install {name}").format(name=module))
|
||||||
|
|
||||||
|
|
||||||
class RemoveConstAction(argparse.Action):
|
class RemoveConstAction(argparse.Action):
|
||||||
|
|
||||||
# pylint: disable=W0622
|
# pylint: disable=redefined-builtin
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
option_strings,
|
option_strings,
|
||||||
dest,
|
dest,
|
||||||
@@ -121,28 +241,34 @@ class OpenSKInstaller:
|
|||||||
self.args = args
|
self.args = args
|
||||||
# Where all the TAB files should go
|
# Where all the TAB files should go
|
||||||
self.tab_folder = os.path.join("target", "tab")
|
self.tab_folder = os.path.join("target", "tab")
|
||||||
# This is the filename that elf2tab command expects in order
|
board = SUPPORTED_BOARDS[self.args.board]
|
||||||
# to create a working TAB file.
|
|
||||||
self.target_elf_filename = os.path.join(self.tab_folder, "cortex-m4.elf")
|
|
||||||
self.tockloader_default_args = argparse.Namespace(
|
self.tockloader_default_args = argparse.Namespace(
|
||||||
arch="cortex-m4",
|
arch=board.arch,
|
||||||
board=getattr(self.args, "board", "nrf52840"),
|
board=self.args.board,
|
||||||
debug=False,
|
debug=False,
|
||||||
force=False,
|
force=False,
|
||||||
jlink=True,
|
jlink=self.args.programmer == "jlink",
|
||||||
jlink_device="nrf52840_xxaa",
|
jlink_device=board.jlink_device,
|
||||||
jlink_if="swd",
|
jlink_if=board.jlink_if,
|
||||||
jlink_speed=1200,
|
jlink_speed=1200,
|
||||||
|
openocd=self.args.programmer == "openocd",
|
||||||
|
openocd_board=board.openocd_board,
|
||||||
jtag=False,
|
jtag=False,
|
||||||
no_bootloader_entry=False,
|
no_bootloader_entry=False,
|
||||||
page_size=4096,
|
page_size=board.page_size,
|
||||||
port=None,
|
port=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
def checked_command_output(self, cmd):
|
def checked_command_output(self, cmd, env=None, cwd=None):
|
||||||
cmd_output = ""
|
cmd_output = ""
|
||||||
try:
|
try:
|
||||||
cmd_output = subprocess.check_output(cmd)
|
cmd_output = subprocess.run(
|
||||||
|
cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
timeout=None,
|
||||||
|
check=True,
|
||||||
|
env=env,
|
||||||
|
cwd=cwd).stdout
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
fatal("Failed to execute {}: {}".format(cmd[0], str(e)))
|
fatal("Failed to execute {}: {}".format(cmd[0], str(e)))
|
||||||
# Unreachable because fatal() will exit
|
# Unreachable because fatal() will exit
|
||||||
@@ -166,38 +292,104 @@ class OpenSKInstaller:
|
|||||||
# Need to update
|
# Need to update
|
||||||
self.checked_command_output(
|
self.checked_command_output(
|
||||||
["rustup", "install", target_toolchain_fullstring])
|
["rustup", "install", target_toolchain_fullstring])
|
||||||
self.checked_command_output(
|
targets = set([x.arch for _, x in SUPPORTED_BOARDS.items()])
|
||||||
["rustup", "target", "add", "thumbv7em-none-eabi"])
|
for arch in targets:
|
||||||
|
self.checked_command_output(["rustup", "target", "add", arch])
|
||||||
info("Rust toolchain up-to-date")
|
info("Rust toolchain up-to-date")
|
||||||
|
|
||||||
def build_and_install_tockos(self):
|
def search_binary(self, name, start_directory="."):
|
||||||
|
for root, _, files in os.walk(start_directory):
|
||||||
|
for fname in files:
|
||||||
|
if fname == name:
|
||||||
|
return os.path.join(root, fname)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def build_tockos(self):
|
||||||
|
info("Building Tock OS for board {}".format(self.args.board))
|
||||||
|
props = SUPPORTED_BOARDS[self.args.board]
|
||||||
|
out_directory = os.path.join(props.path, "target", props.arch, "release")
|
||||||
|
os.makedirs(out_directory, exist_ok=True)
|
||||||
|
rust_flags = [
|
||||||
|
"-C",
|
||||||
|
"link-arg=-Tlayout.ld",
|
||||||
|
"-C",
|
||||||
|
"linker=rust-lld",
|
||||||
|
"-C",
|
||||||
|
"linker-flavor=ld.lld",
|
||||||
|
"-C",
|
||||||
|
"relocation-model=dynamic-no-pic",
|
||||||
|
"-C",
|
||||||
|
"link-arg=-zmax-page-size=512",
|
||||||
|
"--remap-path-prefix={}=".format(os.path.realpath(props.path)),
|
||||||
|
]
|
||||||
|
env = os.environ.copy()
|
||||||
|
env["RUSTFLAGS"] = " ".join(rust_flags)
|
||||||
self.checked_command_output(
|
self.checked_command_output(
|
||||||
["make", "-C", SUPPORTED_BOARDS[self.args.board], "flash"])
|
["cargo", "build", "--release", "--target={}".format(props.arch)],
|
||||||
|
env=env,
|
||||||
def build_and_install_example(self):
|
cwd=props.path)
|
||||||
assert self.args.application
|
info("Converting Tock OS file into a binary")
|
||||||
|
kernel_name = os.path.basename(props.path)
|
||||||
|
shutil.copyfile(
|
||||||
|
os.path.join(out_directory, kernel_name),
|
||||||
|
os.path.join(out_directory, "{}.elf".format(kernel_name)))
|
||||||
|
# Find appropriate llvm-objcopy
|
||||||
|
llvm_dir = self.checked_command_output(["rustc", "--print=sysroot"],
|
||||||
|
cwd=props.path).strip()
|
||||||
|
if not llvm_dir:
|
||||||
|
fatal("Couldn't determine where rustc is installed. "
|
||||||
|
"This shouldn't happen.")
|
||||||
|
if not os.path.isdir(llvm_dir):
|
||||||
|
fatal("Something went wrong while locating llvm-objcopy.")
|
||||||
|
objcopy = self.search_binary("llvm-objcopy", start_directory=llvm_dir)
|
||||||
|
if not objcopy:
|
||||||
|
fatal("Couldn't locate llvm-objcopy binary in your system.")
|
||||||
self.checked_command_output([
|
self.checked_command_output([
|
||||||
"cargo", "build", "--release", "--target=thumbv7em-none-eabi",
|
objcopy, "--output-target=binary",
|
||||||
"--features={}".format(",".join(self.args.features)), "--example",
|
os.path.join(out_directory, "{}.elf".format(kernel_name)),
|
||||||
self.args.application
|
os.path.join(out_directory, "{}.bin".format(kernel_name))
|
||||||
])
|
])
|
||||||
self.install_elf_file(
|
|
||||||
os.path.join("target/thumbv7em-none-eabi/release/examples",
|
|
||||||
self.args.application))
|
|
||||||
|
|
||||||
def build_and_install_opensk(self):
|
def build_example(self):
|
||||||
assert self.args.application
|
info("Building example {}".format(self.args.application))
|
||||||
|
self._build_app_or_example(is_example=True)
|
||||||
|
|
||||||
|
def build_opensk(self):
|
||||||
info("Building OpenSK application")
|
info("Building OpenSK application")
|
||||||
self.checked_command_output([
|
self._build_app_or_example(is_example=False)
|
||||||
"cargo",
|
|
||||||
"build",
|
def _build_app_or_example(self, is_example):
|
||||||
"--release",
|
assert self.args.application
|
||||||
"--target=thumbv7em-none-eabi",
|
# Ideally we would build a TAB file for all boards at once but depending on
|
||||||
"--features={}".format(",".join(self.args.features)),
|
# the chip on the board, the link script could be totally different.
|
||||||
])
|
# And elf2tab doesn't seem to let us set the boards a TAB file has been
|
||||||
self.install_elf_file(
|
# created for. So at the moment we only build for the selected board.
|
||||||
os.path.join("target/thumbv7em-none-eabi/release",
|
props = SUPPORTED_BOARDS[self.args.board]
|
||||||
self.args.application))
|
rust_flags = [
|
||||||
|
"-C",
|
||||||
|
"link-arg=-T{}".format(props.app_ldscript),
|
||||||
|
"-C",
|
||||||
|
"relocation-model=static",
|
||||||
|
"-D",
|
||||||
|
"warnings",
|
||||||
|
"--remap-path-prefix={}=".format(os.getcwd()),
|
||||||
|
]
|
||||||
|
env = os.environ.copy()
|
||||||
|
env["RUSTFLAGS"] = " ".join(rust_flags)
|
||||||
|
|
||||||
|
command = [
|
||||||
|
"cargo", "build", "--release", "--target={}".format(props.arch),
|
||||||
|
"--features={}".format(",".join(self.args.features))
|
||||||
|
]
|
||||||
|
if is_example:
|
||||||
|
command.extend(["--example", self.args.application])
|
||||||
|
self.checked_command_output(command, env=env)
|
||||||
|
app_path = os.path.join("target", props.arch, "release")
|
||||||
|
if is_example:
|
||||||
|
app_path = os.path.join(app_path, "examples")
|
||||||
|
app_path = os.path.join(app_path, self.args.application)
|
||||||
|
# Create a TAB file
|
||||||
|
self.create_tab_file({props.arch: app_path})
|
||||||
|
|
||||||
def generate_crypto_materials(self, force_regenerate):
|
def generate_crypto_materials(self, force_regenerate):
|
||||||
has_error = subprocess.call([
|
has_error = subprocess.call([
|
||||||
@@ -208,8 +400,11 @@ class OpenSKInstaller:
|
|||||||
error(("Something went wrong while trying to generate ECC "
|
error(("Something went wrong while trying to generate ECC "
|
||||||
"key and/or certificate for OpenSK"))
|
"key and/or certificate for OpenSK"))
|
||||||
|
|
||||||
def install_elf_file(self, elf_path):
|
def create_tab_file(self, binaries):
|
||||||
|
assert binaries
|
||||||
assert self.args.application
|
assert self.args.application
|
||||||
|
info("Generating Tock TAB file for application/example {}".format(
|
||||||
|
self.args.application))
|
||||||
package_parameter = "-n"
|
package_parameter = "-n"
|
||||||
elf2tab_ver = self.checked_command_output(["elf2tab", "--version"]).split(
|
elf2tab_ver = self.checked_command_output(["elf2tab", "--version"]).split(
|
||||||
" ", maxsplit=1)[1]
|
" ", maxsplit=1)[1]
|
||||||
@@ -221,17 +416,26 @@ class OpenSKInstaller:
|
|||||||
os.makedirs(self.tab_folder, exist_ok=True)
|
os.makedirs(self.tab_folder, exist_ok=True)
|
||||||
tab_filename = os.path.join(self.tab_folder,
|
tab_filename = os.path.join(self.tab_folder,
|
||||||
"{}.tab".format(self.args.application))
|
"{}.tab".format(self.args.application))
|
||||||
shutil.copyfile(elf_path, self.target_elf_filename)
|
elf2tab_args = [
|
||||||
self.checked_command_output([
|
"elf2tab", package_parameter, self.args.application, "-o", tab_filename
|
||||||
"elf2tab", package_parameter, self.args.application, "-o", tab_filename,
|
]
|
||||||
self.target_elf_filename, "--stack={}".format(STACK_SIZE),
|
for arch, app_file in binaries.items():
|
||||||
"--app-heap={}".format(APP_HEAP_SIZE), "--kernel-heap=1024",
|
dest_file = os.path.join(self.tab_folder, "{}.elf".format(arch))
|
||||||
"--protected-region-size=64"
|
shutil.copyfile(app_file, dest_file)
|
||||||
|
elf2tab_args.append(dest_file)
|
||||||
|
|
||||||
|
elf2tab_args.extend([
|
||||||
|
"--stack={}".format(STACK_SIZE), "--app-heap={}".format(APP_HEAP_SIZE),
|
||||||
|
"--kernel-heap=1024", "--protected-region-size=64"
|
||||||
])
|
])
|
||||||
self.install_padding()
|
self.checked_command_output(elf2tab_args)
|
||||||
|
|
||||||
|
def install_tab_file(self, tab_filename):
|
||||||
|
assert self.args.application
|
||||||
info("Installing Tock application {}".format(self.args.application))
|
info("Installing Tock application {}".format(self.args.application))
|
||||||
|
board_props = SUPPORTED_BOARDS[self.args.board]
|
||||||
args = copy.copy(self.tockloader_default_args)
|
args = copy.copy(self.tockloader_default_args)
|
||||||
setattr(args, "app_address", 0x40000)
|
setattr(args, "app_address", board_props.app_address)
|
||||||
setattr(args, "erase", self.args.clear_apps)
|
setattr(args, "erase", self.args.clear_apps)
|
||||||
setattr(args, "make", False)
|
setattr(args, "make", False)
|
||||||
setattr(args, "no_replace", False)
|
setattr(args, "no_replace", False)
|
||||||
@@ -244,16 +448,38 @@ class OpenSKInstaller:
|
|||||||
fatal("Couldn't install Tock application {}: {}".format(
|
fatal("Couldn't install Tock application {}: {}".format(
|
||||||
self.args.application, str(e)))
|
self.args.application, str(e)))
|
||||||
|
|
||||||
def install_padding(self):
|
def get_padding(self):
|
||||||
fake_header = tbfh.TBFHeader("")
|
fake_header = tbfh.TBFHeader("")
|
||||||
fake_header.version = 2
|
fake_header.version = 2
|
||||||
fake_header.fields["header_size"] = 0x10
|
fake_header.fields["header_size"] = 0x10
|
||||||
fake_header.fields["total_size"] = 0x10000
|
fake_header.fields["total_size"] = (
|
||||||
|
SUPPORTED_BOARDS[self.args.board].app_address -
|
||||||
|
SUPPORTED_BOARDS[self.args.board].padding_address)
|
||||||
fake_header.fields["flags"] = 0
|
fake_header.fields["flags"] = 0
|
||||||
padding = fake_header.get_binary()
|
return fake_header.get_binary()
|
||||||
|
|
||||||
|
def install_tock_os(self):
|
||||||
|
board_props = SUPPORTED_BOARDS[self.args.board]
|
||||||
|
kernel_file = os.path.join(board_props.path, "target", board_props.arch,
|
||||||
|
"release", "{}.bin".format(self.args.board))
|
||||||
|
info("Flashing file {}.".format(kernel_file))
|
||||||
|
with open(kernel_file, "rb") as f:
|
||||||
|
kernel = f.read()
|
||||||
|
args = copy.copy(self.tockloader_default_args)
|
||||||
|
setattr(args, "address", board_props.app_address)
|
||||||
|
tock = loader.TockLoader(args)
|
||||||
|
tock.open(args)
|
||||||
|
try:
|
||||||
|
tock.flash_binary(kernel, board_props.kernel_address)
|
||||||
|
except TockLoaderException as e:
|
||||||
|
fatal("Couldn't install padding: {}".format(str(e)))
|
||||||
|
|
||||||
|
def install_padding(self):
|
||||||
|
padding = self.get_padding()
|
||||||
|
board_props = SUPPORTED_BOARDS[self.args.board]
|
||||||
info("Flashing padding application")
|
info("Flashing padding application")
|
||||||
args = copy.copy(self.tockloader_default_args)
|
args = copy.copy(self.tockloader_default_args)
|
||||||
setattr(args, "address", 0x30000)
|
setattr(args, "address", board_props.padding_address)
|
||||||
tock = loader.TockLoader(args)
|
tock = loader.TockLoader(args)
|
||||||
tock.open(args)
|
tock.open(args)
|
||||||
try:
|
try:
|
||||||
@@ -263,7 +489,8 @@ class OpenSKInstaller:
|
|||||||
|
|
||||||
def clear_apps(self):
|
def clear_apps(self):
|
||||||
args = copy.copy(self.tockloader_default_args)
|
args = copy.copy(self.tockloader_default_args)
|
||||||
setattr(args, "app_address", 0x40000)
|
board_props = SUPPORTED_BOARDS[self.args.board]
|
||||||
|
setattr(args, "app_address", board_props.app_address)
|
||||||
info("Erasing all installed applications")
|
info("Erasing all installed applications")
|
||||||
tock = loader.TockLoader(args)
|
tock = loader.TockLoader(args)
|
||||||
tock.open(args)
|
tock.open(args)
|
||||||
@@ -271,11 +498,13 @@ class OpenSKInstaller:
|
|||||||
tock.erase_apps(False)
|
tock.erase_apps(False)
|
||||||
except TockLoaderException as e:
|
except TockLoaderException as e:
|
||||||
# Erasing apps is not critical
|
# Erasing apps is not critical
|
||||||
info(("A non-critical error occured while erasing "
|
info(("A non-critical error occurred while erasing "
|
||||||
"apps: {}".format(str(e))))
|
"apps: {}".format(str(e))))
|
||||||
|
|
||||||
# pylint: disable=W0212
|
# pylint: disable=protected-access
|
||||||
def verify_flashed_app(self, expected_app):
|
def verify_flashed_app(self, expected_app):
|
||||||
|
if self.args.programmer not in ("jlink", "openocd"):
|
||||||
|
return False
|
||||||
args = copy.copy(self.tockloader_default_args)
|
args = copy.copy(self.tockloader_default_args)
|
||||||
tock = loader.TockLoader(args)
|
tock = loader.TockLoader(args)
|
||||||
app_found = False
|
app_found = False
|
||||||
@@ -284,51 +513,192 @@ class OpenSKInstaller:
|
|||||||
app_found = expected_app in apps
|
app_found = expected_app in apps
|
||||||
return app_found
|
return app_found
|
||||||
|
|
||||||
|
def create_hex_file(self, dest_file):
|
||||||
|
# We produce an intelhex file with everything in it
|
||||||
|
# pylint: disable=g-import-not-at-top,import-outside-toplevel
|
||||||
|
import intelhex
|
||||||
|
board_props = SUPPORTED_BOARDS[self.args.board]
|
||||||
|
final_hex = intelhex.IntelHex()
|
||||||
|
|
||||||
|
if self.args.tockos:
|
||||||
|
# Process kernel
|
||||||
|
kernel_path = os.path.join(board_props.path, "target", board_props.arch,
|
||||||
|
"release", "{}.bin".format(self.args.board))
|
||||||
|
with open(kernel_path, "rb") as kernel:
|
||||||
|
kern_hex = intelhex.IntelHex()
|
||||||
|
kern_hex.frombytes(kernel.read(), offset=board_props.kernel_address)
|
||||||
|
final_hex.merge(kern_hex, overlap="error")
|
||||||
|
|
||||||
|
# Add padding
|
||||||
|
if board_props.padding_address:
|
||||||
|
padding_hex = intelhex.IntelHex()
|
||||||
|
padding_hex.frombytes(
|
||||||
|
self.get_padding(), offset=board_props.padding_address)
|
||||||
|
final_hex.merge(padding_hex, overlap="error")
|
||||||
|
|
||||||
|
# Now we can add the application from the TAB file
|
||||||
|
app_tab_path = "target/tab/{}.tab".format(self.args.application)
|
||||||
|
assert os.path.exists(app_tab_path)
|
||||||
|
app_tab = tab.TAB(app_tab_path)
|
||||||
|
if board_props.arch not in app_tab.get_supported_architectures():
|
||||||
|
fatal(("It seems that the TAB file was not produced for the "
|
||||||
|
"architecture {}".format(board_props.arch)))
|
||||||
|
app_hex = intelhex.IntelHex()
|
||||||
|
app_hex.frombytes(
|
||||||
|
app_tab.extract_app(board_props.arch).get_binary(),
|
||||||
|
offset=board_props.app_address)
|
||||||
|
final_hex.merge(app_hex)
|
||||||
|
info("Generating all-merged HEX file: {}".format(dest_file))
|
||||||
|
final_hex.tofile(dest_file, format="hex")
|
||||||
|
|
||||||
|
def check_prerequisites(self):
|
||||||
|
if self.args.programmer == "jlink":
|
||||||
|
assert_mandatory_binary("JLinkExe")
|
||||||
|
|
||||||
|
if self.args.programmer == "openocd":
|
||||||
|
assert_mandatory_binary("openocd")
|
||||||
|
|
||||||
|
if self.args.programmer == "pyocd":
|
||||||
|
assert_mandatory_binary("pyocd")
|
||||||
|
assert_python_library("intelhex")
|
||||||
|
if not SUPPORTED_BOARDS[self.args.board].pyocd_target:
|
||||||
|
fatal("This board doesn't seem to support flashing through pyocd.")
|
||||||
|
|
||||||
|
if self.args.programmer == "nordicdfu":
|
||||||
|
assert_mandatory_binary("nrfutil")
|
||||||
|
assert_python_library("intelhex")
|
||||||
|
assert_python_library("nordicsemi.lister")
|
||||||
|
if not SUPPORTED_BOARDS[self.args.board].nordic_dfu:
|
||||||
|
fatal("This board doesn't support flashing over DFU.")
|
||||||
|
|
||||||
|
if self.args.programmer == "none":
|
||||||
|
assert_python_library("intelhex")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if self.args.action is None:
|
if self.args.listing == "boards":
|
||||||
# Nothing to do
|
print(os.linesep.join(get_supported_boards()))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
if self.args.listing == "programmers":
|
||||||
|
print(os.linesep.join(PROGRAMMERS))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if self.args.listing:
|
||||||
|
# Missing check?
|
||||||
|
fatal("Listing {} is not implemented.".format(self.args.listing))
|
||||||
|
|
||||||
|
self.check_prerequisites()
|
||||||
self.update_rustc_if_needed()
|
self.update_rustc_if_needed()
|
||||||
|
|
||||||
if self.args.action == "os":
|
|
||||||
info("Installing Tock on board {}".format(self.args.board))
|
|
||||||
self.build_and_install_tockos()
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if self.args.action == "app":
|
|
||||||
if self.args.application is None:
|
if self.args.application is None:
|
||||||
fatal("Unspecified application")
|
fatal("Please specify an application to be flashed")
|
||||||
if self.args.clear_apps:
|
|
||||||
self.clear_apps()
|
# Compile what needs to be compiled
|
||||||
|
if self.args.tockos:
|
||||||
|
self.build_tockos()
|
||||||
|
|
||||||
if self.args.application == "ctap2":
|
if self.args.application == "ctap2":
|
||||||
self.generate_crypto_materials(self.args.regenerate_keys)
|
self.generate_crypto_materials(self.args.regenerate_keys)
|
||||||
self.build_and_install_opensk()
|
self.build_opensk()
|
||||||
else:
|
else:
|
||||||
self.build_and_install_example()
|
self.build_example()
|
||||||
|
|
||||||
|
# Flashing
|
||||||
|
board_props = SUPPORTED_BOARDS[self.args.board]
|
||||||
|
if self.args.programmer in ("jlink", "openocd"):
|
||||||
|
# We rely on Tockloader to do the job
|
||||||
|
if self.args.clear_apps:
|
||||||
|
self.clear_apps()
|
||||||
|
if self.args.tockos:
|
||||||
|
# Install Tock OS
|
||||||
|
self.install_tock_os()
|
||||||
|
# Install padding and application
|
||||||
|
self.install_padding()
|
||||||
|
self.install_tab_file("target/tab/{}.tab".format(self.args.application))
|
||||||
if self.verify_flashed_app(self.args.application):
|
if self.verify_flashed_app(self.args.application):
|
||||||
info("You're all set!")
|
info("You're all set!")
|
||||||
return 0
|
return 0
|
||||||
error(("It seems that something went wrong. "
|
error(("It seems that something went wrong. App/example not found "
|
||||||
"App/example not found on your board."))
|
"on your board. Ensure the connections between the programmer and "
|
||||||
|
"the board are correct."))
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
if self.args.programmer in ("pyocd", "nordicdfu", "none"):
|
||||||
|
dest_file = "target/{}_merged.hex".format(self.args.board)
|
||||||
|
self.create_hex_file(dest_file)
|
||||||
|
|
||||||
|
if self.args.programmer == "pyocd":
|
||||||
|
info("Flashing HEX file")
|
||||||
|
self.checked_command_output([
|
||||||
|
"pyocd", "flash", "--target={}".format(board_props.pyocd_target),
|
||||||
|
"--format=hex", "--erase=auto", dest_file
|
||||||
|
])
|
||||||
|
if self.args.programmer == "nordicdfu":
|
||||||
|
info("Creating DFU package")
|
||||||
|
dfu_pkg_file = "target/{}_dfu.zip".format(self.args.board)
|
||||||
|
self.checked_command_output([
|
||||||
|
"nrfutil", "pkg", "generate", "--hw-version=52", "--sd-req=0",
|
||||||
|
"--application-version=1", "--application={}".format(dest_file),
|
||||||
|
dfu_pkg_file
|
||||||
|
])
|
||||||
|
info(
|
||||||
|
"Please insert the dongle and switch it to DFU mode by keeping the "
|
||||||
|
"button pressed while inserting...")
|
||||||
|
info("Press [ENTER] when ready.")
|
||||||
|
_ = input()
|
||||||
|
# Search for the DFU devices
|
||||||
|
serial_number = []
|
||||||
|
# pylint: disable=g-import-not-at-top,import-outside-toplevel
|
||||||
|
from nordicsemi.lister import device_lister
|
||||||
|
for device in device_lister.DeviceLister().enumerate():
|
||||||
|
if device.vendor_id == "1915" and device.product_id == "521F":
|
||||||
|
serial_number.append(device.serial_number)
|
||||||
|
if not serial_number:
|
||||||
|
fatal("Couldn't find any DFU device on your system.")
|
||||||
|
if len(serial_number) > 1:
|
||||||
|
fatal("Multiple DFU devices are detected. Please only connect one.")
|
||||||
|
# Run the command without capturing stdout so that we show progress
|
||||||
|
info("Flashing device using DFU...")
|
||||||
|
return subprocess.run(
|
||||||
|
[
|
||||||
|
"nrfutil", "dfu", "usb-serial",
|
||||||
|
"--package={}".format(dfu_pkg_file),
|
||||||
|
"--serial-number={}".format(serial_number[0])
|
||||||
|
],
|
||||||
|
check=False,
|
||||||
|
timeout=None,
|
||||||
|
).returncode
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
# Make sure the current working directory is the right one before running
|
# Make sure the current working directory is the right one before running
|
||||||
os.chdir(os.path.realpath(os.path.dirname(__file__)))
|
os.chdir(os.path.realpath(os.path.dirname(__file__)))
|
||||||
# Check for pre-requisite executable files.
|
|
||||||
if not shutil.which("JLinkExe"):
|
|
||||||
fatal(("Couldn't find JLinkExe binary. Make sure Segger JLink tools "
|
|
||||||
"are installed and correctly set up."))
|
|
||||||
|
|
||||||
OpenSKInstaller(args).run()
|
OpenSKInstaller(args).run()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
shared_parser = argparse.ArgumentParser(add_help=False)
|
main_parser = argparse.ArgumentParser()
|
||||||
shared_parser.add_argument(
|
action_group = main_parser.add_mutually_exclusive_group(required=True)
|
||||||
|
action_group.add_argument(
|
||||||
|
"--list",
|
||||||
|
metavar="WHAT",
|
||||||
|
choices=("boards", "programmers"),
|
||||||
|
default=None,
|
||||||
|
dest="listing",
|
||||||
|
help=("List supported boards or programmers, 1 per line and then exit."),
|
||||||
|
)
|
||||||
|
action_group.add_argument(
|
||||||
|
"--board",
|
||||||
|
metavar="BOARD_NAME",
|
||||||
|
dest="board",
|
||||||
|
default=None,
|
||||||
|
choices=get_supported_boards(),
|
||||||
|
help="Indicates which board Tock OS will be compiled for.",
|
||||||
|
)
|
||||||
|
|
||||||
|
main_parser.add_argument(
|
||||||
"--dont-clear-apps",
|
"--dont-clear-apps",
|
||||||
action="store_false",
|
action="store_false",
|
||||||
default=True,
|
default=True,
|
||||||
@@ -336,32 +706,26 @@ if __name__ == "__main__":
|
|||||||
help=("When installing an application, previously installed "
|
help=("When installing an application, previously installed "
|
||||||
"applications won't be erased from the board."),
|
"applications won't be erased from the board."),
|
||||||
)
|
)
|
||||||
|
main_parser.add_argument(
|
||||||
main_parser = argparse.ArgumentParser()
|
"--programmer",
|
||||||
commands = main_parser.add_subparsers(
|
metavar="METHOD",
|
||||||
dest="action",
|
dest="programmer",
|
||||||
help=("Indicates which part of the firmware should be compiled and "
|
choices=PROGRAMMERS,
|
||||||
"flashed to the connected board."))
|
default="jlink",
|
||||||
|
help=("Sets the method to be used to flash Tock OS or the application "
|
||||||
os_commands = commands.add_parser(
|
"on the target board."),
|
||||||
"os",
|
|
||||||
parents=[shared_parser],
|
|
||||||
help=("Compiles and installs Tock OS. The target board must be "
|
|
||||||
"specified by setting the --board argument."),
|
|
||||||
)
|
)
|
||||||
os_commands.add_argument(
|
|
||||||
"--board",
|
|
||||||
metavar="BOARD_NAME",
|
|
||||||
dest="board",
|
|
||||||
choices=get_supported_boards(),
|
|
||||||
help="Indicates which board Tock OS will be compiled for.",
|
|
||||||
required=True)
|
|
||||||
|
|
||||||
app_commands = commands.add_parser(
|
main_parser.add_argument(
|
||||||
"app",
|
"--no-tockos",
|
||||||
parents=[shared_parser],
|
action="store_false",
|
||||||
help="compiles and installs an application.")
|
default=True,
|
||||||
app_commands.add_argument(
|
dest="tockos",
|
||||||
|
help=("Only compiles and flash the application/example. "
|
||||||
|
"Otherwise TockOS will also be bundled and flashed."),
|
||||||
|
)
|
||||||
|
|
||||||
|
main_parser.add_argument(
|
||||||
"--panic-console",
|
"--panic-console",
|
||||||
action="append_const",
|
action="append_const",
|
||||||
const="panic_console",
|
const="panic_console",
|
||||||
@@ -370,7 +734,7 @@ if __name__ == "__main__":
|
|||||||
"output messages before starting blinking the LEDs on the "
|
"output messages before starting blinking the LEDs on the "
|
||||||
"board."),
|
"board."),
|
||||||
)
|
)
|
||||||
app_commands.add_argument(
|
main_parser.add_argument(
|
||||||
"--debug-allocations",
|
"--debug-allocations",
|
||||||
action="append_const",
|
action="append_const",
|
||||||
const="debug_allocations",
|
const="debug_allocations",
|
||||||
@@ -378,7 +742,7 @@ if __name__ == "__main__":
|
|||||||
help=("The console will be used to output allocator statistics every "
|
help=("The console will be used to output allocator statistics every "
|
||||||
"time an allocation/deallocation happens."),
|
"time an allocation/deallocation happens."),
|
||||||
)
|
)
|
||||||
app_commands.add_argument(
|
main_parser.add_argument(
|
||||||
"--no-u2f",
|
"--no-u2f",
|
||||||
action=RemoveConstAction,
|
action=RemoveConstAction,
|
||||||
const="with_ctap1",
|
const="with_ctap1",
|
||||||
@@ -386,7 +750,7 @@ if __name__ == "__main__":
|
|||||||
help=("Compiles the OpenSK application without backward compatible "
|
help=("Compiles the OpenSK application without backward compatible "
|
||||||
"support for U2F/CTAP1 protocol."),
|
"support for U2F/CTAP1 protocol."),
|
||||||
)
|
)
|
||||||
app_commands.add_argument(
|
main_parser.add_argument(
|
||||||
"--regen-keys",
|
"--regen-keys",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
default=False,
|
default=False,
|
||||||
@@ -396,7 +760,7 @@ if __name__ == "__main__":
|
|||||||
"This is useful to allow flashing multiple OpenSK authenticators "
|
"This is useful to allow flashing multiple OpenSK authenticators "
|
||||||
"in a row without them being considered clones."),
|
"in a row without them being considered clones."),
|
||||||
)
|
)
|
||||||
app_commands.add_argument(
|
main_parser.add_argument(
|
||||||
"--debug",
|
"--debug",
|
||||||
action="append_const",
|
action="append_const",
|
||||||
const="debug_ctap",
|
const="debug_ctap",
|
||||||
@@ -405,7 +769,7 @@ if __name__ == "__main__":
|
|||||||
"(i.e. more debug messages will be sent over the console port "
|
"(i.e. more debug messages will be sent over the console port "
|
||||||
"such as hexdumps of packets)."),
|
"such as hexdumps of packets)."),
|
||||||
)
|
)
|
||||||
app_commands.add_argument(
|
main_parser.add_argument(
|
||||||
"--no-persistent-storage",
|
"--no-persistent-storage",
|
||||||
action="append_const",
|
action="append_const",
|
||||||
const="ram_storage",
|
const="ram_storage",
|
||||||
@@ -413,7 +777,8 @@ if __name__ == "__main__":
|
|||||||
help=("Compiles and installs the OpenSK application without persistent "
|
help=("Compiles and installs the OpenSK application without persistent "
|
||||||
"storage (i.e. unplugging the key will reset the key)."),
|
"storage (i.e. unplugging the key will reset the key)."),
|
||||||
)
|
)
|
||||||
apps_group = app_commands.add_mutually_exclusive_group()
|
|
||||||
|
apps_group = main_parser.add_mutually_exclusive_group()
|
||||||
apps_group.add_argument(
|
apps_group.add_argument(
|
||||||
"--opensk",
|
"--opensk",
|
||||||
dest="application",
|
dest="application",
|
||||||
@@ -428,6 +793,6 @@ if __name__ == "__main__":
|
|||||||
help=("Compiles and installs the crypto_bench example that tests "
|
help=("Compiles and installs the crypto_bench example that tests "
|
||||||
"the performance of the cryptographic algorithms on the board."))
|
"the performance of the cryptographic algorithms on the board."))
|
||||||
|
|
||||||
app_commands.set_defaults(features=["with_ctap1"])
|
main_parser.set_defaults(features=["with_ctap1"])
|
||||||
|
|
||||||
main(main_parser.parse_args())
|
main(main_parser.parse_args())
|
||||||
|
|||||||
144
docs/install.md
144
docs/install.md
@@ -16,8 +16,9 @@ You will need one the following supported boards:
|
|||||||
scenarios as the JTAG probe is already on the board.
|
scenarios as the JTAG probe is already on the board.
|
||||||
* [Nordic nRF52840 Dongle](https://www.nordicsemi.com/Software-and-tools/Development-Kits/nRF52840-Dongle)
|
* [Nordic nRF52840 Dongle](https://www.nordicsemi.com/Software-and-tools/Development-Kits/nRF52840-Dongle)
|
||||||
to have a more practical form factor.
|
to have a more practical form factor.
|
||||||
|
* [Makerdiary nRF52840-MDK USB dongle](https://wiki.makerdiary.com/nrf52840-mdk/).
|
||||||
|
|
||||||
In the case of the Nordic USB dongle, you will also need the following extra
|
In the case of the Nordic USB dongle, you may also need the following extra
|
||||||
hardware:
|
hardware:
|
||||||
|
|
||||||
* a [Segger J-Link](https://www.segger.com/products/debug-probes/j-link/) JTAG
|
* a [Segger J-Link](https://www.segger.com/products/debug-probes/j-link/) JTAG
|
||||||
@@ -30,13 +31,18 @@ hardware:
|
|||||||
[Tag-Connect TC2050 retainer clip](http://www.tag-connect.com/TC2050-CLIP)
|
[Tag-Connect TC2050 retainer clip](http://www.tag-connect.com/TC2050-CLIP)
|
||||||
to keep the spring loaded connector pressed to the PCB.
|
to keep the spring loaded connector pressed to the PCB.
|
||||||
|
|
||||||
Although [OpenOCD](http://openocd.org/) should be supported we encountered some
|
Additionnaly, OpenSK supports other ways to flash your board:
|
||||||
issues while trying to flash a firmware with it. Therefore we suggest at the
|
|
||||||
moment to use a
|
|
||||||
[Segger J-Link](https://www.segger.com/products/debug-probes/j-link/) probe
|
|
||||||
instead.
|
|
||||||
|
|
||||||
This guide **does not** cover how to setup the JTAG probe on your system.
|
* [OpenOCD](http://openocd.org/).
|
||||||
|
* [Segger J-Link](https://www.segger.com/products/debug-probes/j-link/)
|
||||||
|
(default method).
|
||||||
|
* [pyOCD](https://pypi.org/project/pyocd/).
|
||||||
|
* [nrfutil](https://pypi.org/project/nrfutil/) for the USB dongle boards that
|
||||||
|
supports it, which allows you to directly flash a working board over USB
|
||||||
|
without additional hardware.
|
||||||
|
|
||||||
|
This guide **does not** cover how to setup the JTAG probe and their related
|
||||||
|
tools on your system.
|
||||||
|
|
||||||
### Software
|
### Software
|
||||||
|
|
||||||
@@ -141,17 +147,17 @@ Our build script `build.rs` is responsible for converting `opensk_cert.pem` and
|
|||||||
|
|
||||||
1. Connect a micro USB cable to the JTAG USB port.
|
1. Connect a micro USB cable to the JTAG USB port.
|
||||||
|
|
||||||
1. Run our script for compiling/flashing Tock OS on your device (_output may
|
1. Run our script for compiling/flashing Tock OS and OpenSK on your device
|
||||||
differ_):
|
(_output may differ_):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ ./deploy.py os --board=nrf52840_dk
|
$ ./deploy.py --board=nrf52840dk --opensk
|
||||||
info: Updating rust toolchain to nightly-2020-02-03
|
info: Updating rust toolchain to nightly-2020-02-03
|
||||||
info: syncing channel updates for 'nightly-2020-02-03-x86_64-unknown-linux-gnu'
|
info: syncing channel updates for 'nightly-2020-02-03-x86_64-unknown-linux-gnu'
|
||||||
info: checking for self-updates
|
info: checking for self-updates
|
||||||
info: component 'rust-std' for target 'thumbv7em-none-eabi' is up to date
|
info: component 'rust-std' for target 'thumbv7em-none-eabi' is up to date
|
||||||
info: Rust toolchain up-to-date
|
info: Rust toolchain up-to-date
|
||||||
info: Installing Tock on board nrf52840_dk
|
info: Building Tock OS for board nrf52840dk
|
||||||
Compiling tock-registers v0.5.0 (./third_party/tock/libraries/tock-register-interface)
|
Compiling tock-registers v0.5.0 (./third_party/tock/libraries/tock-register-interface)
|
||||||
Compiling tock-cells v0.1.0 (./third_party/tock/libraries/tock-cells)
|
Compiling tock-cells v0.1.0 (./third_party/tock/libraries/tock-cells)
|
||||||
Compiling enum_primitive v0.1.0 (./third_party/tock/libraries/enum_primitive)
|
Compiling enum_primitive v0.1.0 (./third_party/tock/libraries/enum_primitive)
|
||||||
@@ -166,47 +172,17 @@ Our build script `build.rs` is responsible for converting `opensk_cert.pem` and
|
|||||||
Compiling nrf52840 v0.1.0 (./third_party/tock/chips/nrf52840)
|
Compiling nrf52840 v0.1.0 (./third_party/tock/chips/nrf52840)
|
||||||
Compiling components v0.1.0 (./third_party/tock/boards/components)
|
Compiling components v0.1.0 (./third_party/tock/boards/components)
|
||||||
Compiling nrf52dk_base v0.1.0 (./third_party/tock/boards/nordic/nrf52dk_base)
|
Compiling nrf52dk_base v0.1.0 (./third_party/tock/boards/nordic/nrf52dk_base)
|
||||||
Finished release [optimized + debuginfo] target(s) in 11.97s
|
Finished release [optimized + debuginfo] target(s) in 13.15s
|
||||||
[STATUS ] Flashing binar(y|ies) to board...
|
info: Converting Tock OS file into a binary
|
||||||
[INFO ] Using known arch and jtag-device for known board nrf52dk
|
info: Building OpenSK application
|
||||||
[INFO ] Finished in 0.284 seconds
|
Finished release [optimized] target(s) in 0.02s
|
||||||
```
|
info: Generating Tock TAB file for application/example ctap2
|
||||||
|
|
||||||
1. Run our script for compiling/flashing the OpenSK application on your device
|
|
||||||
(_output may differ_):
|
|
||||||
|
|
||||||
```shell
|
|
||||||
$ ./deploy.py app --opensk
|
|
||||||
info: Updating rust toolchain to nightly-2020-02-03
|
|
||||||
info: syncing channel updates for 'nightly-2020-02-03-x86_64-unknown-linux-gnu'
|
|
||||||
info: checking for self-updates
|
|
||||||
info: component 'rust-std' for target 'thumbv7em-none-eabi' is up to date
|
|
||||||
info: Rust toolchain up-to-date
|
|
||||||
info: Erasing all installed applications
|
info: Erasing all installed applications
|
||||||
All apps have been erased.
|
All apps have been erased.
|
||||||
info: Building OpenSK application
|
info: Flashing file third_party/tock/boards/nordic/nrf52840dk/target/thumbv7em-none-eabi/release/nrf52840dk.bin.
|
||||||
Compiling autocfg v1.0.0
|
|
||||||
Compiling pkg-config v0.3.17
|
|
||||||
Compiling cc v1.0.50
|
|
||||||
Compiling libc v0.2.66
|
|
||||||
Compiling bitflags v1.2.1
|
|
||||||
Compiling foreign-types-shared v0.1.1
|
|
||||||
Compiling openssl v0.10.28
|
|
||||||
Compiling cfg-if v0.1.10
|
|
||||||
Compiling lazy_static v1.4.0
|
|
||||||
Compiling byteorder v1.3.2
|
|
||||||
Compiling linked_list_allocator v0.6.6
|
|
||||||
Compiling arrayref v0.3.6
|
|
||||||
Compiling cbor v0.1.0 (./libraries/cbor)
|
|
||||||
Compiling subtle v2.2.2
|
|
||||||
Compiling foreign-types v0.3.2
|
|
||||||
Compiling libtock v0.1.0 (./third_party/libtock-rs)
|
|
||||||
Compiling crypto v0.1.0 (./libraries/crypto)
|
|
||||||
Compiling openssl-sys v0.9.54
|
|
||||||
Compiling ctap2 v0.1.0 (.)
|
|
||||||
Finished release [optimized] target(s) in 15.34s
|
|
||||||
info: Flashing padding application
|
info: Flashing padding application
|
||||||
info: Installing Tock application ctap2
|
info: Installing Tock application ctap2
|
||||||
|
info: You're all set!
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Connect a micro USB cable to the device USB port.
|
1. Connect a micro USB cable to the device USB port.
|
||||||
@@ -217,6 +193,8 @@ the board in order to see your OpenSK device on your system.
|
|||||||
|
|
||||||
#### Nordic nRF52840 Dongle
|
#### Nordic nRF52840 Dongle
|
||||||
|
|
||||||
|
##### Using external programmer (JLink, OpenOCD, etc.)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
1. The JTAG probe used for programming won't provide power to the board.
|
1. The JTAG probe used for programming won't provide power to the board.
|
||||||
@@ -232,17 +210,18 @@ the board in order to see your OpenSK device on your system.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
1. Run our script for compiling/flashing Tock OS on your device (_output may
|
1. Depending on the programmer you're using, you may have to adapt the next
|
||||||
differ_):
|
command line. Run our script for compiling/flashing Tock OS on your device
|
||||||
|
(_output may differ_):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ ./deploy.py os --board=nrf52840_dongle
|
$ ./deploy.py os --board=nrf52840_dongle --programmer=jlink
|
||||||
info: Updating rust toolchain to nightly-2020-02-03
|
info: Updating rust toolchain to nightly-2020-02-03
|
||||||
info: syncing channel updates for 'nightly-2020-02-03-x86_64-unknown-linux-gnu'
|
info: syncing channel updates for 'nightly-2020-02-03-x86_64-unknown-linux-gnu'
|
||||||
info: checking for self-updates
|
info: checking for self-updates
|
||||||
info: component 'rust-std' for target 'thumbv7em-none-eabi' is up to date
|
info: component 'rust-std' for target 'thumbv7em-none-eabi' is up to date
|
||||||
info: Rust toolchain up-to-date
|
info: Rust toolchain up-to-date
|
||||||
info: Installing Tock on board nrf52840_dongle
|
info: Building Tock OS for board nrf52840_dongle
|
||||||
Compiling tock-cells v0.1.0 (./third_party/tock/libraries/tock-cells)
|
Compiling tock-cells v0.1.0 (./third_party/tock/libraries/tock-cells)
|
||||||
Compiling tock-registers v0.5.0 (./third_party/tock/libraries/tock-register-interface)
|
Compiling tock-registers v0.5.0 (./third_party/tock/libraries/tock-register-interface)
|
||||||
Compiling enum_primitive v0.1.0 (./third_party/tock/libraries/enum_primitive)
|
Compiling enum_primitive v0.1.0 (./third_party/tock/libraries/enum_primitive)
|
||||||
@@ -258,50 +237,39 @@ the board in order to see your OpenSK device on your system.
|
|||||||
Compiling components v0.1.0 (./third_party/tock/boards/components)
|
Compiling components v0.1.0 (./third_party/tock/boards/components)
|
||||||
Compiling nrf52dk_base v0.1.0 (./third_party/tock/boards/nordic/nrf52dk_base)
|
Compiling nrf52dk_base v0.1.0 (./third_party/tock/boards/nordic/nrf52dk_base)
|
||||||
Finished release [optimized + debuginfo] target(s) in 11.72s
|
Finished release [optimized + debuginfo] target(s) in 11.72s
|
||||||
[STATUS ] Flashing binar(y|ies) to board...
|
info: Converting Tock OS file into a binary
|
||||||
[INFO ] Using known arch and jtag-device for known board nrf52dk
|
info: Building OpenSK application
|
||||||
[INFO ] Finished in 0.280 seconds
|
Finished release [optimized] target(s) in 0.02s
|
||||||
```
|
info: Generating Tock TAB file for application/example ctap2
|
||||||
|
|
||||||
1. Run our script for compiling/flashing the OpenSK application on your device
|
|
||||||
(_output may differ_):
|
|
||||||
|
|
||||||
```shell
|
|
||||||
$ ./deploy.py app --opensk
|
|
||||||
info: Updating rust toolchain to nightly-2020-02-03
|
|
||||||
info: syncing channel updates for 'nightly-2020-02-03-x86_64-unknown-linux-gnu'
|
|
||||||
info: checking for self-updates
|
|
||||||
info: component 'rust-std' for target 'thumbv7em-none-eabi' is up to date
|
|
||||||
info: Rust toolchain up-to-date
|
|
||||||
info: Erasing all installed applications
|
info: Erasing all installed applications
|
||||||
All apps have been erased.
|
All apps have been erased.
|
||||||
info: Building OpenSK application
|
info: Flashing file third_party/tock/boards/nordic/nrf52840_dongle/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin.
|
||||||
Compiling autocfg v1.0.0
|
|
||||||
Compiling pkg-config v0.3.17
|
|
||||||
Compiling cc v1.0.50
|
|
||||||
Compiling libc v0.2.66
|
|
||||||
Compiling bitflags v1.2.1
|
|
||||||
Compiling foreign-types-shared v0.1.1
|
|
||||||
Compiling openssl v0.10.28
|
|
||||||
Compiling cfg-if v0.1.10
|
|
||||||
Compiling lazy_static v1.4.0
|
|
||||||
Compiling byteorder v1.3.2
|
|
||||||
Compiling linked_list_allocator v0.6.6
|
|
||||||
Compiling arrayref v0.3.6
|
|
||||||
Compiling cbor v0.1.0 (./libraries/cbor)
|
|
||||||
Compiling subtle v2.2.2
|
|
||||||
Compiling foreign-types v0.3.2
|
|
||||||
Compiling libtock v0.1.0 (./third_party/libtock-rs)
|
|
||||||
Compiling crypto v0.1.0 (./libraries/crypto)
|
|
||||||
Compiling openssl-sys v0.9.54
|
|
||||||
Compiling ctap2 v0.1.0 (.)
|
|
||||||
Finished release [optimized] target(s) in 15.34s
|
|
||||||
info: Flashing padding application
|
info: Flashing padding application
|
||||||
info: Installing Tock application ctap2
|
info: Installing Tock application ctap2
|
||||||
|
info: You're all set!
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Remove the programming cable and the USB-A extension cable.
|
1. Remove the programming cable and the USB-A extension cable.
|
||||||
|
|
||||||
|
### Advanced installation
|
||||||
|
|
||||||
|
Although flashing using a Segger JLink probe is the officially supported way,
|
||||||
|
our tool, `deploy.py` also supports other methods:
|
||||||
|
|
||||||
|
* OpenOCD: `./deploy.py --board=nrf52840_dongle --opensk --programmer=openocd`
|
||||||
|
* pyOCD: `./deploy.py --board=nrf52840_dongle --opensk --programmer=pyocd`
|
||||||
|
* Nordic DFU: `./deploy.py --board=nrf52840_dongle --opensk
|
||||||
|
--programmer=nordicdfu`
|
||||||
|
* Custom: `./deploy.py --board=nrf52840_dongle --opensk --programmer=none`. In
|
||||||
|
this case, an IntelHex file will be created and how to program a board is
|
||||||
|
left to the user.
|
||||||
|
|
||||||
|
If your board is already flashed with Tock OS, you may skip installing it:
|
||||||
|
`./deploy.py --board=nrf52840dk --opensk --no-tockos`
|
||||||
|
|
||||||
|
For more options, we invite you to read the help of our `deploy.py` script by
|
||||||
|
running `./deploy.py --help`.
|
||||||
|
|
||||||
### Installing the udev rule (Linux only)
|
### Installing the udev rule (Linux only)
|
||||||
|
|
||||||
By default on Linux, a USB device will require root privilege in order interact
|
By default on Linux, a USB device will require root privilege in order interact
|
||||||
|
|||||||
23
patches/tock/06-add-set_vector_table_offset.patch
Normal file
23
patches/tock/06-add-set_vector_table_offset.patch
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
diff --git a/arch/cortex-m/src/scb.rs b/arch/cortex-m/src/scb.rs
|
||||||
|
index 8107f16..a271db9 100644
|
||||||
|
--- a/arch/cortex-m/src/scb.rs
|
||||||
|
+++ b/arch/cortex-m/src/scb.rs
|
||||||
|
@@ -9,7 +9,7 @@ use kernel::common::StaticRef;
|
||||||
|
struct ScbRegisters {
|
||||||
|
cpuid: VolatileCell<u32>,
|
||||||
|
icsr: VolatileCell<u32>,
|
||||||
|
- vtor: VolatileCell<u32>,
|
||||||
|
+ vtor: VolatileCell<*const ()>,
|
||||||
|
aircr: VolatileCell<u32>,
|
||||||
|
scr: VolatileCell<u32>,
|
||||||
|
ccr: VolatileCell<u32>,
|
||||||
|
@@ -54,3 +54,8 @@ pub unsafe fn reset() {
|
||||||
|
let reset = (0x5FA << 16) | (aircr & (0x7 << 8)) | (1 << 2);
|
||||||
|
SCB.aircr.set(reset);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+/// relocate interrupt vector table
|
||||||
|
+pub unsafe fn set_vector_table_offset(offset: *const ()) {
|
||||||
|
+ SCB.vtor.set(offset);
|
||||||
|
+}
|
||||||
|
|
||||||
21
patches/tock/07-nrf52-bootloader.patch
Normal file
21
patches/tock/07-nrf52-bootloader.patch
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
diff --git a/chips/nrf52/src/crt1.rs b/chips/nrf52/src/crt1.rs
|
||||||
|
index 9703aac..281ceeb 100644
|
||||||
|
--- a/chips/nrf52/src/crt1.rs
|
||||||
|
+++ b/chips/nrf52/src/crt1.rs
|
||||||
|
@@ -1,4 +1,4 @@
|
||||||
|
-use cortexm4::{generic_isr, hard_fault_handler, nvic, svc_handler, systick_handler};
|
||||||
|
+use cortexm4::{generic_isr, hard_fault_handler, nvic, scb, svc_handler, systick_handler};
|
||||||
|
use tock_rt0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -168,5 +168,9 @@ pub unsafe extern "C" fn init() {
|
||||||
|
tock_rt0::init_data(&mut _etext, &mut _srelocate, &mut _erelocate);
|
||||||
|
tock_rt0::zero_bss(&mut _szero, &mut _ezero);
|
||||||
|
|
||||||
|
+ // Ensure that we are compatible with a bootloader.
|
||||||
|
+ // For this we need to offset our vector table
|
||||||
|
+ scb::set_vector_table_offset(BASE_VECTORS.as_ptr() as *const ());
|
||||||
|
+
|
||||||
|
nvic::enable_all();
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user