Skip to content

Commit

Permalink
Merge #2200 #2216
Browse files Browse the repository at this point in the history
2200: Add Teensy 4 board r=bradjc a=mciantyre

### Pull Request Overview

The PR proposes Tock support for the Teensy 4. As of this PR, the Tock kernel, and a variety of small examples, can run on [Teensy 4.0][teensy40] and [Teensy 4.1][teensy41] development boards. The PR builds on the i.MX RT chip foundation added in #1918.

[teensy40]: https://www.pjrc.com/store/teensy40.html
[teensy41]: https://www.pjrc.com/store/teensy41.html

The board makes use of

- the LED on pin 13
- UART2 on pins 14 and 15
- GPT1 as an alarm

The Teensy 4 boards use i.MX RT **1062** chips. Given our current chip features, the 1060 chip family is identical to the 1050 chip family. Before integrating the Teensy 4 board, I *renamed `chips/imxrt1050` to `chips/imxrt10xx`*. I updated the `imxrt1050-evkb` board to use the renamed crate.

Additional changes to the i.MX RT chip crate include

- adding a LPUART2 peripheral
- renaming the `gpt1` module to `gpt`, and adding `GPT2`
- supporting periodic clock selection, allowing a user to select the static crystal oscillator as the GPT clock source

Changes to the chip crate should be backwards compatible for `imxrt1050-evkb` users. Let me know if we see an issue.

### Testing Strategy

I tested the PR by running `blink` and `console` libtock-c examples on both a Teensy 4.0 and 4.1 board. I repackaged the examples [here](https://github.com/mciantyre/tock-teensy4-apps).

The PR was **not** tested on an NXP i.MX RT 1050 evaluation board; I don't have that hardware.

### TODO or Help Wanted

This pull request may be tested on a 1050 evaluation board. @valexandru, if you have an opportunity to test this work and review these changes, I'd appreciate it!

This PR does not address any of the TODOs noted in #1918. In particular, the `imxrt10xx` chip still does not use the new peripheral instantiation approach (#2069). If this is still TODO and not urgent, I'm happy to support that cleanup in a separate PR.

This Teensy 4 support was based on a different chip implementation. That chip implementation supported DMA, and a UART driver that used DMA. If we see value in a DMA driver for i.MX RT chips, I'm happy to contribute the driver.

### Documentation Updated

- [x] ~~Updated the relevant files in `/docs`~~, or **no updates are required**

I've added documentation in `boards/teensy4`. The documentation

- lists the tools that you need to program a Teensy 4
- how to build the kernel and apps
- how to convert the program to a HEX file, which is necessary to program a board

### Formatting

- [x] Ran `make prepush`.

### New Platform Checklist

- [x] Hardware is widely available.
- [x] I can support the platform, which includes release testing for the platform, at least initially.
- Basic features are implemented:
  - [x] `Console`, including `debug!()` and userspace `printf()`.
  - [x] Timers.
  - [x] GPIO with interrupts.

I assume the basic chip features were provided by #1918. Let me know if we need to make all three features available through the board. As of this writing, the Teensy 4 board does not expose an input GPIO that responds to an interrupt.


2216: add 15.4 and ble to nano33ble r=bradjc a=hudson-ayers

### Pull Request Overview

This pull request adds the 15.4 and BLE drivers to the nano33ble, rather than leaving support as commented out, as the comments had already fallen out-of-date.


### Testing Strategy

BLE was tested using the `ble_advertising` and `ble_passive_scanning` apps in `libtock-c`.

15.4 was tested using the `radio_tx` and `radio_rx` apps in `libtock-c` and sending messages back and forth with an nrf52840-dk.

### TODO or Help Wanted

N/A

### Documentation Updated

- [x] No updates are required.

### Formatting

- [x] Ran `make prepush`.


Co-authored-by: Ian McIntyre <ianpmcintyre@gmail.com>
Co-authored-by: Hudson Ayers <hayers@stanford.edu>
Co-authored-by: Hudson Ayers <32688905+hudson-ayers@users.noreply.github.com>
  • Loading branch information
4 people committed Dec 2, 2020
3 parents d8d1f17 + 715c920 + 4fefbfa commit 40d7961
Show file tree
Hide file tree
Showing 29 changed files with 1,360 additions and 129 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Expand Up @@ -23,14 +23,14 @@ members = [
"boards/redboard_artemis_nano",
"boards/stm32f3discovery",
"boards/stm32f412gdiscovery",
"boards/teensy40",
"boards/nano33ble",
"capsules",
"chips/apollo3",
"chips/arty_e21_chip",
"chips/e310x",
"chips/imxrt1050",
"chips/earlgrey",
"chips/imxrt1050",
"chips/imxrt10xx",
"chips/lowrisc",
"chips/msp432",
"chips/nrf52",
Expand Down
1 change: 1 addition & 0 deletions arch/cortex-m7/src/lib.rs
Expand Up @@ -20,6 +20,7 @@ pub use cortexm::svc_handler;
pub use cortexm::syscall;
pub use cortexm::systick;
pub use cortexm::systick_handler;
pub use cortexm::unhandled_interrupt;

/// Provide a `switch_to_user` function with exactly that name for syscall.rs.
#[cfg(all(target_arch = "arm", target_os = "none"))]
Expand Down
1 change: 1 addition & 0 deletions boards/README.md
Expand Up @@ -20,6 +20,7 @@ that Tock supports.
| [STM32F412G Discovery kit](stm32f412gdiscovery/README.md) | ARM Cortex-M4 | STM32F412G | openocd | custom | #1827 |
| [SparkFun RedBoard Artemis Nano](redboard_artemis_nano/README.md) | ARM Cortex-M4 | Apollo3 | custom | custom | No |
| [i.MX RT 1052 Evaluation Kit](imxrt1050-evkb/README.md) | ARM Cortex-M7 | i.MX RT 1052 | custom | custom | No |
| [Teensy 4.0](teensy40/README.md) | ARM Cortex-M7 | i.MX RT 1062 | custom | custom | No |
| [SiFive HiFive1](hifive1/README.md) | RISC-V | FE310-G000 | openocd | tockloader | [Yes (5.1)][qemu] |
| [Digilent Arty A-7 100T](arty_e21/README.md) | RISC-V RV32IMAC | SiFive E21 | openocd | tockloader | No |
| [Earlgrey on Nexys Video](earlgrey_nexysvideo/README.md) | RISC-V RV32IMC | EarlGrey | custom | custom | [Yes (5.1)][qemu] |
Expand Down
2 changes: 1 addition & 1 deletion boards/imxrt1050-evkb/Cargo.toml
Expand Up @@ -10,4 +10,4 @@ components = { path = "../components" }
cortexm7 = { path = "../../arch/cortex-m7" }
capsules = { path = "../../capsules" }
kernel = { path = "../../kernel" }
imxrt1050 = { path = "../../chips/imxrt1050" }
imxrt10xx = { path = "../../chips/imxrt10xx" }
2 changes: 1 addition & 1 deletion boards/imxrt1050-evkb/src/io.rs
Expand Up @@ -7,7 +7,7 @@ use kernel::hil::led;
use kernel::hil::uart;
use kernel::hil::uart::Configure;

use imxrt1050;
use crate::imxrt1050;
use imxrt1050::gpio::PinId;

use crate::CHIP;
Expand Down
21 changes: 11 additions & 10 deletions boards/imxrt1050-evkb/src/main.rs
Expand Up @@ -19,7 +19,6 @@ use kernel::{create_capability, static_init};

// use components::fxos8700::Fxos8700Component;
// use components::ninedof::NineDofComponent;

use imxrt1050::iomuxc::DriveStrength;
use imxrt1050::iomuxc::MuxMode;
use imxrt1050::iomuxc::OpenDrainEn;
Expand All @@ -28,6 +27,7 @@ use imxrt1050::iomuxc::PullKeepEn;
use imxrt1050::iomuxc::PullUpDown;
use imxrt1050::iomuxc::Sion;
use imxrt1050::iomuxc::Speed;
use imxrt10xx as imxrt1050;

// Unit Tests for drivers.
// #[allow(dead_code)]
Expand All @@ -45,7 +45,7 @@ const NUM_PROCS: usize = 1;
// Actual memory for holding the active process structures.
static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] = [None];

static mut CHIP: Option<&'static imxrt1050::chip::Imxrt1050> = None;
static mut CHIP: Option<&'static imxrt1050::chip::Imxrt10xx> = None;

// How should the kernel respond when a process faults.
const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic;
Expand All @@ -67,7 +67,7 @@ pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
struct Imxrt1050EVKB {
alarm: &'static capsules::alarm::AlarmDriver<
'static,
VirtualMuxAlarm<'static, imxrt1050::gpt1::Gpt1<'static>>,
VirtualMuxAlarm<'static, imxrt1050::gpt::Gpt1<'static>>,
>,
button: &'static capsules::button::Button<'static, imxrt1050::gpio::Pin<'static>>,
console: &'static capsules::console::Console<'static>,
Expand Down Expand Up @@ -163,14 +163,15 @@ unsafe fn set_pin_primary_functions() {

/// Helper function for miscellaneous peripheral functions
unsafe fn setup_peripherals() {
use imxrt1050::gpt1::GPT1;
use imxrt1050::ccm::CCM;
use imxrt1050::gpt::GPT1;

// LPUART1 IRQn is 20
cortexm7::nvic::Nvic::new(imxrt1050::nvic::LPUART1).enable();

// TIM2 IRQn is 28
GPT1.enable_clock();
GPT1.start();
GPT1.start(CCM.perclk_sel(), CCM.perclk_divider());
cortexm7::nvic::Nvic::new(imxrt1050::nvic::GPT1).enable();
}

Expand Down Expand Up @@ -201,8 +202,8 @@ pub unsafe fn reset_handler() {
DynamicDeferredCall::set_global_instance(dynamic_deferred_caller);

let chip = static_init!(
imxrt1050::chip::Imxrt1050,
imxrt1050::chip::Imxrt1050::new()
imxrt1050::chip::Imxrt10xx,
imxrt1050::chip::Imxrt10xx::new()
);
CHIP = Some(chip);

Expand Down Expand Up @@ -298,13 +299,13 @@ pub unsafe fn reset_handler() {
.finalize(components::button_component_buf!(imxrt1050::gpio::Pin));

// ALARM
let gpt1 = &imxrt1050::gpt1::GPT1;
let gpt1 = &imxrt1050::gpt::GPT1;
let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize(
components::alarm_mux_component_helper!(imxrt1050::gpt1::Gpt1),
components::alarm_mux_component_helper!(imxrt1050::gpt::Gpt1),
);

let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm)
.finalize(components::alarm_component_helper!(imxrt1050::gpt1::Gpt1));
.finalize(components::alarm_component_helper!(imxrt1050::gpt::Gpt1));

// GPIO
// For now we expose only two pins
Expand Down
48 changes: 29 additions & 19 deletions boards/nano33ble/src/main.rs
Expand Up @@ -59,6 +59,9 @@ const I2C_PULLUP_PIN: Pin = Pin::P1_00;
/// Interrupt pin for the APDS9960 sensor.
const APDS9960_PIN: Pin = Pin::P0_19;

/// Personal Area Network ID for the IEEE 802.15.4 radio
const PAN_ID: u16 = 0xABCD;

/// UART Writer for panic!()s.
pub mod io;

Expand All @@ -84,12 +87,12 @@ pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];

/// Supported drivers by the platform
pub struct Platform {
// ble_radio: &'static capsules::ble_advertising_driver::BLE<
// 'static,
// nrf52::ble_radio::Radio,
// VirtualMuxAlarm<'static, Rtc<'static>>,
// >,
// ieee802154_radio: &'static capsules::ieee802154::RadioDriver<'static>,
ble_radio: &'static capsules::ble_advertising_driver::BLE<
'static,
nrf52::ble_radio::Radio<'static>,
capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52::rtc::Rtc<'static>>,
>,
ieee802154_radio: &'static capsules::ieee802154::RadioDriver<'static>,
console: &'static capsules::console::Console<'static>,
proximity: &'static capsules::proximity::ProximitySensor<'static>,
gpio: &'static capsules::gpio::GPIO<'static, nrf52::gpio::GPIOPin<'static>>,
Expand All @@ -114,8 +117,8 @@ impl kernel::Platform for Platform {
capsules::alarm::DRIVER_NUM => f(Some(self.alarm)),
capsules::led::DRIVER_NUM => f(Some(self.led)),
capsules::rng::DRIVER_NUM => f(Some(self.rng)),
// capsules::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
// capsules::ieee802154::DRIVER_NUM => f(Some(radio)),
capsules::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
capsules::ieee802154::DRIVER_NUM => f(Some(self.ieee802154_radio)),
kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
_ => f(None),
}
Expand Down Expand Up @@ -315,16 +318,23 @@ pub unsafe fn reset_handler() {
// WIRELESS
//--------------------------------------------------------------------------

// let ble_radio =
// BLEComponent::new(board_kernel, &base_peripherals.ble_radio, mux_alarm).finalize(());
let ble_radio =
nrf52_components::BLEComponent::new(board_kernel, &base_peripherals.ble_radio, mux_alarm)
.finalize(());

// let (ieee802154_radio, _) = Ieee802154Component::new(
// board_kernel,
// &base_peripherals.ieee802154_radio,
// PAN_ID,
// SRC_MAC,
// )
// .finalize(());
let serial_num = nrf52840::ficr::FICR_INSTANCE.address();
let serial_num_bottom_16 = u16::from_le_bytes([serial_num[0], serial_num[1]]);
let (ieee802154_radio, _mux_mac) = components::ieee802154::Ieee802154Component::new(
board_kernel,
&base_peripherals.ieee802154_radio,
&base_peripherals.ecb,
PAN_ID,
serial_num_bottom_16,
)
.finalize(components::ieee802154_component_helper!(
nrf52840::ieee802154_radio::Radio,
nrf52840::aes::AesECB<'static>
));

//--------------------------------------------------------------------------
// FINAL SETUP AND BOARD BOOT
Expand All @@ -335,8 +345,8 @@ pub unsafe fn reset_handler() {
nrf52_components::NrfClockComponent::new().finalize(());

let platform = Platform {
// ble_radio: ble_radio,
// ieee802154_radio: ieee802154_radio,
ble_radio: ble_radio,
ieee802154_radio: ieee802154_radio,
console: console,
proximity: proximity,
led: led,
Expand Down
13 changes: 13 additions & 0 deletions boards/teensy40/Cargo.toml
@@ -0,0 +1,13 @@
[package]
name = "teensy40"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
build = "build.rs"
edition = "2018"

[dependencies]
components = { path = "../components" }
cortexm7 = { path = "../../arch/cortex-m7" }
capsules = { path = "../../capsules" }
kernel = { path = "../../kernel" }
imxrt10xx = { path = "../../chips/imxrt10xx" }
31 changes: 31 additions & 0 deletions boards/teensy40/Makefile
@@ -0,0 +1,31 @@
# Makefile for building the tock kernel for the Teensy 4

TARGET=thumbv7em-none-eabi
PLATFORM=teensy40

include ../Makefile.common

%.hex: %.elf
$(Q)$(OBJCOPY) -O ihex $< $@

kernel: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).elf

.PHONY: program
program: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).hex
$(Q)teensy_loader_cli --mcu=TEENSY40 -w -v $<

# Unsupported; there's no easily-accessible JTAG interface
.PHONY: flash
flash:
echo "Use 'make program' to program the Teensy 4"
exit 1

# For testing with a blinky LED
BLINK=../../../libtock-c/examples/blink/build/cortex-m7/cortex-m7.tbf
app.elf: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).elf
$(Q)arm-none-eabi-objcopy --update-section .apps=$(BLINK) $< $@

app: app.elf
$(Q)$(OBJCOPY) -O ihex $< $@
teensy_loader_cli --mcu=TEENSY40 -w -v $@
$(Q)rm $@ $<
80 changes: 80 additions & 0 deletions boards/teensy40/README.md
@@ -0,0 +1,80 @@
Teensy 4.0 Development Board
============================

The `teensy40` board supports the Teensy **4.0** development board.
For more information, visit the
[Teensy 4.0 Development Board](https://www.pjrc.com/store/teensy40.html)
product page.

The board may suffice for the [Teensy **4.1** development board](t41), which
shares common pins and a larger amount of flash memory. However, the board
will not contain features that are only available on the Teensy 4.1 development
board, such as extended flash memory and RAM, an on-board SD card, or ethernet.

[t41]: https://www.pjrc.com/store/teensy41.html

Programming Dependencies
------------------------

Before attempting to program your Teensy 4.0 with Tock and Tock apps, make sure
that you have either

- a build of [`teensy_loader_cli`](https://github.com/PaulStoffregen/teensy_loader_cli), or
- the [Teensy Loader Application](https://www.pjrc.com/teensy/loader.html)

If you're already familiar with programming the Teensy with Arduino tools,
the Teensy Loader Application is already bundled with the Teensyduino add-ons
that you may already be using.

Programming
-----------

From this directory, build the Tock kernel for the Teensy 4:

```bash
$ make
```

Build Tock apps out of tree. Once you've built an app, use
`arm-none-eabi-objcopy` with `--update-section` to create an ELF image that
includes your app(s). The example below combines a prebuilt `blink` example
with the Teensy 4 Tock kernel.

```bash
$ arm-none-eabi-objcopy \
--update-section .apps=../../../libtock-c/examples/blink/build/cortex-m7/cortex-m7.tbf \
../../target/thumbv7em-none-eabi/release/teensy40.elf \
../../target/thumbv7em-none-eabi/release/teensy40-app.elf
```

Once you've created a single ELF image, use `arm-none-eabi-objcopy` to turn
that into HEX:

```bash
$ arm-none-eabi-objcopy -O ihex \
../../target/thumbv7em-none-eabi/release/teensy40-app.elf \
../../target/thumbv7em-none-eabi/release/teensy40-app.hex
```

Finally, use a Teensy programmer to flash `teensy40-app.hex` to your board!

```bash
$ teensy_loader_cli -w -v --mcu=TEENSY40 target/thumbv7em-none-eabi/release/teensy40-app.hex
```

Use the example `Makefile` below to create a build and flash workflow:

```Makefile
APP=../../../libtock-c/examples/blink/build/cortex-m7/cortex-m7.tbf
KERNEL=$(TOCK_ROOT_DIRECTORY)/target/teensy40/release/teensy40.elf
KERNEL_WITH_APP=$(TOCK_ROOT_DIRECTORY)/target/teensy40/release/teensy40-app.elf
KERNEL_WITH_APP_HEX=$(TOCK_ROOT_DIRECTORY)/target/teensy40/release/teensy40-app.hex

.PHONY: program
program: target/thumbv7em-none-eabi/release/teensy40.elf
arm-none-eabi-objcopy --update-section .apps=$(APP) $(KERNEL) $(KERNEL_WITH_APP)
arm-none-eabi-objcopy -O ihex $(KENERL_WITH_APP) $(KERNEL_WITH_APP_HEX)
teensy_loader_cli -w -v --mcu=TEENSY40 $(KERNEL_WITH_APP_HEX)
```

For another example, see [`Makefile`](./Makefile).
4 changes: 4 additions & 0 deletions boards/teensy40/build.rs
@@ -0,0 +1,4 @@
fn main() {
println!("cargo:rerun-if-changed=layout.ld");
println!("cargo:rerun-if-changed=../kernel_layout.ld");
}

0 comments on commit 40d7961

Please sign in to comment.