From d4c43044e001895b5835c4f672af739a4db92634 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 29 Jul 2015 22:30:16 -0700 Subject: [PATCH 01/13] Shuffle binaries in SPI flash image to insert HackRF firmware binary. Bootstrap is now 64k @ 0x00000. HackRF image is 64k @ 0x10000. Baseband image is 128k @ 0x20000. Application image is remainder of SPI flash, @ 0x40000. --- firmware/Makefile | 13 ++++++++++--- firmware/application/m4_startup.cpp | 2 +- firmware/bootstrap/bootstrap.c | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/firmware/Makefile b/firmware/Makefile index a80ac819..b65c470a 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -23,12 +23,15 @@ PATH_BOOTSTRAP=bootstrap PATH_APPLICATION=application PATH_BASEBAND=baseband +# TODO: Pass these (as #defines?) to Makefiles, use values in code. PAD_BOOTSTRAP=0x10000 -PAD_BASEBAND=0x10000 +PAD_HACKRF_FIRMWARE=0x10000 +PAD_BASEBAND=0x20000 TARGET=portapack-h1-firmware TARGET_BOOTSTRAP=$(PATH_BOOTSTRAP)/bootstrap +TARGET_HACKRF_FIRMWARE=hackrf_one_usb_rom_to_ram TARGET_APPLICATION=$(PATH_APPLICATION)/build/application TARGET_BASEBAND=$(PATH_BASEBAND)/build/baseband @@ -53,12 +56,16 @@ program: $(TARGET).bin sleep 1s hackrf_spiflash -w $(TARGET).bin -$(TARGET).bin: $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin - cat $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin >$(TARGET).bin +$(TARGET).bin: $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_HACKRF_FIRMWARE)_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin + cat $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_HACKRF_FIRMWARE)_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin >$(TARGET).bin $(TARGET_BOOTSTRAP)_pad.bin: $(TARGET_BOOTSTRAP).elf $(CP) -O binary --pad-to $(PAD_BOOTSTRAP) $(TARGET_BOOTSTRAP).elf $(TARGET_BOOTSTRAP)_pad.bin +$(TARGET_HACKRF_FIRMWARE)_pad.bin: $(TARGET_HACKRF_FIRMWARE).bin + # TODO: Not confident this is reliable. It certainly won't work on Windows. + dd if=/dev/null of=$(TARGET_HACKRF_FIRMWARE)_pad.bin bs=1 count=1 seek=$(PAD_HACKRF_FIRMWARE) + $(TARGET_BASEBAND)_pad.bin: $(TARGET_BASEBAND).elf $(CP) -O binary --pad-to $(PAD_BASEBAND) $(TARGET_BASEBAND).elf $(TARGET_BASEBAND)_pad.bin diff --git a/firmware/application/m4_startup.cpp b/firmware/application/m4_startup.cpp index 100983e3..b2ba689e 100644 --- a/firmware/application/m4_startup.cpp +++ b/firmware/application/m4_startup.cpp @@ -27,7 +27,7 @@ #include #include -static constexpr uint32_t m4_text_flash_image_offset = 0x10000; +static constexpr uint32_t m4_text_flash_image_offset = 0x20000; static constexpr size_t m4_text_size = 0x8000; static constexpr uint32_t m4_text_flash_base = LPC_SPIFI_DATA_CACHED_BASE + m4_text_flash_image_offset; static constexpr uint32_t m4_text_ram_base = 0x10080000; diff --git a/firmware/bootstrap/bootstrap.c b/firmware/bootstrap/bootstrap.c index 87f9d8ef..862b861f 100644 --- a/firmware/bootstrap/bootstrap.c +++ b/firmware/bootstrap/bootstrap.c @@ -99,7 +99,7 @@ int main(void) { /* NOTE: MEMMAP registers are ORed with the shadow address to create the * actual address. */ - LPC_CREG->M0APPMEMMAP = LPC_SPIFI_DATA_CACHED_BASE + 0x20000; + LPC_CREG->M0APPMEMMAP = LPC_SPIFI_DATA_CACHED_BASE + 0x40000; /* Change M0APP_RST to 0 */ LPC_RGU->RESET_CTRL[1] = 0; From b32f5e2239c6f9aca78bdc547073c10ef87bb64b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 30 Jul 2015 09:41:33 -0700 Subject: [PATCH 02/13] Generalize method for executing SPI flash image in M4 RAM. --- firmware/application/m4_startup.cpp | 13 ++---- firmware/application/m4_startup.hpp | 6 ++- firmware/application/main.cpp | 4 +- firmware/common/spi_image.hpp | 68 +++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 12 deletions(-) create mode 100644 firmware/common/spi_image.hpp diff --git a/firmware/application/m4_startup.cpp b/firmware/application/m4_startup.cpp index b2ba689e..5a705bff 100644 --- a/firmware/application/m4_startup.cpp +++ b/firmware/application/m4_startup.cpp @@ -23,15 +23,8 @@ #include "hal.h" -#include -#include #include -static constexpr uint32_t m4_text_flash_image_offset = 0x20000; -static constexpr size_t m4_text_size = 0x8000; -static constexpr uint32_t m4_text_flash_base = LPC_SPIFI_DATA_CACHED_BASE + m4_text_flash_image_offset; -static constexpr uint32_t m4_text_ram_base = 0x10080000; - /* TODO: OK, this is cool, but how do I put the M4 to sleep so I can switch to * a different image? Other than asking the old image to sleep while the M0 * makes changes? @@ -39,14 +32,14 @@ static constexpr uint32_t m4_text_ram_base = 0x10080000; * I suppose I could force M4MEMMAP to an invalid memory reason which would * cause an exception and effectively halt the M4. But that feels gross. */ -void m4_init() { +void m4_init(const portapack::spi_flash::region_t from, void* const to) { /* Initialize M4 code RAM */ - std::memcpy((void*)m4_text_ram_base, (void*)m4_text_flash_base, m4_text_size); + std::memcpy(to, from.base_address(), from.size); /* M4 core is assumed to be sleeping with interrupts off, so we can mess * with its address space and RAM without concern. */ - LPC_CREG->M4MEMMAP = m4_text_ram_base; + LPC_CREG->M4MEMMAP = reinterpret_cast(to); /* Reset M4 core */ LPC_RGU->RESET_CTRL[0] = (1 << 13); diff --git a/firmware/application/m4_startup.hpp b/firmware/application/m4_startup.hpp index 00b36e76..b4763156 100644 --- a/firmware/application/m4_startup.hpp +++ b/firmware/application/m4_startup.hpp @@ -22,6 +22,10 @@ #ifndef __M4_STARTUP_H__ #define __M4_STARTUP_H__ -void m4_init(); +#include + +#include "spi_image.hpp" + +void m4_init(const portapack::spi_flash::region_t from, void* const to); #endif/*__M4_STARTUP_H__*/ diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 9cd811be..3af69b99 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -59,6 +59,7 @@ using namespace hackrf::one; #include "spi_pp.hpp" #include "m4_startup.hpp" +#include "spi_image.hpp" #include "debug.hpp" #include "led.hpp" @@ -649,7 +650,8 @@ context.message_map[Message::ID::FSKPacket] = [](const Message* const p) { }; m4txevent_interrupt_enable(); - m4_init(); + + m4_init(portapack::spi_flash::baseband, portapack::spi_flash::m4_text_ram_base); while(true) { const auto events = event_dispatcher.wait(); diff --git a/firmware/common/spi_image.hpp b/firmware/common/spi_image.hpp new file mode 100644 index 00000000..afc5053b --- /dev/null +++ b/firmware/common/spi_image.hpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __SPI_IMAGE_H__ +#define __SPI_IMAGE_H__ + +#include +#include + +#include "hal.h" + +namespace portapack { +namespace spi_flash { + +struct region_t { + const size_t offset; + const size_t size; + + constexpr const void* base_address() { + return reinterpret_cast(LPC_SPIFI_DATA_CACHED_BASE + offset); + } +}; + +constexpr region_t bootstrap { + .offset = 0x00000, + .size = 0x10000, +}; + +constexpr region_t hackrf { + .offset = 0x10000, + .size = 0x8000, +}; + +constexpr region_t baseband { + .offset = 0x20000, + .size = 0x8000, +}; + +constexpr region_t application { + .offset = 0x40000, + .size = 0x40000, +}; + +// TODO: Refactor into another header that defines memory regions. +constexpr void* m4_text_ram_base = reinterpret_cast(0x10080000); + +} /* namespace spi_flash */ +} /* namespace portapack */ + +#endif/*__SPI_IMAGE_H__*/ From 8af8941687c6441461330873310a592b3e6ef01a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 30 Jul 2015 10:01:12 -0700 Subject: [PATCH 03/13] Use from-RAM DFU image, proper HackRF firmware padding. --- firmware/Makefile | 11 ++++++----- firmware/common/spi_image.hpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/firmware/Makefile b/firmware/Makefile index b65c470a..54705d1c 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -31,7 +31,7 @@ PAD_BASEBAND=0x20000 TARGET=portapack-h1-firmware TARGET_BOOTSTRAP=$(PATH_BOOTSTRAP)/bootstrap -TARGET_HACKRF_FIRMWARE=hackrf_one_usb_rom_to_ram +TARGET_HACKRF_FIRMWARE=hackrf_one_usb_ram TARGET_APPLICATION=$(PATH_APPLICATION)/build/application TARGET_BASEBAND=$(PATH_BASEBAND)/build/baseband @@ -56,15 +56,16 @@ program: $(TARGET).bin sleep 1s hackrf_spiflash -w $(TARGET).bin -$(TARGET).bin: $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_HACKRF_FIRMWARE)_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin - cat $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_HACKRF_FIRMWARE)_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin >$(TARGET).bin +$(TARGET).bin: $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_HACKRF_FIRMWARE)_dfu_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin + cat $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_HACKRF_FIRMWARE)_dfu_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin >$(TARGET).bin $(TARGET_BOOTSTRAP)_pad.bin: $(TARGET_BOOTSTRAP).elf $(CP) -O binary --pad-to $(PAD_BOOTSTRAP) $(TARGET_BOOTSTRAP).elf $(TARGET_BOOTSTRAP)_pad.bin -$(TARGET_HACKRF_FIRMWARE)_pad.bin: $(TARGET_HACKRF_FIRMWARE).bin +$(TARGET_HACKRF_FIRMWARE)_dfu_pad.bin: $(TARGET_HACKRF_FIRMWARE).dfu # TODO: Not confident this is reliable. It certainly won't work on Windows. - dd if=/dev/null of=$(TARGET_HACKRF_FIRMWARE)_pad.bin bs=1 count=1 seek=$(PAD_HACKRF_FIRMWARE) + cp $(TARGET_HACKRF_FIRMWARE).dfu $(TARGET_HACKRF_FIRMWARE)_dfu_pad.bin + dd if=/dev/null of=$(TARGET_HACKRF_FIRMWARE)_dfu_pad.bin bs=1 count=1 seek=$(PAD_HACKRF_FIRMWARE) $(TARGET_BASEBAND)_pad.bin: $(TARGET_BASEBAND).elf $(CP) -O binary --pad-to $(PAD_BASEBAND) $(TARGET_BASEBAND).elf $(TARGET_BASEBAND)_pad.bin diff --git a/firmware/common/spi_image.hpp b/firmware/common/spi_image.hpp index afc5053b..e693d3e9 100644 --- a/firmware/common/spi_image.hpp +++ b/firmware/common/spi_image.hpp @@ -45,7 +45,7 @@ constexpr region_t bootstrap { }; constexpr region_t hackrf { - .offset = 0x10000, + .offset = 0x10010, // Image starts at 0x10 into .dfu file. .size = 0x8000, }; From 1d16cd8aac37a8dda72c3e7ca8af49b5a9fa2f97 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 1 Aug 2015 13:42:27 -0700 Subject: [PATCH 04/13] Consolidate peripheral declarations. --- firmware/application/Makefile | 1 + firmware/application/main.cpp | 146 +----------------- firmware/application/portapack.cpp | 187 ++++++++++++++++++++++++ firmware/application/portapack.hpp | 45 ++++++ firmware/application/radio.cpp | 5 +- firmware/application/receiver_model.cpp | 9 +- firmware/application/ui_navigation.cpp | 2 +- firmware/application/ui_receiver.cpp | 7 +- 8 files changed, 244 insertions(+), 158 deletions(-) create mode 100644 firmware/application/portapack.cpp create mode 100644 firmware/application/portapack.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index ba3fd78b..f3e7941a 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -124,6 +124,7 @@ CPPSRC = main.cpp \ event.cpp \ message_queue.cpp \ hackrf_hal.cpp \ + portapack.cpp \ portapack_shared_memory.cpp \ portapack_io.cpp \ i2c_pp.cpp \ diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 3af69b99..d74991b6 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -22,42 +22,27 @@ #include "ch.h" #include "test.h" -#include "hackrf_hal.hpp" -#include "hackrf_gpio.hpp" -using namespace hackrf::one; +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; +#include "portapack.hpp" #include "portapack_shared_memory.hpp" -#include "portapack_hal.hpp" -#include "portapack_io.hpp" #include "cpld_update.hpp" #include "message_queue.hpp" -#include "si5351.hpp" -#include "clock_manager.hpp" - -#include "wm8731.hpp" -#include "radio.hpp" -#include "touch.hpp" -#include "touch_adc.hpp" - #include "ui.hpp" #include "ui_widget.hpp" #include "ui_painter.hpp" #include "ui_navigation.hpp" -#include "receiver_model.hpp" - #include "irq_ipc.hpp" #include "irq_lcd_frame.hpp" #include "irq_controls.hpp" #include "event.hpp" -#include "i2c_pp.hpp" -#include "spi_pp.hpp" - #include "m4_startup.hpp" #include "spi_image.hpp" @@ -68,12 +53,6 @@ using namespace hackrf::one; #include -I2C i2c0(&I2CD0); -SPI ssp0(&SPID1); -SPI ssp1(&SPID2); - -wolfson::wm8731::WM8731 audio_codec { i2c0, portapack::wm8731_i2c_address }; - /* From ChibiOS crt0.c: * Two stacks available for Cortex-M, main stack or process stack. * @@ -147,112 +126,6 @@ static spi_bus_t ssp0 = { * _default_exit() (default is infinite loop) */ -si5351::Si5351 clock_generator { - i2c0, si5351_i2c_address -}; - -ClockManager clock_manager { - i2c0, clock_generator -}; - -ReceiverModel receiver_model { - clock_manager -}; - -class Power { -public: - void init() { - /* VAA powers: - * MAX5864 analog section. - * MAX2837 registers and other functions. - * RFFC5072 analog section. - * - * Beware that power applied to pins of the MAX2837 may - * show up on VAA and start powering other components on the - * VAA net. So turn on VAA before driving pins from MCU to - * MAX2837. - */ - /* Turn on VAA */ - gpio_vaa_disable.clear(); - gpio_vaa_disable.output(); - - /* 1V8 powers CPLD internals. - */ - /* Turn on 1V8 */ - gpio_1v8_enable.set(); - gpio_1v8_enable.output(); - - /* Set VREGMODE for switching regulator on HackRF One */ - gpio_vregmode.set(); - gpio_vregmode.output(); - } - -private: -}; - -static Power power; - -static void init() { - for(const auto& pin : pins) { - pin.init(); - } - - /* Configure other pins */ - LPC_SCU->SFSI2C0 = - (1U << 3) - | (1U << 11) - ; - - power.init(); - - gpio_max5864_select.set(); - gpio_max5864_select.output(); - - gpio_max2837_select.set(); - gpio_max2837_select.output(); - - led_usb.setup(); - led_rx.setup(); - led_tx.setup(); - - clock_manager.init(); - clock_manager.run_at_full_speed(); - - clock_manager.start_audio_pll(); - audio_codec.init(); - - clock_manager.enable_first_if_clock(); - clock_manager.enable_second_if_clock(); - clock_manager.enable_codec_clocks(); - radio::init(); - - touch::adc::init(); -} - -extern "C" { - -void __late_init(void) { - - reset(); - - /* - * System initializations. - * - HAL initialization, this also initializes the configured device drivers - * and performs the board-specific initializations. - * - Kernel initialization, the main() function becomes a thread and the - * RTOS is active. - */ - halInit(); - - /* After this call, scheduler, systick, heap, etc. are available. */ - /* By doing chSysInit() here, it runs before C++ constructors, which may - * require the heap. - */ - chSysInit(); -} - -} - extern "C" { CH_IRQ_HANDLER(RTC_IRQHandler) { @@ -601,18 +474,8 @@ message_handlers[Message::ID::TestResults] = [&system_view](const Message* const }; */ -portapack::IO portapack::io { - portapack::gpio_dir, - portapack::gpio_lcd_rd, - portapack::gpio_lcd_wr, - portapack::gpio_io_stbx, - portapack::gpio_addr, - portapack::gpio_lcd_te, - portapack::gpio_unused, -}; - int main(void) { - init(); + portapack::init(); if( !cpld_update_if_necessary() ) { chSysHalt(); @@ -646,7 +509,6 @@ int main(void) { context.message_map[Message::ID::FSKPacket] = [](const Message* const p) { const auto message = static_cast(p); (void)message; - led_usb.toggle(); }; m4txevent_interrupt_enable(); diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp new file mode 100644 index 00000000..894b1f0a --- /dev/null +++ b/firmware/application/portapack.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "portapack.hpp" +#include "portapack_hal.hpp" + +#include "hackrf_hal.hpp" +#include "hackrf_gpio.hpp" +using namespace hackrf::one; + +#include "si5351.hpp" +#include "clock_manager.hpp" + +#include "i2c_pp.hpp" + +#include "touch_adc.hpp" + +#include "m4_startup.hpp" +#include "spi_image.hpp" + +namespace portapack { + +portapack::IO io { + portapack::gpio_dir, + portapack::gpio_lcd_rd, + portapack::gpio_lcd_wr, + portapack::gpio_io_stbx, + portapack::gpio_addr, + portapack::gpio_lcd_te, + portapack::gpio_unused, +}; + +I2C i2c0(&I2CD0); +SPI ssp0(&SPID1); +SPI ssp1(&SPID2); + +wolfson::wm8731::WM8731 audio_codec { i2c0, portapack::wm8731_i2c_address }; + +si5351::Si5351 clock_generator { + i2c0, hackrf::one::si5351_i2c_address +}; + +ClockManager clock_manager { + i2c0, clock_generator +}; + +ReceiverModel receiver_model { + clock_manager +}; + +class Power { +public: + void init() { + /* VAA powers: + * MAX5864 analog section. + * MAX2837 registers and other functions. + * RFFC5072 analog section. + * + * Beware that power applied to pins of the MAX2837 may + * show up on VAA and start powering other components on the + * VAA net. So turn on VAA before driving pins from MCU to + * MAX2837. + */ + /* Turn on VAA */ + gpio_vaa_disable.clear(); + gpio_vaa_disable.output(); + + /* 1V8 powers CPLD internals. + */ + /* Turn on 1V8 */ + gpio_1v8_enable.set(); + gpio_1v8_enable.output(); + + /* Set VREGMODE for switching regulator on HackRF One */ + gpio_vregmode.set(); + gpio_vregmode.output(); + } + + void shutdown() { + gpio_1v8_enable.clear(); + gpio_vaa_disable.set(); + } + +private: +}; + +static Power power; + +void init() { + for(const auto& pin : pins) { + pin.init(); + } + + /* Configure other pins */ + LPC_SCU->SFSI2C0 = + (1U << 3) + | (1U << 11) + ; + + power.init(); + + gpio_max5864_select.set(); + gpio_max5864_select.output(); + + gpio_max2837_select.set(); + gpio_max2837_select.output(); + + led_usb.setup(); + led_rx.setup(); + led_tx.setup(); + + clock_manager.init(); + clock_manager.run_at_full_speed(); + + clock_manager.start_audio_pll(); + audio_codec.init(); + + clock_manager.enable_first_if_clock(); + clock_manager.enable_second_if_clock(); + clock_manager.enable_codec_clocks(); + radio::init(); + + touch::adc::init(); +} + +void shutdown() { + sdcStop(&SDCD1); + + radio::disable(); + audio_codec.reset(); + clock_manager.shutdown(); + + power.shutdown(); + // TODO: Wait a bit for supplies to discharge? + + chSysDisable(); + hackrf::one::reset(); + m4_init(portapack::spi_flash::hackrf, reinterpret_cast(0x10000000)); + + while(true) { + __WFE(); + } +} + +extern "C" { + +void __late_init(void) { + + reset(); + + /* + * System initializations. + * - HAL initialization, this also initializes the configured device drivers + * and performs the board-specific initializations. + * - Kernel initialization, the main() function becomes a thread and the + * RTOS is active. + */ + halInit(); + + /* After this call, scheduler, systick, heap, etc. are available. */ + /* By doing chSysInit() here, it runs before C++ constructors, which may + * require the heap. + */ + chSysInit(); +} + +} + +} /* namespace portapack */ diff --git a/firmware/application/portapack.hpp b/firmware/application/portapack.hpp new file mode 100644 index 00000000..cf885894 --- /dev/null +++ b/firmware/application/portapack.hpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "portapack_io.hpp" + +#include "receiver_model.hpp" + +#include "spi_pp.hpp" +#include "wm8731.hpp" + +#include "radio.hpp" + +namespace portapack { + +extern portapack::IO io; + +extern SPI ssp0; +extern SPI ssp1; + +extern wolfson::wm8731::WM8731 audio_codec; + +extern ReceiverModel receiver_model; + +void init(); +void shutdown(); + +} /* namespace portapack */ diff --git a/firmware/application/radio.cpp b/firmware/application/radio.cpp index b493f217..f404f76a 100644 --- a/firmware/application/radio.cpp +++ b/firmware/application/radio.cpp @@ -36,8 +36,7 @@ #include "hackrf_gpio.hpp" using namespace hackrf::one; -#include "spi_pp.hpp" -extern SPI ssp1; +#include "portapack.hpp" namespace radio { @@ -75,7 +74,7 @@ static constexpr SPIConfig ssp_config_max5864 = { .cpsr = ssp1_cpsr, }; -static spi::arbiter::Arbiter ssp1_arbiter(ssp1); +static spi::arbiter::Arbiter ssp1_arbiter(portapack::ssp1); static spi::arbiter::Target ssp1_target_max2837 { ssp1_arbiter, diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index 6c642302..51e8c27e 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -22,13 +22,8 @@ #include "receiver_model.hpp" #include "portapack_shared_memory.hpp" -#include "radio.hpp" -#include "wm8731.hpp" - -// TODO: Nasty. Put this in an #include somewhere, or a shared system state -// object? - -extern wolfson::wm8731::WM8731 audio_codec; +#include "portapack.hpp" +using namespace portapack; rf::Frequency ReceiverModel::tuning_frequency() const { return tuning_frequency_; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 68e92833..16a6e45d 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -27,7 +27,7 @@ #include "ui_debug.hpp" #include "ui_receiver.hpp" -extern ReceiverModel receiver_model; +#include "portapack.hpp" namespace ui { diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 9ef66cac..beb4a2f6 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -21,11 +21,8 @@ #include "ui_receiver.hpp" -// TODO: Nasty. Put this in an #include somewhere, or a shared system state -// object? - -#include "wm8731.hpp" -extern wolfson::wm8731::WM8731 audio_codec; +#include "portapack.hpp" +using namespace portapack; namespace ui { From c025a2bba2d66b231f67e294dd7aacb39a8d81b7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 1 Aug 2015 13:43:58 -0700 Subject: [PATCH 05/13] Code to shut down ClockManager-controlled devices. --- firmware/application/clock_manager.cpp | 5 +++++ firmware/application/clock_manager.hpp | 1 + 2 files changed, 6 insertions(+) diff --git a/firmware/application/clock_manager.cpp b/firmware/application/clock_manager.cpp index 0b4e577d..c7323978 100644 --- a/firmware/application/clock_manager.cpp +++ b/firmware/application/clock_manager.cpp @@ -296,6 +296,11 @@ void ClockManager::init() { clock_generator.reset_plls(); } +void ClockManager::shutdown() { + run_from_irc(); + clock_generator.reset(); +} + void ClockManager::run_from_irc() { change_clock_configuration(cgu::CLK_SEL::IRC); } diff --git a/firmware/application/clock_manager.hpp b/firmware/application/clock_manager.hpp index d1d56830..b9956342 100644 --- a/firmware/application/clock_manager.hpp +++ b/firmware/application/clock_manager.hpp @@ -43,6 +43,7 @@ public: } void init(); + void shutdown(); void run_from_irc(); void run_at_full_speed(); From bfc73a6675dfcde3bf85ce99a7182991cab8ed40 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 1 Aug 2015 13:44:52 -0700 Subject: [PATCH 06/13] Move update_peripheral_clocks Incorrect order of operations would hang execution if switching to IRC. --- firmware/application/clock_manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/clock_manager.cpp b/firmware/application/clock_manager.cpp index c7323978..e674b067 100644 --- a/firmware/application/clock_manager.cpp +++ b/firmware/application/clock_manager.cpp @@ -382,14 +382,14 @@ void ClockManager::change_clock_configuration(const cgu::CLK_SEL clk_sel) { set_m4_clock_to_irc(); + update_peripheral_clocks(clk_sel); + if( clk_sel == cgu::CLK_SEL::PLL1 ) { set_m4_clock_to_pll1(); } else { power_down_pll1(); } - update_peripheral_clocks(clk_sel); - start_peripherals(clk_sel); if( clk_sel != cgu::CLK_SEL::XTAL ) { From 8797aa97580bb3249322132782ab18cc33cd707c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 1 Aug 2015 13:45:52 -0700 Subject: [PATCH 07/13] Stop audio PLL if shutting down GP_CLKIN clock source. --- firmware/application/clock_manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/application/clock_manager.cpp b/firmware/application/clock_manager.cpp index e674b067..e6c4d242 100644 --- a/firmware/application/clock_manager.cpp +++ b/firmware/application/clock_manager.cpp @@ -398,6 +398,7 @@ void ClockManager::change_clock_configuration(const cgu::CLK_SEL clk_sel) { /* If not using PLL1, disable clock feeding GP_CLKIN */ if( clk_sel != cgu::CLK_SEL::PLL1 ) { + stop_audio_pll(); disable_gp_clkin_source(); } } From fecbb7205e5dbb5fb39cfc4fff03dd6172feeda4 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 1 Aug 2015 13:46:15 -0700 Subject: [PATCH 08/13] Menu item to launch HackRF firmware. --- firmware/application/ui_navigation.cpp | 28 ++++++++++++++++++++++++-- firmware/application/ui_navigation.hpp | 23 +++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 16a6e45d..ca70a801 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -97,13 +97,14 @@ void NavigationView::focus() { /* SystemMenuView ********************************************************/ SystemMenuView::SystemMenuView(NavigationView& nav) { - add_items<6>({ { - { "Receiver", [&nav](){ nav.push(new ReceiverView { nav, receiver_model }); } }, + add_items<7>({ { + { "Receiver", [&nav](){ nav.push(new ReceiverView { nav, portapack::receiver_model }); } }, { "Capture", [&nav](){ nav.push(new NotImplementedView { nav }); } }, { "Analyze", [&nav](){ nav.push(new NotImplementedView { nav }); } }, { "Setup", [&nav](){ nav.push(new SetupMenuView { nav }); } }, { "About", [&nav](){ nav.push(new AboutView { nav }); } }, { "Debug", [&nav](){ nav.push(new DebugMenuView { nav }); } }, + { "HackRF", [&nav](){ nav.push(new HackRFFirmwareView { nav }); } }, } }); } @@ -146,6 +147,29 @@ Context& SystemView::context() const { return context_; } +/* HackRFFirmwareView ****************************************************/ + +HackRFFirmwareView::HackRFFirmwareView(NavigationView& nav) { + button_yes.on_select = [&nav](Button&){ + // TODO: Clear screen? + portapack::shutdown(); + }; + + button_no.on_select = [&nav](Button&){ + nav.pop(); + }; + + add_children({ { + &text_title, + &button_yes, + &button_no, + } }); +} + +void HackRFFirmwareView::focus() { + button_no.focus(); +} + /* NotImplementedView ****************************************************/ NotImplementedView::NotImplementedView(NavigationView& nav) { diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index c0cadbfc..d2963c6f 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -107,6 +107,29 @@ private: Context& context_; }; +class HackRFFirmwareView : public View { +public: + HackRFFirmwareView(NavigationView& nav); + + void focus() override; + +private: + Text text_title { + { 5 * 8, 7 * 16, 19 * 8, 16 }, + "Execute HackRF Firmware?" + }; + + Button button_yes { + { 4 * 8, 13 * 16, 8 * 8, 24 }, + "Yes", + }; + + Button button_no { + { 18 * 8, 13 * 16, 8 * 8, 24 }, + "No", + }; +}; + class NotImplementedView : public View { public: NotImplementedView(NavigationView& nav); From 65d5f68bfbacbd8a73c3d9b0537d1a14842d3cbd Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 1 Aug 2015 14:31:51 -0700 Subject: [PATCH 09/13] Move LCD display object to portapack namespace. Globals are bad... Except in embedded development! --- firmware/application/main.cpp | 4 ++-- firmware/application/portapack.cpp | 2 ++ firmware/application/portapack.hpp | 3 +++ firmware/application/ui_console.cpp | 3 +++ firmware/application/ui_console.hpp | 9 ++------- firmware/application/ui_spectrum.hpp | 9 +++++---- firmware/common/ui_painter.cpp | 13 ++++++++----- firmware/common/ui_painter.hpp | 10 +--------- firmware/common/ui_widget.hpp | 2 -- 9 files changed, 26 insertions(+), 29 deletions(-) diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index d74991b6..0a15dcc3 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -486,7 +486,7 @@ int main(void) { portapack::io.init(); ui::Context context; - context.display.init(); + portapack::display.init(); sdcStart(&SDCD1, nullptr); @@ -503,7 +503,7 @@ int main(void) { context, { 0, 0, 240, 320 } }; - ui::Painter painter { context.display }; + ui::Painter painter; EventDispatcher event_dispatcher { &system_view, painter, context }; context.message_map[Message::ID::FSKPacket] = [](const Message* const p) { diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 894b1f0a..99c09162 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -48,6 +48,8 @@ portapack::IO io { portapack::gpio_unused, }; +lcd::ILI9341 display; + I2C i2c0(&I2CD0); SPI ssp0(&SPID1); SPI ssp1(&SPID2); diff --git a/firmware/application/portapack.hpp b/firmware/application/portapack.hpp index cf885894..939442de 100644 --- a/firmware/application/portapack.hpp +++ b/firmware/application/portapack.hpp @@ -25,6 +25,7 @@ #include "spi_pp.hpp" #include "wm8731.hpp" +#include "lcd_ili9341.hpp" #include "radio.hpp" @@ -32,6 +33,8 @@ namespace portapack { extern portapack::IO io; +extern lcd::ILI9341 display; + extern SPI ssp0; extern SPI ssp1; diff --git a/firmware/application/ui_console.cpp b/firmware/application/ui_console.cpp index 3c44c5c1..2fe99364 100644 --- a/firmware/application/ui_console.cpp +++ b/firmware/application/ui_console.cpp @@ -21,6 +21,9 @@ #include "ui_console.hpp" +#include "portapack.hpp" +using namespace portapack; + namespace ui { void Console::write(const std::string message) { diff --git a/firmware/application/ui_console.hpp b/firmware/application/ui_console.hpp index 53ea3b0f..5722e858 100644 --- a/firmware/application/ui_console.hpp +++ b/firmware/application/ui_console.hpp @@ -26,8 +26,6 @@ #include "ui_painter.hpp" #include "ui_widget.hpp" -#include "lcd_ili9341.hpp" - #include namespace ui { @@ -35,10 +33,8 @@ namespace ui { class Console : public Widget { public: constexpr Console( - const Rect parent_rect, - lcd::ILI9341& display - ) : Widget { parent_rect }, - display(display) + const Rect parent_rect + ) : Widget { parent_rect } { } @@ -52,7 +48,6 @@ private: static constexpr Color foreground { Color::white() }; Point pos { 0, 0 }; - lcd::ILI9341& display; void crlf(); }; diff --git a/firmware/application/ui_spectrum.hpp b/firmware/application/ui_spectrum.hpp index bbc4821e..029c0c5c 100644 --- a/firmware/application/ui_spectrum.hpp +++ b/firmware/application/ui_spectrum.hpp @@ -26,7 +26,9 @@ #include "ui_widget.hpp" #include "spectrum_color_lut.hpp" -#include "lcd_ili9341.hpp" +#include "portapack.hpp" +using namespace portapack; + #include "message.hpp" #include @@ -180,14 +182,14 @@ class WaterfallView : public Widget { public: void on_show() override { const auto screen_r = screen_rect(); - context().display.scroll_set_area(screen_r.top(), screen_r.bottom()); + display.scroll_set_area(screen_r.top(), screen_r.bottom()); } void on_hide() override { /* TODO: Clear region to eliminate brief flash of content at un-shifted * position? */ - context().display.scroll_disable(); + display.scroll_disable(); } void paint(Painter& painter) override { @@ -212,7 +214,6 @@ public: pixel_row[i] = pixel_color; } - auto& display = context().display; const auto draw_y = display.scroll(1); display.draw_pixels( diff --git a/firmware/common/ui_painter.cpp b/firmware/common/ui_painter.cpp index 39874f1c..ef246e5f 100644 --- a/firmware/common/ui_painter.cpp +++ b/firmware/common/ui_painter.cpp @@ -21,6 +21,9 @@ #include "ui_painter.hpp" +#include "portapack.hpp" +using namespace portapack; + namespace ui { Style Style::invert() const { @@ -33,7 +36,7 @@ Style Style::invert() const { size_t Painter::draw_char(const Point p, const Style& style, const char c) { const auto glyph = style.font.glyph(c); - display_.draw_glyph(p, glyph, style.foreground, style.background); + display.draw_glyph(p, glyph, style.foreground, style.background); return glyph.advance().x; } @@ -41,7 +44,7 @@ size_t Painter::draw_string(Point p, const Style& style, const std::string text) size_t width = 0; for(const auto c : text) { const auto glyph = style.font.glyph(c); - display_.draw_glyph(p, glyph, style.foreground, style.background); + display.draw_glyph(p, glyph, style.foreground, style.background); const auto advance = glyph.advance(); p += advance; width += advance.x; @@ -50,11 +53,11 @@ size_t Painter::draw_string(Point p, const Style& style, const std::string text) } void Painter::draw_hline(Point p, size_t width, const Color c) { - display_.fill_rectangle({ p, { static_cast(width), 1 } }, c); + display.fill_rectangle({ p, { static_cast(width), 1 } }, c); } void Painter::draw_vline(Point p, size_t height, const Color c) { - display_.fill_rectangle({ p, { 1, static_cast(height) } }, c); + display.fill_rectangle({ p, { 1, static_cast(height) } }, c); } void Painter::draw_rectangle(const Rect r, const Color c) { @@ -65,7 +68,7 @@ void Painter::draw_rectangle(const Rect r, const Color c) { } void Painter::fill_rectangle(const Rect r, const Color c) { - display_.fill_rectangle(r, c); + display.fill_rectangle(r, c); } } /* namespace ui */ diff --git a/firmware/common/ui_painter.hpp b/firmware/common/ui_painter.hpp index c10b2415..542f3cab 100644 --- a/firmware/common/ui_painter.hpp +++ b/firmware/common/ui_painter.hpp @@ -25,8 +25,6 @@ #include "ui.hpp" #include "ui_text.hpp" -#include "lcd_ili9341.hpp" - #include namespace ui { @@ -41,11 +39,7 @@ struct Style { class Painter { public: - Painter( - lcd::ILI9341& display - ) : display_(display) - { - } + Painter() { }; Painter(const Painter&) = delete; Painter(Painter&&) = delete; @@ -58,8 +52,6 @@ public: void fill_rectangle(const Rect r, const Color c); private: - lcd::ILI9341& display_; - void draw_hline(Point p, size_t width, const Color c); void draw_vline(Point p, size_t height, const Color c); }; diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index 7ab54597..797083cf 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -29,7 +29,6 @@ #include "utility.hpp" -#include "lcd_ili9341.hpp" #include "message.hpp" #include @@ -48,7 +47,6 @@ std::string to_string_hex(const uint32_t n, const int32_t l = 0); struct Context { FocusManager focus_manager; - lcd::ILI9341 display; MessageHandlerMap message_map; }; From b5802aadda456cc3ada0f24d9515f2fb6b5af9fa Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 1 Aug 2015 14:32:22 -0700 Subject: [PATCH 10/13] Clean up HackRF firmware mode message. --- firmware/application/ui_navigation.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index d2963c6f..76d56988 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -115,8 +115,8 @@ public: private: Text text_title { - { 5 * 8, 7 * 16, 19 * 8, 16 }, - "Execute HackRF Firmware?" + { 6 * 8, 7 * 16, 19 * 8, 16 }, + "Enter HackRF Mode?" }; Button button_yes { From 98a1eb5c1ce8ae20a42e7dc64cbfda2eb2dabebd Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 1 Aug 2015 14:36:27 -0700 Subject: [PATCH 11/13] Add LCD shutdown method. Resets LCD controller, turns off backlight. --- firmware/common/lcd_ili9341.cpp | 5 +++++ firmware/common/lcd_ili9341.hpp | 1 + 2 files changed, 6 insertions(+) diff --git a/firmware/common/lcd_ili9341.cpp b/firmware/common/lcd_ili9341.cpp index 0da6171b..96b3da0d 100644 --- a/firmware/common/lcd_ili9341.cpp +++ b/firmware/common/lcd_ili9341.cpp @@ -225,6 +225,11 @@ void ILI9341::init() { io.lcd_backlight(1); } +void ILI9341::shutdown() { + io.lcd_backlight(0); + lcd_reset(); +} + void ILI9341::fill_rectangle(ui::Rect r, const ui::Color c) { const auto r_clipped = r.intersect(screen_rect()); if( !r_clipped.is_empty() ) { diff --git a/firmware/common/lcd_ili9341.hpp b/firmware/common/lcd_ili9341.hpp index 3a4c7cef..2a0d6cd6 100644 --- a/firmware/common/lcd_ili9341.hpp +++ b/firmware/common/lcd_ili9341.hpp @@ -42,6 +42,7 @@ public: void operator=(const ILI9341&) = delete; void init(); + void shutdown(); void fill_rectangle(ui::Rect r, const ui::Color c); void fill_circle( From 96babc3e840ff968deb7bd3604327a7bf7f3e528 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 1 Aug 2015 14:40:05 -0700 Subject: [PATCH 12/13] Shut down LCD during PortaPack shutdown. --- firmware/application/portapack.cpp | 2 ++ firmware/application/ui_navigation.cpp | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 99c09162..cacc4f61 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -146,6 +146,8 @@ void init() { void shutdown() { sdcStop(&SDCD1); + display.shutdown(); + radio::disable(); audio_codec.reset(); clock_manager.shutdown(); diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index ca70a801..56c97283 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -151,7 +151,6 @@ Context& SystemView::context() const { HackRFFirmwareView::HackRFFirmwareView(NavigationView& nav) { button_yes.on_select = [&nav](Button&){ - // TODO: Clear screen? portapack::shutdown(); }; From e6a3cba14ee04fe11ac4d95a7b057841735868ff Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 1 Aug 2015 14:43:48 -0700 Subject: [PATCH 13/13] Move HackRF firmware launch out of portapack::shutdown --- firmware/application/portapack.cpp | 8 -------- firmware/application/ui_navigation.cpp | 13 +++++++++++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index cacc4f61..9f4c361c 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -33,9 +33,6 @@ using namespace hackrf::one; #include "touch_adc.hpp" -#include "m4_startup.hpp" -#include "spi_image.hpp" - namespace portapack { portapack::IO io { @@ -157,11 +154,6 @@ void shutdown() { chSysDisable(); hackrf::one::reset(); - m4_init(portapack::spi_flash::hackrf, reinterpret_cast(0x10000000)); - - while(true) { - __WFE(); - } } extern "C" { diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 56c97283..21716ead 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -28,6 +28,9 @@ #include "ui_receiver.hpp" #include "portapack.hpp" +#include "m4_startup.hpp" +#include "spi_image.hpp" +using namespace portapack; namespace ui { @@ -98,7 +101,7 @@ void NavigationView::focus() { SystemMenuView::SystemMenuView(NavigationView& nav) { add_items<7>({ { - { "Receiver", [&nav](){ nav.push(new ReceiverView { nav, portapack::receiver_model }); } }, + { "Receiver", [&nav](){ nav.push(new ReceiverView { nav, receiver_model }); } }, { "Capture", [&nav](){ nav.push(new NotImplementedView { nav }); } }, { "Analyze", [&nav](){ nav.push(new NotImplementedView { nav }); } }, { "Setup", [&nav](){ nav.push(new SetupMenuView { nav }); } }, @@ -151,7 +154,13 @@ Context& SystemView::context() const { HackRFFirmwareView::HackRFFirmwareView(NavigationView& nav) { button_yes.on_select = [&nav](Button&){ - portapack::shutdown(); + shutdown(); + + m4_init(spi_flash::hackrf, reinterpret_cast(0x10000000)); + + while(true) { + __WFE(); + } }; button_no.on_select = [&nav](Button&){