From 5dfb53263ac749605fb6745a1f41f0da6a4caeff Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 6 Oct 2016 13:38:56 -0700 Subject: [PATCH] Extract BufferExchange, simplify threading. --- firmware/application/CMakeLists.txt | 1 + firmware/application/capture_thread.cpp | 86 ++++------------------- firmware/application/capture_thread.hpp | 6 +- firmware/application/event_m0.cpp | 4 +- firmware/common/buffer_exchange.cpp | 54 +++++++++++++++ firmware/common/buffer_exchange.hpp | 91 +++++++++++++++++++++++++ 6 files changed, 161 insertions(+), 81 deletions(-) create mode 100644 firmware/common/buffer_exchange.cpp create mode 100644 firmware/common/buffer_exchange.hpp diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 2af3460ef..81e1d4bda 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -174,6 +174,7 @@ set(CPPSRC file.cpp log_file.cpp ${COMMON}/png_writer.cpp + ${COMMON}/buffer_exchange.cpp capture_thread.cpp io_file.cpp io_wave.cpp diff --git a/firmware/application/capture_thread.cpp b/firmware/application/capture_thread.cpp index 0ac35a604..50558a449 100644 --- a/firmware/application/capture_thread.cpp +++ b/firmware/application/capture_thread.cpp @@ -22,67 +22,20 @@ #include "capture_thread.hpp" #include "baseband_api.hpp" +#include "buffer_exchange.hpp" -// BufferExchange /////////////////////////////////////////////////////////// - -class BufferExchange { -public: - BufferExchange(CaptureConfig* const config); - ~BufferExchange(); - -#if defined(LPC43XX_M0) - StreamBuffer* get() { - StreamBuffer* p { nullptr }; - fifo_buffers_for_application->out(p); - return p; +struct BasebandCapture { + BasebandCapture(CaptureConfig* const config) { + baseband::capture_start(config); } - bool put(StreamBuffer* const p) { - return fifo_buffers_for_baseband->in(p); + ~BasebandCapture() { + baseband::capture_stop(); } -#endif - -#if defined(LPC43XX_M4) - StreamBuffer* get() { - StreamBuffer* p { nullptr }; - fifo_buffers_for_baseband->out(p); - return p; - } - - bool put(StreamBuffer* const p) { - return fifo_buffers_for_application->in(p); - } -#endif - - static FIFO* fifo_buffers_for_baseband; - static FIFO* fifo_buffers_for_application; - -private: - CaptureConfig* const config; }; -FIFO* BufferExchange::fifo_buffers_for_baseband = nullptr; -FIFO* BufferExchange::fifo_buffers_for_application = nullptr; - -BufferExchange::BufferExchange( - CaptureConfig* const config -) : config { config } -{ - baseband::capture_start(config); - fifo_buffers_for_baseband = config->fifo_buffers_empty; - fifo_buffers_for_application = config->fifo_buffers_full; -} - -BufferExchange::~BufferExchange() { - fifo_buffers_for_baseband = nullptr; - fifo_buffers_for_application = nullptr; - baseband::capture_stop(); -} - // CaptureThread ////////////////////////////////////////////////////////// -Thread* CaptureThread::thread = nullptr; - CaptureThread::CaptureThread( std::unique_ptr writer, size_t write_size, @@ -101,23 +54,11 @@ CaptureThread::CaptureThread( CaptureThread::~CaptureThread() { if( thread ) { chThdTerminate(thread); - chEvtSignal(thread, event_mask_loop_wake); chThdWait(thread); thread = nullptr; } } -void CaptureThread::check_fifo_isr() { - // TODO: Prevent over-signalling by transmitting a set of - // flags from the baseband core. - const auto fifo = BufferExchange::fifo_buffers_for_application; - if( fifo ) { - if( !fifo->is_empty() ) { - chEvtSignalI(thread, event_mask_loop_wake); - } - } -} - msg_t CaptureThread::static_fn(void* arg) { auto obj = static_cast(arg); const auto error = obj->run(); @@ -132,20 +73,17 @@ msg_t CaptureThread::static_fn(void* arg) { } Optional CaptureThread::run() { + BasebandCapture capture { &config }; BufferExchange buffers { &config }; while( !chThdShouldTerminate() ) { auto buffer = buffers.get(); - if( buffer ) { - auto write_result = writer->write(buffer->data(), buffer->size()); - if( write_result.is_error() ) { - return write_result.error(); - } - buffer->empty(); - buffers.put(buffer); - } else { - chEvtWaitAny(event_mask_loop_wake); + auto write_result = writer->write(buffer->data(), buffer->size()); + if( write_result.is_error() ) { + return write_result.error(); } + buffer->empty(); + buffers.put(buffer); } return { }; diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 01c45b2eb..5a4398b0d 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -48,16 +48,12 @@ public: return config; } - static void check_fifo_isr(); - private: - static constexpr auto event_mask_loop_wake = EVENT_MASK(0); - CaptureConfig config; std::unique_ptr writer; std::function success_callback; std::function error_callback; - static Thread* thread; + Thread* thread; static msg_t static_fn(void* arg); diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index a7fae4a3c..bb32041ca 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -31,7 +31,7 @@ #include "irq_controls.hpp" -#include "capture_thread.hpp" +#include "buffer_exchange.hpp" #include "ch.h" @@ -48,7 +48,7 @@ CH_IRQ_HANDLER(M4Core_IRQHandler) { CH_IRQ_PROLOGUE(); chSysLockFromIsr(); - CaptureThread::check_fifo_isr(); + BufferExchange::handle_isr(); EventDispatcher::check_fifo_isr(); chSysUnlockFromIsr(); diff --git a/firmware/common/buffer_exchange.cpp b/firmware/common/buffer_exchange.cpp new file mode 100644 index 000000000..37bc47f1c --- /dev/null +++ b/firmware/common/buffer_exchange.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 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 "buffer_exchange.hpp" + +BufferExchange* BufferExchange::obj { nullptr }; + +BufferExchange::BufferExchange( + CaptureConfig* const config +) : config { config } +{ + obj = this; + fifo_buffers_for_baseband = config->fifo_buffers_empty; + fifo_buffers_for_application = config->fifo_buffers_full; +} + +BufferExchange::~BufferExchange() { + obj = nullptr; + fifo_buffers_for_baseband = nullptr; + fifo_buffers_for_application = nullptr; +} + +StreamBuffer* BufferExchange::get(FIFO* fifo) { + while(true) { + StreamBuffer* p { nullptr }; + fifo->out(p); + if( p ) { + return p; + } + + chSysLock(); + thread = chThdSelf(); + chSchGoSleepS(THD_STATE_SUSPENDED); + chSysUnlock(); + } +} diff --git a/firmware/common/buffer_exchange.hpp b/firmware/common/buffer_exchange.hpp new file mode 100644 index 000000000..091a6ea2e --- /dev/null +++ b/firmware/common/buffer_exchange.hpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2016 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. + */ + +#pragma once + +#include "ch.h" + +#include "message.hpp" +#include "fifo.hpp" +#include "io.hpp" + +class BufferExchange { +public: + BufferExchange(CaptureConfig* const config); + ~BufferExchange(); + +#if defined(LPC43XX_M0) + bool empty() const { + return fifo_buffers_for_application->is_empty(); + } + + StreamBuffer* get() { + return get(fifo_buffers_for_application); + } + + bool put(StreamBuffer* const p) { + return fifo_buffers_for_baseband->in(p); + } +#endif + +#if defined(LPC43XX_M4) + bool empty() const { + return fifo_buffers_for_baseband->is_empty(); + } + + StreamBuffer* get() { + return get(fifo_buffers_for_baseband); + } + + bool put(StreamBuffer* const p) { + return fifo_buffers_for_application->in(p); + } +#endif + + static void handle_isr() { + if( obj ) { + obj->check_fifo_isr(); + } + } + +private: + CaptureConfig* const config; + FIFO* fifo_buffers_for_baseband; + FIFO* fifo_buffers_for_application; + Thread* thread; + static BufferExchange* obj; + + void check_fifo_isr() { + if( !empty() ) { + wakeup_isr(); + } + } + + void wakeup_isr() { + auto thread_tmp = thread; + if( thread_tmp ) { + thread = nullptr; + chSchReadyI(thread_tmp); + } + } + + StreamBuffer* get(FIFO* fifo); +};