diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index 3aba34e1..5e971115 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -126,6 +126,7 @@ CPPSRC = main.cpp \ message_queue.cpp \ event.cpp \ event_m4.cpp \ + thread_wait.cpp \ gpdma.cpp \ baseband_dma.cpp \ baseband_sgpio.cpp \ diff --git a/firmware/baseband/baseband_dma.cpp b/firmware/baseband/baseband_dma.cpp index 7467f551..f5dcca1e 100644 --- a/firmware/baseband/baseband_dma.cpp +++ b/firmware/baseband/baseband_dma.cpp @@ -32,6 +32,8 @@ using namespace lpc43xx; #include "portapack_dma.hpp" +#include "thread_wait.hpp" + namespace baseband { namespace dma { @@ -99,21 +101,19 @@ constexpr size_t msg_count = transfers_per_buffer - 1; static std::array lli_loop; static constexpr auto& gpdma_channel_sgpio = gpdma::channels[portapack::sgpio_gpdma_channel_number]; -static Semaphore semaphore; - -static volatile const gpdma::channel::LLI* next_lli = nullptr; +static ThreadWait thread_wait; static void transfer_complete() { - next_lli = gpdma_channel_sgpio.next_lli(); - chSemSignalI(&semaphore); + const auto next_lli_index = gpdma_channel_sgpio.next_lli() - &lli_loop[0]; + thread_wait.wake_from_interrupt(next_lli_index); } static void dma_error() { + thread_wait.wake_from_interrupt(-1); disable(); } void init() { - chSemInit(&semaphore, 0); gpdma_channel_sgpio.set_handlers(transfer_complete, dma_error); // LPC_GPDMA->SYNC |= (1 << gpdma_src_peripheral); @@ -138,9 +138,6 @@ void configure( void enable(const baseband::Direction direction) { const auto gpdma_config = config(direction); gpdma_channel_sgpio.configure(lli_loop[0], gpdma_config); - - chSemReset(&semaphore, 0); - gpdma_channel_sgpio.enable(); } @@ -153,16 +150,11 @@ void disable() { } baseband::buffer_t wait_for_rx_buffer() { - const auto status = chSemWait(&semaphore); - if( status == RDY_OK ) { - const auto next = next_lli; - if( next ) { - const size_t next_index = next - &lli_loop[0]; - const size_t free_index = (next_index + transfers_per_buffer - 2) & transfers_mask; - return { reinterpret_cast(lli_loop[free_index].destaddr), transfer_samples }; - } else { - return { }; - } + const auto next_index = thread_wait.sleep(); + + if( next_index >= 0 ) { + const size_t free_index = (next_index + transfers_per_buffer - 2) & transfers_mask; + return { reinterpret_cast(lli_loop[free_index].destaddr), transfer_samples }; } else { return { }; } diff --git a/firmware/baseband/rssi_dma.cpp b/firmware/baseband/rssi_dma.cpp index 91f3b496..355698ad 100644 --- a/firmware/baseband/rssi_dma.cpp +++ b/firmware/baseband/rssi_dma.cpp @@ -33,6 +33,8 @@ using namespace lpc43xx; #include "portapack_dma.hpp" #include "portapack_adc.hpp" +#include "thread_wait.hpp" + namespace rf { namespace rssi { namespace dma { @@ -99,20 +101,19 @@ static buffers_config_t buffers_config; static sample_t *samples { nullptr }; static gpdma::channel::LLI *lli { nullptr }; -static Semaphore semaphore; -static volatile const gpdma::channel::LLI* next_lli = nullptr; +static ThreadWait thread_wait; static void transfer_complete() { - next_lli = gpdma_channel.next_lli(); - chSemSignalI(&semaphore); + const auto next_lli_index = gpdma_channel.next_lli() - &lli[0]; + thread_wait.wake_from_interrupt(next_lli_index); } static void dma_error() { + thread_wait.wake_from_interrupt(-1); disable(); } void init() { - chSemInit(&semaphore, 0); gpdma_channel.set_handlers(transfer_complete, dma_error); // LPC_GPDMA->SYNC |= (1 << gpdma_peripheral); @@ -147,8 +148,6 @@ void free() { void enable() { const auto gpdma_config = config(); gpdma_channel.configure(lli[0], gpdma_config); - - chSemReset(&semaphore, 0); gpdma_channel.enable(); } @@ -161,16 +160,11 @@ void disable() { } rf::rssi::buffer_t wait_for_buffer() { - const auto status = chSemWait(&semaphore); - if( status == RDY_OK ) { - const auto next = next_lli; - if( next ) { - const size_t next_index = next - &lli[0]; - const size_t free_index = (next_index + buffers_config.count - 2) % buffers_config.count; - return { reinterpret_cast(lli[free_index].destaddr), buffers_config.items_per_buffer }; - } else { - return { nullptr, 0 }; - } + const auto next_index = thread_wait.sleep(); + + if( next_index >= 0 ) { + const size_t free_index = (next_index + buffers_config.count - 2) % buffers_config.count; + return { reinterpret_cast(lli[free_index].destaddr), buffers_config.items_per_buffer }; } else { // TODO: Should I return here, or loop if RDY_RESET? return { nullptr, 0 }; diff --git a/firmware/common/thread_wait.cpp b/firmware/common/thread_wait.cpp new file mode 100644 index 00000000..dd3aac27 --- /dev/null +++ b/firmware/common/thread_wait.cpp @@ -0,0 +1,42 @@ +/* + * 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 "thread_wait.hpp" + +int ThreadWait::sleep() { + chSysLock(); + thread_to_wake = chThdSelf(); + chSchGoSleepS(THD_STATE_SUSPENDED); + const auto result = chThdSelf()->p_u.rdymsg; + chSysUnlock(); + return result; +} + +bool ThreadWait::wake_from_interrupt(const int value) { + if( thread_to_wake ) { + thread_to_wake->p_u.rdymsg = value; + chSchReadyI(thread_to_wake); + thread_to_wake = nullptr; + return true; + } else { + return false; + } +} diff --git a/firmware/common/thread_wait.hpp b/firmware/common/thread_wait.hpp new file mode 100644 index 00000000..9380dc43 --- /dev/null +++ b/firmware/common/thread_wait.hpp @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef __THREAD_WAIT_H__ +#define __THREAD_WAIT_H__ + +#include + +class ThreadWait { +public: + int sleep(); + bool wake_from_interrupt(const int value); + +private: + Thread* thread_to_wake { nullptr }; +}; + +#endif/*__THREAD_WAIT_H__*/