Skip to content

Commit

Permalink
boards: add makepython-nrf52840
Browse files Browse the repository at this point in the history
  • Loading branch information
bradjc committed Sep 21, 2023
1 parent 2167772 commit 8eb471f
Show file tree
Hide file tree
Showing 8 changed files with 859 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ members = [
"boards/litex/sim",
"boards/msp_exp432p401r",
"boards/microbit_v2",
"boards/makepython-nrf52840",
"boards/nordic/nrf52840dk",
"boards/nordic/nrf52840_dongle",
"boards/nordic/nrf52dk",
Expand Down
21 changes: 21 additions & 0 deletions boards/makepython-nrf52840/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Licensed under the Apache License, Version 2.0 or the MIT License.
# SPDX-License-Identifier: Apache-2.0 OR MIT
# Copyright Tock Contributors 2022.

[package]
name = "makepython-nrf52840"
version.workspace = true
authors.workspace = true
build = "build.rs"
edition.workspace = true

[dependencies]
cortexm4 = { path = "../../arch/cortex-m4" }
kernel = { path = "../../kernel" }
nrf52 = { path = "../../chips/nrf52" }
nrf52840 = { path = "../../chips/nrf52840" }
components = { path = "../components" }
nrf52_components = { path = "../nordic/nrf52_components" }

capsules-core = { path = "../../capsules/core" }
capsules-extra = { path = "../../capsules/extra" }
24 changes: 24 additions & 0 deletions boards/makepython-nrf52840/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Licensed under the Apache License, Version 2.0 or the MIT License.
# SPDX-License-Identifier: Apache-2.0 OR MIT
# Copyright Tock Contributors 2022.

# Makefile for building the tock kernel for the Arduino Nano 33 BLE board.

TOCK_ARCH=cortex-m4
TARGET=thumbv7em-none-eabi
PLATFORM=makepython-nrf52840

include ../Makefile.common

ifdef PORT
FLAGS += --port $(PORT)
endif

# Default target for installing the kernel.
.PHONY: install
install: program

# Upload the kernel using tockloader and the tock bootloader
.PHONY: program
program: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).bin
tockloader $(FLAGS) flash --address 0x10000 $<
13 changes: 13 additions & 0 deletions boards/makepython-nrf52840/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
MakePython nRF52840
===================

<img src="https://www.makerfabs.com/image/cache/makerfabs/MakePython%20nRF52840/MakePython%20nRF52840-1-1000x750.jpg" width="35%">

The [MakePython nRF52840](https://www.makerfabs.com/makepython-nrf52840.html) is
a development board with the Nordic nRF52840 SoC and a 128 x 64 pixel OLED
display.


## Getting Started

First, follow the [Tock Getting Started guide](../../doc/Getting_Started.md).
8 changes: 8 additions & 0 deletions boards/makepython-nrf52840/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

fn main() {
println!("cargo:rerun-if-changed=layout.ld");
println!("cargo:rerun-if-changed=../kernel_layout.ld");
}
14 changes: 14 additions & 0 deletions boards/makepython-nrf52840/layout.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* Licensed under the Apache License, Version 2.0 or the MIT License. */
/* SPDX-License-Identifier: Apache-2.0 OR MIT */
/* Copyright Tock Contributors 2023. */

MEMORY
{
rom (rx) : ORIGIN = 0x00010000, LENGTH = 256K
prog (rx) : ORIGIN = 0x00050000, LENGTH = 704K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
}

PAGE_SIZE = 4K;

INCLUDE ../kernel_layout.ld
144 changes: 144 additions & 0 deletions boards/makepython-nrf52840/src/io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

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};
use kernel::ErrorCode;
use nrf52840::gpio::Pin;

use crate::CHIP;
use crate::PROCESSES;
use crate::PROCESS_PRINTER;
use kernel::hil::uart::Transmit;
use kernel::utilities::cells::VolatileCell;

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(())
}
}

const BUF_LEN: usize = 512;
static mut STATIC_PANIC_BUF: [u8; BUF_LEN] = [0; BUF_LEN];

static mut DUMMY: DummyUsbClient = DummyUsbClient {
fired: VolatileCell::new(false),
};

struct DummyUsbClient {
fired: VolatileCell<bool>,
}

impl uart::TransmitClient for DummyUsbClient {
fn transmitted_buffer(&self, _: &'static mut [u8], _: usize, _: Result<(), ErrorCode>) {
self.fired.set(true);
}
}

impl IoWrite for Writer {
fn write(&mut self, buf: &[u8]) -> usize {
if !self.initialized {
self.initialized = true;
}
// Here we mimic a synchronous UART output by calling transmit_buffer
// on the CDC stack and then spinning on USB interrupts until the transaction
// is complete. If the USB or CDC stack panicked, this may fail. It will also
// fail if the panic occurred prior to the USB connection being initialized.
// In the latter case, the LEDs should still blink in the panic pattern.

// spin so that if any USB DMA is ongoing it will finish
// we should only need this on the first call to write()
let mut i = 0;
loop {
i += 1;
cortexm4::support::nop();
if i > 10000 {
break;
}
}

// copy_from_slice() requires equal length slices
// This will truncate any writes longer than BUF_LEN, but simplifies the
// code. In practice, BUF_LEN=512 always seems sufficient for the size of
// individual calls to write made by the panic handler.
let mut max = BUF_LEN;
if buf.len() < BUF_LEN {
max = buf.len();
}

unsafe {
// If CDC_REF_FOR_PANIC is not yet set we panicked very early,
// and not much we can do. Don't want to double fault,
// so just return.
super::CDC_REF_FOR_PANIC.map(|cdc| {
// Lots of unsafe dereferencing of global static mut objects here.
// However, this should be okay, because it all happens within
// a single thread, and:
// - This is the only place the global CDC_REF_FOR_PANIC is used, the logic is the same
// as applies for the global CHIP variable used in the panic handler.
// - We do create multiple mutable references to the STATIC_PANIC_BUF, but we never
// access the STATIC_PANIC_BUF after a slice of it is passed to transmit_buffer
// until the slice has been returned in the uart callback.
// - Similarly, only this function uses the global DUMMY variable, and we do not
// mutate it.
let usb = &mut cdc.controller();
STATIC_PANIC_BUF[..max].copy_from_slice(&buf[..max]);
let static_buf = &mut STATIC_PANIC_BUF;
cdc.set_transmit_client(&DUMMY);
let _ = cdc.transmit_buffer(static_buf, max);
loop {
if let Some(interrupt) = cortexm4::nvic::next_pending() {
if interrupt == 39 {
usb.handle_interrupt();
}
let n = cortexm4::nvic::Nvic::new(interrupt);
n.clear_pending();
n.enable();
}
if DUMMY.fired.get() {
// buffer finished transmitting, return so we can output additional
// messages when requested by the panic handler.
break;
}
}
DUMMY.fired.set(false);
});
}
buf.len()
}
}

/// Default panic handler for the Nano 33 Board.
///
/// We just use the standard default provided by the debug module in the kernel.
#[cfg(not(test))]
#[no_mangle]
#[panic_handler]
pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! {
let led_kernel_pin = &nrf52840::gpio::GPIOPin::new(Pin::P1_10);
let led = &mut led::LedLow::new(led_kernel_pin);
let writer = &mut WRITER;
debug::panic(
&mut [led],
writer,
pi,
&cortexm4::support::nop,
&PROCESSES,
&CHIP,
&PROCESS_PRINTER,
)
}
Loading

0 comments on commit 8eb471f

Please sign in to comment.