From c8aa111d0f13e7eb4e76e08b4bcd987f92dd765b Mon Sep 17 00:00:00 2001 From: Peter Antypas Date: Mon, 2 Nov 2020 20:05:15 -0800 Subject: [PATCH] RXPacket pool --- latest/Firmware/.cproject | 4 + .../Firmware/.settings/language.settings.xml | 2 +- latest/Firmware/Inc/CircularQueue.hpp | 6 +- latest/Firmware/Inc/EventQueue.hpp | 1 + latest/Firmware/Inc/Events.hpp | 29 ++++--- latest/Firmware/Inc/FreeRTOSConfig.h | 2 +- latest/Firmware/Inc/ObjectPool.hpp | 5 +- latest/Firmware/Inc/RXPacket.hpp | 2 + latest/Firmware/Inc/RadioManager.hpp | 7 +- latest/Firmware/Inc/Receiver.hpp | 2 +- latest/Firmware/Inc/Transceiver.hpp | 4 +- latest/Firmware/Inc/_assert.h | 16 ++-- latest/Firmware/Src/Events.cpp | 77 ++++++++++++++++--- latest/Firmware/Src/GPS.cpp | 9 +-- latest/Firmware/Src/RXPacketProcessor.cpp | 18 +++-- latest/Firmware/Src/RadioManager.cpp | 9 ++- latest/Firmware/Src/Receiver.cpp | 33 ++++---- latest/Firmware/Src/Transceiver.cpp | 2 +- latest/Firmware/Src/main.cpp | 2 +- 19 files changed, 154 insertions(+), 76 deletions(-) diff --git a/latest/Firmware/.cproject b/latest/Firmware/.cproject index 1b6aa57..41e8205 100644 --- a/latest/Firmware/.cproject +++ b/latest/Firmware/.cproject @@ -902,6 +902,8 @@ @@ -942,6 +944,8 @@ diff --git a/latest/Firmware/.settings/language.settings.xml b/latest/Firmware/.settings/language.settings.xml index 3456f14..1ff1052 100644 --- a/latest/Firmware/.settings/language.settings.xml +++ b/latest/Firmware/.settings/language.settings.xml @@ -59,7 +59,7 @@ - + diff --git a/latest/Firmware/Inc/CircularQueue.hpp b/latest/Firmware/Inc/CircularQueue.hpp index 3373081..fd83e5c 100644 --- a/latest/Firmware/Inc/CircularQueue.hpp +++ b/latest/Firmware/Inc/CircularQueue.hpp @@ -22,9 +22,9 @@ #define CIRCULARQUEUE_HPP_ +#include #include "_assert.h" - template class CircularQueue { public: @@ -35,7 +35,7 @@ public: mWritePosition = 0; mSize = size; mBuffer = new T[mSize]; - ASSERT(mBuffer); + ASSERT_VALID_PTR(mBuffer); } inline bool empty() @@ -77,7 +77,7 @@ private: volatile int mReadPosition; volatile int mWritePosition; size_t mSize; - volatile T* mBuffer; + volatile T* mBuffer = nullptr; }; #endif /* CIRCULARQUEUE_HPP_ */ diff --git a/latest/Firmware/Inc/EventQueue.hpp b/latest/Firmware/Inc/EventQueue.hpp index 8dcdf30..ac43a6b 100644 --- a/latest/Firmware/Inc/EventQueue.hpp +++ b/latest/Firmware/Inc/EventQueue.hpp @@ -27,6 +27,7 @@ #include "FreeRTOS.h" #include "queue.h" + using namespace std; class EventQueue diff --git a/latest/Firmware/Inc/Events.hpp b/latest/Firmware/Inc/Events.hpp index 8e846c7..6061d97 100644 --- a/latest/Firmware/Inc/Events.hpp +++ b/latest/Firmware/Inc/Events.hpp @@ -29,6 +29,7 @@ #include "RXPacket.hpp" #include "ObjectPool.hpp" #include "AISChannels.h" +//#include "RadioManager.hpp" using namespace std; @@ -67,23 +68,27 @@ typedef struct { uint8_t rssi; } RSSISample; + class Event { public: EventType type; uint32_t flags; - Event() - : type(UNKNOWN_EVENT), flags(0) { - } + Event(); +#if 0 Event(EventType t) - : type(t), flags(0) + : type(t), flags(0), rxPacket(nullptr) { - } +#endif - RXPacket rxPacket; + + void reset(); + + // This is an object, so it can't be a member of the union ... + RXPacket *rxPacket; union { NMEABuffer nmeaBuffer; @@ -108,7 +113,7 @@ public: virtual void processEvent(const Event &event)=0; }; -#if 1 + class EventPool { public: @@ -119,11 +124,15 @@ public: void deleteEvent(Event *event); uint32_t utilization(); uint32_t maxUtilization(); + RXPacket *newRXPacket(); + void releaseRXPacket(RXPacket *); +private: + EventPool(); private: - ObjectPool *mISRPool; - ObjectPool *mThreadPool; + ObjectPool mISRPool; + ObjectPool mThreadPool; + ObjectPool mRXPool; }; -#endif #endif /* EVENTS_HPP_ */ diff --git a/latest/Firmware/Inc/FreeRTOSConfig.h b/latest/Firmware/Inc/FreeRTOSConfig.h index f562ac8..ca336f8 100644 --- a/latest/Firmware/Inc/FreeRTOSConfig.h +++ b/latest/Firmware/Inc/FreeRTOSConfig.h @@ -64,7 +64,7 @@ #define configTICK_RATE_HZ ((TickType_t)1000) #define configMAX_PRIORITIES ( 7 ) #define configMINIMAL_STACK_SIZE ((uint16_t)128) -#define configTOTAL_HEAP_SIZE ((size_t)20480) +#define configTOTAL_HEAP_SIZE ((size_t)22480) #define configMAX_TASK_NAME_LEN ( 16 ) #define configUSE_16_BIT_TICKS 0 #define configUSE_MUTEXES 0 diff --git a/latest/Firmware/Inc/ObjectPool.hpp b/latest/Firmware/Inc/ObjectPool.hpp index 61cdb0b..cf747e5 100644 --- a/latest/Firmware/Inc/ObjectPool.hpp +++ b/latest/Firmware/Inc/ObjectPool.hpp @@ -41,11 +41,13 @@ public: mUtilization = 0; mMaxUtilization = 0; + //printf_serial_now("ObjectPool @%p\r\n", this); for ( uint32_t i = 0; i < mSize; ++i ) { T *p = new T(); - ASSERT(p); + ASSERT_VALID_PTR(p); mQueue.push(p); + //printf_serial_now("\t@%p\r\n", p); } } @@ -61,7 +63,6 @@ public: mQueue.push(o); } - uint32_t maxUtilization() { return mMaxUtilization; diff --git a/latest/Firmware/Inc/RXPacket.hpp b/latest/Firmware/Inc/RXPacket.hpp index a185226..f1fba22 100644 --- a/latest/Firmware/Inc/RXPacket.hpp +++ b/latest/Firmware/Inc/RXPacket.hpp @@ -25,6 +25,8 @@ #include "_assert.h" #include "AISChannels.h" #include "config.h" +#include "ObjectPool.hpp" + using namespace std; diff --git a/latest/Firmware/Inc/RadioManager.hpp b/latest/Firmware/Inc/RadioManager.hpp index 0b2c5c5..77ac5a4 100644 --- a/latest/Firmware/Inc/RadioManager.hpp +++ b/latest/Firmware/Inc/RadioManager.hpp @@ -30,7 +30,7 @@ #include "AISChannels.h" -class RadioManager : public GPSDelegate, public EventConsumer +class RadioManager : public GPSDelegate, EventConsumer { public: static RadioManager &instance(); @@ -49,7 +49,6 @@ public: void transmitCW(VHFChannel channel); VHFChannel alternateChannel(VHFChannel channel); - private: RadioManager(); void spiOff(); @@ -58,9 +57,9 @@ private: Transceiver *mTransceiverIC; Receiver *mReceiverIC; bool mInitializing; - - CircularQueue *mTXQueue; time_t mUTC; + + CircularQueue mTXQueue; }; #endif /* RADIOMANAGER_HPP_ */ diff --git a/latest/Firmware/Inc/Receiver.hpp b/latest/Firmware/Inc/Receiver.hpp index f5169f6..9d9052a 100644 --- a/latest/Firmware/Inc/Receiver.hpp +++ b/latest/Firmware/Inc/Receiver.hpp @@ -57,7 +57,7 @@ protected: void processNRZIBit(uint8_t level); virtual void configureGPIOsForRX(); protected: - RXPacket mRXPacket; + RXPacket *mRXPacket = nullptr; uint16_t mBitWindow; uint8_t mLastNRZIBit; uint32_t mBitCount; diff --git a/latest/Firmware/Inc/Transceiver.hpp b/latest/Firmware/Inc/Transceiver.hpp index 68ca2e6..6f5ad87 100644 --- a/latest/Firmware/Inc/Transceiver.hpp +++ b/latest/Firmware/Inc/Transceiver.hpp @@ -23,10 +23,10 @@ #include "Receiver.hpp" #include "TXPacket.hpp" -#include "EventQueue.hpp" +#include "Events.hpp" #include -class Transceiver : public Receiver, EventConsumer +class Transceiver : public Receiver, public EventConsumer { public: Transceiver(GPIO_TypeDef *sdnPort, diff --git a/latest/Firmware/Inc/_assert.h b/latest/Firmware/Inc/_assert.h index 8a1dcc9..b17433c 100644 --- a/latest/Firmware/Inc/_assert.h +++ b/latest/Firmware/Inc/_assert.h @@ -20,16 +20,18 @@ #ifndef ASSERT_H_ #define ASSERT_H_ -#include - -#include "config.h" -#include "printf_serial.h" -#if DEV_MODE -#define ASSERT(b) if (!(b)) {assert_failed((uint8_t*)__FILE__, (uint32_t)__LINE__); } +#ifdef DEBUG +#define ASSERT(b) if (!(b)) {asm("bkpt 0");} #else -#define ASSERT(b) assert(b); +#define ASSERT(b) +#endif + +#ifdef DEBUG +#define ASSERT_VALID_PTR(p) ASSERT((uint32_t)p >= 0x20000000 && (uint32_t)p <= 0x20009FFF) +#else +#define ASSERT_VALID_PTR(p) #endif diff --git a/latest/Firmware/Src/Events.cpp b/latest/Firmware/Src/Events.cpp index b8fe801..c7b3a4a 100644 --- a/latest/Firmware/Src/Events.cpp +++ b/latest/Firmware/Src/Events.cpp @@ -21,17 +21,52 @@ #include "Events.hpp" #include "printf_serial.h" -#if 1 + +/////////////////////////////////////////////////////////////////////////////// +// +// Event +// +/////////////////////////////////////////////////////////////////////////////// + +Event::Event() + : type(UNKNOWN_EVENT), flags(0), rxPacket(nullptr) +{ +} + +void Event::reset() +{ + if ( rxPacket ) + { + ASSERT_VALID_PTR(rxPacket); + EventPool::instance().releaseRXPacket(rxPacket); + } + + rxPacket = nullptr; + + type = UNKNOWN_EVENT; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// EventPool +// +/////////////////////////////////////////////////////////////////////////////// + EventPool &EventPool::instance() { static EventPool __instance; return __instance; } + +EventPool::EventPool() + : mISRPool(25), mThreadPool(10), mRXPool(20) +{ + +} + void EventPool::init() { - mISRPool = new ObjectPool(25); - mThreadPool = new ObjectPool(10); } Event *EventPool::newEvent(EventType type) @@ -39,20 +74,22 @@ Event *EventPool::newEvent(EventType type) Event *result = nullptr; if ( Utils::inISR() ) { - result = mISRPool->get(); + result = mISRPool.get(); if ( result ) { result->type = type; result->flags = 1; + ASSERT(!result->rxPacket); } } else { - result = mThreadPool->get(); + result = mThreadPool.get(); if ( result ) { result->type = type; result->flags = 0; + ASSERT(!result->rxPacket); } } @@ -60,25 +97,43 @@ Event *EventPool::newEvent(EventType type) //if ( !result) //printf2_now("\r\n[DEBUG]newEvent(0x%.8x) failed\r\n", type); + if ( result == nullptr ) + return result; + + ASSERT_VALID_PTR(result); return result; } void EventPool::deleteEvent(Event *event) { - ASSERT(event); + ASSERT_VALID_PTR(event); + event->reset(); if ( event->flags ) - mISRPool->put(event); + mISRPool.put(event); else - mThreadPool->put(event); + mThreadPool.put(event); } uint32_t EventPool::maxUtilization() { - return std::max(mISRPool->maxUtilization(), mThreadPool->maxUtilization()); + return std::max(mISRPool.maxUtilization(), mThreadPool.maxUtilization()); } uint32_t EventPool::utilization() { - return std::max(mISRPool->utilization(), mThreadPool->utilization()); + return std::max(mISRPool.utilization(), mThreadPool.utilization()); } -#endif + +RXPacket *EventPool::newRXPacket() +{ + RXPacket *p = mRXPool.get(); + ASSERT_VALID_PTR(p); + return p; +} + +void EventPool::releaseRXPacket(RXPacket *packet) +{ + ASSERT_VALID_PTR(packet); + mRXPool.put(packet); +} + diff --git a/latest/Firmware/Src/GPS.cpp b/latest/Firmware/Src/GPS.cpp index 304e19a..3cd5dcf 100644 --- a/latest/Firmware/Src/GPS.cpp +++ b/latest/Firmware/Src/GPS.cpp @@ -182,15 +182,14 @@ void GPS::onPPS() void GPS::processEvent(const Event &event) { - //printf2("-> GPS::processEvent()\r\n"); - processLine(event.nmeaBuffer.sentence); - //printf2("<- GPS::processEvent()\r\n"); + ASSERT(event.rxPacket == nullptr); } void GPS::processLine(const char* buff) { - if ( buff[0] == '$' && buff[1] != '$' ) { + if ( buff[0] == '$' && buff[1] != '$' ) + { unsigned reportedHash; char *starPos = strstr(buff, "*"); if ( starPos && sscanf(starPos + 1, "%x", &reportedHash) == 1 ) @@ -205,7 +204,7 @@ void GPS::processLine(const char* buff) } } - } + } } void GPS::parseSentence(const char *buff) diff --git a/latest/Firmware/Src/RXPacketProcessor.cpp b/latest/Firmware/Src/RXPacketProcessor.cpp index 2cfc33d..ca235ce 100644 --- a/latest/Firmware/Src/RXPacketProcessor.cpp +++ b/latest/Firmware/Src/RXPacketProcessor.cpp @@ -15,11 +15,13 @@ You should have received a copy of the GNU General Public License along with this program. If not, see -*/ + */ #include +#include "_assert.h" #include "config.h" +#include "RadioManager.hpp" #include "RXPacketProcessor.hpp" #include "AISMessages.hpp" #include "DataTerminal.hpp" @@ -51,13 +53,14 @@ void RXPacketProcessor::processEvent(const Event &e) { case AIS_PACKET_EVENT: { - if (e.rxPacket.isBad() || !e.rxPacket.checkCRC ()) + ASSERT(e.rxPacket); + if (e.rxPacket->isBad() || !e.rxPacket->checkCRC ()) return; - if ( e.rxPacket.messageType() == 15 ) + if ( e.rxPacket->messageType() == 15 ) { AISMessage15 msg; - if ( msg.decode(e.rxPacket) ) + if ( msg.decode(*e.rxPacket) ) { // Make sure we actually can transmit something if ( mStationData.magic != STATION_DATA_MAGIC ) @@ -100,9 +103,8 @@ void RXPacketProcessor::processEvent(const Event &e) mSentences.clear(); - // Need to make a copy to mutate the packet - RXPacket p(e.rxPacket); - mEncoder.encode(p, mSentences); + ASSERT_VALID_PTR(e.rxPacket); + mEncoder.encode(*(e.rxPacket), mSentences); for (vector::iterator i = mSentences.begin(); i != mSentences.end(); ++i) { #ifdef MULTIPLEXED_OUTPUT @@ -116,7 +118,7 @@ void RXPacketProcessor::processEvent(const Event &e) // Special handling for specific messages that we care about - switch (e.rxPacket.messageType()) + switch (e.rxPacket->messageType()) { case 20: // TODO: This is a time slot reservation from a base station. Use this information to block those time slots. diff --git a/latest/Firmware/Src/RadioManager.cpp b/latest/Firmware/Src/RadioManager.cpp index 40a3725..63c3ece 100644 --- a/latest/Firmware/Src/RadioManager.cpp +++ b/latest/Firmware/Src/RadioManager.cpp @@ -34,11 +34,12 @@ RadioManager &RadioManager::instance() } RadioManager::RadioManager() + : mTXQueue(4) { mTransceiverIC = NULL; mReceiverIC = NULL; mInitializing = true; - mTXQueue = new CircularQueue(4); + //mTXQueue = new CircularQueue(4); mUTC = 0; EventQueue::instance().addObserver(this, CLOCK_EVENT); } @@ -104,11 +105,11 @@ void RadioManager::processEvent(const Event &e) // Evaluate the state of the transceiver IC and our queue ... if ( mTransceiverIC->assignedTXPacket() == NULL ) { - if ( !mTXQueue->empty() ) + if ( !mTXQueue.empty() ) { // There is no current TX operation pending, so we assign one TXPacket *packet = NULL; - mTXQueue->pop(packet); + mTXQueue.pop(packet); ASSERT(packet); VHFChannel txChannel = packet->channel(); @@ -161,7 +162,7 @@ void RadioManager::timeSlotStarted(uint32_t slotNumber) void RadioManager::scheduleTransmission(TXPacket *packet) { - if ( mTXQueue->push(packet) ) + if ( mTXQueue.push(packet) ) { //DBG("RadioManager queued TX packet for channel %d\r\n", ORDINAL_TO_ITU(packet->channel())); } diff --git a/latest/Firmware/Src/Receiver.cpp b/latest/Firmware/Src/Receiver.cpp index 56c57d2..fef851d 100644 --- a/latest/Firmware/Src/Receiver.cpp +++ b/latest/Firmware/Src/Receiver.cpp @@ -40,6 +40,8 @@ Receiver::Receiver(GPIO_TypeDef *sdnPort, uint32_t sdnPin, GPIO_TypeDef *csPort, mSwitchToChannel = mChannel; mRXByte = 0; mBitWindow = 0; + mRXPacket = EventPool::instance().newRXPacket(); + ASSERT_VALID_PTR(mRXPacket); } Receiver::~Receiver() @@ -100,7 +102,7 @@ void Receiver::resetBitScanner() mRXByte = 0; mBitState = BIT_STATE_PREAMBLE_SYNC; - mRXPacket.reset(); + mRXPacket->reset(); } void Receiver::onBitClock() @@ -109,20 +111,16 @@ void Receiver::onBitClock() if ( gRadioState == RADIO_TRANSMITTING ) return; - bsp_signal_high(); + //bsp_signal_high(); uint8_t bit = HAL_GPIO_ReadPin(mDataPort, mDataPin); processNRZIBit(bit); -#if 1 if ( mSlotBitNumber != 0xffff && mSlotBitNumber++ == CCA_SLOT_BIT - 1 ) { uint8_t rssi = reportRSSI(); - mRXPacket.setRSSI(rssi); + mRXPacket->setRSSI(rssi); } -#else - ++mSlotBitNumber; -#endif - bsp_signal_low(); + //bsp_signal_low(); } void Receiver::timeSlotStarted(uint32_t slot) @@ -136,7 +134,7 @@ void Receiver::timeSlotStarted(uint32_t slot) if ( mBitState == BIT_STATE_IN_PACKET ) return; - mRXPacket.setSlot(slot); + mRXPacket->setSlot(slot); if ( mSwitchAtNextSlot ) { mSwitchAtNextSlot = false; @@ -168,14 +166,14 @@ void Receiver::processNRZIBit(uint8_t bit) if ( mBitWindow == 0b1010101001111110 || mBitWindow == 0b0101010101111110 ) { mBitState = BIT_STATE_IN_PACKET; - mRXPacket.setChannel(mChannel); + mRXPacket->setChannel(mChannel); } break; } case BIT_STATE_IN_PACKET: { - if ( mRXPacket.size() >= MAX_AIS_RX_PACKET_SIZE ) + if ( mRXPacket->size() >= MAX_AIS_RX_PACKET_SIZE ) { // Start over startReceiving(mChannel); @@ -240,7 +238,7 @@ bool Receiver::addBit(uint8_t bit) if ( mBitCount == 8 ) { // Commit to the packet! - mRXPacket.addByte(mRXByte); + mRXPacket->addByte(mRXByte); mBitCount = 0; mRXByte = 0; } @@ -251,14 +249,19 @@ bool Receiver::addBit(uint8_t bit) void Receiver::pushPacket() { Event *p = EventPool::instance().newEvent(AIS_PACKET_EVENT); + RXPacket *currPacket = mRXPacket; + mRXPacket = EventPool::instance().newRXPacket(); + ASSERT_VALID_PTR(mRXPacket); + if ( p ) { bsp_signal_high(); - p->rxPacket = mRXPacket; - bsp_signal_low(); + p->rxPacket = currPacket; EventQueue::instance().push(p); + bsp_signal_low(); } - mRXPacket.reset(); + + mRXPacket->reset(); } uint8_t Receiver::reportRSSI() diff --git a/latest/Firmware/Src/Transceiver.cpp b/latest/Firmware/Src/Transceiver.cpp index abf0723..840966b 100644 --- a/latest/Firmware/Src/Transceiver.cpp +++ b/latest/Firmware/Src/Transceiver.cpp @@ -217,7 +217,7 @@ void Transceiver::onBitClock() } else if ( mUTC && mSlotBitNumber == CCA_SLOT_BIT && mTXPacket->channel() == mChannel ) { - int rssi = mRXPacket.rssi(); + int rssi = mRXPacket->rssi(); int nf = NoiseFloorDetector::instance().getNoiseFloor(AIS_CHANNELS[mChannel].designation); if ( rssi <= nf + TX_CCA_HEADROOM ) { diff --git a/latest/Firmware/Src/main.cpp b/latest/Firmware/Src/main.cpp index d356509..77fd71c 100644 --- a/latest/Firmware/Src/main.cpp +++ b/latest/Firmware/Src/main.cpp @@ -97,7 +97,7 @@ int main(void) bsp_hw_init(); TaskHandle_t xHandle; - if ( xTaskCreate(mainTask, "main", 2048u, NULL, tskIDLE_PRIORITY+4, &xHandle) != pdPASS ) + if ( xTaskCreate(mainTask, "main", 2248u, NULL, tskIDLE_PRIORITY+4, &xHandle) != pdPASS ) { asm("BKPT 0"); }