Heavy optimizations for ROM/RAM usage in UAVCAN_TINY mode

This commit is contained in:
Pavel Kirienko
2014-04-16 21:11:42 +04:00
parent 4085613d00
commit 87e89fc042
9 changed files with 85 additions and 12 deletions
+3 -2
View File
@@ -61,9 +61,10 @@
#endif #endif
/** /**
* Functionality / Code Size trade-off. * Trade-off between ROM/RAM usage and functionality/determinism.
* Note that this feature is not well tested and should be avoided.
* Use code search for UAVCAN_TINY to find what functionality will be disabled. * Use code search for UAVCAN_TINY to find what functionality will be disabled.
* This is particularly useful for embedded systems with less than 64kB of ROM. * This is particularly useful for embedded systems with less than 40kB of ROM.
*/ */
#ifndef UAVCAN_TINY #ifndef UAVCAN_TINY
# define UAVCAN_TINY 0 # define UAVCAN_TINY 0
+38 -1
View File
@@ -86,13 +86,16 @@ class UAVCAN_EXPORT MapBase : Noncopyable
LinkedListRoot<KVGroup> list_; LinkedListRoot<KVGroup> list_;
IPoolAllocator& allocator_; IPoolAllocator& allocator_;
#if !UAVCAN_TINY
KVPair* const static_; KVPair* const static_;
const unsigned num_static_entries_; const unsigned num_static_entries_;
#endif
KVPair* find(const Key& key); KVPair* find(const Key& key);
#if !UAVCAN_TINY
void optimizeStorage(); void optimizeStorage();
#endif
void compact(); void compact();
struct YesPredicate struct YesPredicate
@@ -101,6 +104,13 @@ class UAVCAN_EXPORT MapBase : Noncopyable
}; };
protected: protected:
#if UAVCAN_TINY
MapBase(IPoolAllocator& allocator)
: allocator_(allocator)
{
assert(Key() == Key());
}
#else
MapBase(KVPair* static_buf, unsigned num_static_entries, IPoolAllocator& allocator) MapBase(KVPair* static_buf, unsigned num_static_entries, IPoolAllocator& allocator)
: allocator_(allocator) : allocator_(allocator)
, static_(static_buf) , static_(static_buf)
@@ -108,6 +118,7 @@ protected:
{ {
assert(Key() == Key()); assert(Key() == Key());
} }
#endif
/// Derived class destructor must call removeAll(); /// Derived class destructor must call removeAll();
~MapBase() { } ~MapBase() { }
@@ -149,11 +160,17 @@ class UAVCAN_EXPORT Map : public MapBase<Key, Value>
typename MapBase<Key, Value>::KVPair static_[NumStaticEntries]; typename MapBase<Key, Value>::KVPair static_[NumStaticEntries];
public: public:
#if !UAVCAN_TINY
// This instantiation will not be valid in UAVCAN_TINY mode
Map(IPoolAllocator& allocator) Map(IPoolAllocator& allocator)
: MapBase<Key, Value>(static_, NumStaticEntries, allocator) : MapBase<Key, Value>(static_, NumStaticEntries, allocator)
{ } { }
~Map() { this->removeAll(); } ~Map() { this->removeAll(); }
#endif // !UAVCAN_TINY
}; };
@@ -162,7 +179,11 @@ class UAVCAN_EXPORT Map<Key, Value, 0> : public MapBase<Key, Value>
{ {
public: public:
Map(IPoolAllocator& allocator) Map(IPoolAllocator& allocator)
#if UAVCAN_TINY
: MapBase<Key, Value>(allocator)
#else
: MapBase<Key, Value>(NULL, 0, allocator) : MapBase<Key, Value>(NULL, 0, allocator)
#endif
{ } { }
~Map() { this->removeAll(); } ~Map() { this->removeAll(); }
@@ -176,6 +197,7 @@ public:
template <typename Key, typename Value> template <typename Key, typename Value>
typename MapBase<Key, Value>::KVPair* MapBase<Key, Value>::find(const Key& key) typename MapBase<Key, Value>::KVPair* MapBase<Key, Value>::find(const Key& key)
{ {
#if !UAVCAN_TINY
for (unsigned i = 0; i < num_static_entries_; i++) for (unsigned i = 0; i < num_static_entries_; i++)
{ {
if (static_[i].match(key)) if (static_[i].match(key))
@@ -183,6 +205,7 @@ typename MapBase<Key, Value>::KVPair* MapBase<Key, Value>::find(const Key& key)
return static_ + i; return static_ + i;
} }
} }
#endif
KVGroup* p = list_.get(); KVGroup* p = list_.get();
while (p) while (p)
@@ -197,6 +220,8 @@ typename MapBase<Key, Value>::KVPair* MapBase<Key, Value>::find(const Key& key)
return NULL; return NULL;
} }
#if !UAVCAN_TINY
template <typename Key, typename Value> template <typename Key, typename Value>
void MapBase<Key, Value>::optimizeStorage() void MapBase<Key, Value>::optimizeStorage()
{ {
@@ -249,6 +274,8 @@ void MapBase<Key, Value>::optimizeStorage()
} }
} }
#endif // !UAVCAN_TINY
template <typename Key, typename Value> template <typename Key, typename Value>
void MapBase<Key, Value>::compact() void MapBase<Key, Value>::compact()
{ {
@@ -313,7 +340,9 @@ void MapBase<Key, Value>::remove(const Key& key)
if (kv) if (kv)
{ {
*kv = KVPair(); *kv = KVPair();
#if !UAVCAN_TINY
optimizeStorage(); optimizeStorage();
#endif
compact(); compact();
} }
} }
@@ -324,6 +353,7 @@ void MapBase<Key, Value>::removeWhere(Predicate predicate)
{ {
unsigned num_removed = 0; unsigned num_removed = 0;
#if !UAVCAN_TINY
for (unsigned i = 0; i < num_static_entries_; i++) for (unsigned i = 0; i < num_static_entries_; i++)
{ {
if (!static_[i].match(Key())) if (!static_[i].match(Key()))
@@ -335,6 +365,7 @@ void MapBase<Key, Value>::removeWhere(Predicate predicate)
} }
} }
} }
#endif
KVGroup* p = list_.get(); KVGroup* p = list_.get();
while (p) while (p)
@@ -356,7 +387,9 @@ void MapBase<Key, Value>::removeWhere(Predicate predicate)
if (num_removed > 0) if (num_removed > 0)
{ {
#if !UAVCAN_TINY
optimizeStorage(); optimizeStorage();
#endif
compact(); compact();
} }
} }
@@ -365,6 +398,7 @@ template <typename Key, typename Value>
template <typename Predicate> template <typename Predicate>
const Key* MapBase<Key, Value>::findFirstKey(Predicate predicate) const const Key* MapBase<Key, Value>::findFirstKey(Predicate predicate) const
{ {
#if !UAVCAN_TINY
for (unsigned i = 0; i < num_static_entries_; i++) for (unsigned i = 0; i < num_static_entries_; i++)
{ {
if (!static_[i].match(Key())) if (!static_[i].match(Key()))
@@ -375,6 +409,7 @@ const Key* MapBase<Key, Value>::findFirstKey(Predicate predicate) const
} }
} }
} }
#endif
KVGroup* p = list_.get(); KVGroup* p = list_.get();
while (p) while (p)
@@ -411,6 +446,7 @@ template <typename Key, typename Value>
unsigned MapBase<Key, Value>::getNumStaticPairs() const unsigned MapBase<Key, Value>::getNumStaticPairs() const
{ {
unsigned num = 0; unsigned num = 0;
#if !UAVCAN_TINY
for (unsigned i = 0; i < num_static_entries_; i++) for (unsigned i = 0; i < num_static_entries_; i++)
{ {
if (!static_[i].match(Key())) if (!static_[i].match(Key()))
@@ -418,6 +454,7 @@ unsigned MapBase<Key, Value>::getNumStaticPairs() const
num++; num++;
} }
} }
#endif
return num; return num;
} }
@@ -98,11 +98,16 @@ class UAVCAN_EXPORT TransferListenerInstantiationHelper
enum { DataTypeMaxByteLen = BitLenToByteLen<DataStruct_::MaxBitLen>::Result }; enum { DataTypeMaxByteLen = BitLenToByteLen<DataStruct_::MaxBitLen>::Result };
enum { NeedsBuffer = int(DataTypeMaxByteLen) > int(MaxSingleFrameTransferPayloadLen) }; enum { NeedsBuffer = int(DataTypeMaxByteLen) > int(MaxSingleFrameTransferPayloadLen) };
enum { BufferSize = NeedsBuffer ? DataTypeMaxByteLen : 0 }; enum { BufferSize = NeedsBuffer ? DataTypeMaxByteLen : 0 };
enum { NumStaticBufs = NeedsBuffer ? (NumStaticBufs_ ? NumStaticBufs_ : 1) : 0 }; #if UAVCAN_TINY
enum { NumStaticBufs = 0 };
enum { NumStaticReceivers = 0 };
#else
enum { NumStaticBufs = NeedsBuffer ? NumStaticBufs_: 0 };
enum { NumStaticReceivers = NumStaticReceivers_ };
#endif
public: public:
// TODO: support for zero static bufs typedef TransferListener<BufferSize, NumStaticBufs, NumStaticReceivers> Type;
typedef TransferListener<BufferSize, NumStaticBufs, NumStaticReceivers_ ? NumStaticReceivers_ : 1> Type;
}; };
+7 -1
View File
@@ -30,8 +30,14 @@ namespace uavcan
{ {
template <std::size_t MemPoolSize_, template <std::size_t MemPoolSize_,
#if UAVCAN_TINY
unsigned OutgoingTransferRegistryStaticEntries = 0,
unsigned OutgoingTransferMaxPayloadLen = 264
#else
unsigned OutgoingTransferRegistryStaticEntries = 10, unsigned OutgoingTransferRegistryStaticEntries = 10,
unsigned OutgoingTransferMaxPayloadLen = MaxTransferPayloadLen> unsigned OutgoingTransferMaxPayloadLen = MaxTransferPayloadLen
#endif
>
class UAVCAN_EXPORT Node : public INode class UAVCAN_EXPORT Node : public INode
{ {
enum enum
@@ -27,8 +27,14 @@ template <typename DataType_,
typename Callback_ = void (*)(const ReceivedDataStructure<typename DataType_::Request>&, typename Callback_ = void (*)(const ReceivedDataStructure<typename DataType_::Request>&,
typename DataType_::Response&), typename DataType_::Response&),
#endif #endif
#if UAVCAN_TINY
unsigned NumStaticReceivers = 0,
unsigned NumStaticBufs = 0
#else
unsigned NumStaticReceivers = 2, unsigned NumStaticReceivers = 2,
unsigned NumStaticBufs = 1> unsigned NumStaticBufs = 1
#endif
>
class UAVCAN_EXPORT ServiceServer class UAVCAN_EXPORT ServiceServer
: public GenericSubscriber<DataType_, typename DataType_::Request, : public GenericSubscriber<DataType_, typename DataType_::Request,
typename TransferListenerInstantiationHelper<typename DataType_::Request, typename TransferListenerInstantiationHelper<typename DataType_::Request,
+7 -1
View File
@@ -25,8 +25,14 @@ template <typename DataType_,
#else #else
typename Callback_ = void (*)(const ReceivedDataStructure<DataType_>&), typename Callback_ = void (*)(const ReceivedDataStructure<DataType_>&),
#endif #endif
#if UAVCAN_TINY
unsigned NumStaticReceivers = 0,
unsigned NumStaticBufs = 0
#else
unsigned NumStaticReceivers = 2, unsigned NumStaticReceivers = 2,
unsigned NumStaticBufs = 1> unsigned NumStaticBufs = 1
#endif
>
class UAVCAN_EXPORT Subscriber class UAVCAN_EXPORT Subscriber
: public GenericSubscriber<DataType_, DataType_, : public GenericSubscriber<DataType_, DataType_,
typename TransferListenerInstantiationHelper<DataType_, NumStaticReceivers, typename TransferListenerInstantiationHelper<DataType_, NumStaticReceivers,
@@ -298,6 +298,9 @@ public:
TransferBufferManager(IPoolAllocator& allocator) TransferBufferManager(IPoolAllocator& allocator)
: TransferBufferManagerImpl(MaxBufSize, allocator) : TransferBufferManagerImpl(MaxBufSize, allocator)
{ {
#if UAVCAN_TINY
StaticAssert<(NumStaticBufs == 0)>::check(); // Static buffers in UAVCAN_TINY mode are not allowed
#endif
StaticAssert<(MaxBufSize > 0)>::check(); StaticAssert<(MaxBufSize > 0)>::check();
} }
}; };
@@ -305,7 +308,7 @@ public:
template <uint16_t MaxBufSize> template <uint16_t MaxBufSize>
class UAVCAN_EXPORT TransferBufferManager<MaxBufSize, 0> : public TransferBufferManagerImpl class UAVCAN_EXPORT TransferBufferManager<MaxBufSize, 0> : public TransferBufferManagerImpl
{ {
StaticTransferBufferManagerEntry<MaxBufSize>* getStaticByIndex(uint16_t index) const StaticTransferBufferManagerEntry<MaxBufSize>* getStaticByIndex(uint16_t) const
{ {
return NULL; return NULL;
} }
@@ -150,6 +150,10 @@ public:
, bufmgr_(allocator) , bufmgr_(allocator)
, receivers_(allocator) , receivers_(allocator)
{ {
#if UAVCAN_TINY
StaticAssert<NumStaticBufs == 0>::check();
StaticAssert<NumStaticReceivers == 0>::check();
#endif
StaticAssert<(NumStaticReceivers >= NumStaticBufs)>::check(); // Otherwise it would be meaningless StaticAssert<(NumStaticReceivers >= NumStaticBufs)>::check(); // Otherwise it would be meaningless
} }
@@ -164,7 +168,12 @@ public:
* This class should be derived by callers. * This class should be derived by callers.
*/ */
template <unsigned MaxBufSize> template <unsigned MaxBufSize>
class UAVCAN_EXPORT ServiceResponseTransferListener : public TransferListener<MaxBufSize, 1, 1> class UAVCAN_EXPORT ServiceResponseTransferListener
#if UAVCAN_TINY
: public TransferListener<MaxBufSize, 0, 0>
#else
: public TransferListener<MaxBufSize, 1, 1>
#endif
{ {
public: public:
struct ExpectedResponseParams struct ExpectedResponseParams
@@ -10,7 +10,7 @@
namespace namespace
{ {
typedef uavcan::Node<2048> Node; typedef uavcan::Node<3584> Node;
Node& getNode() Node& getNode()
{ {