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

View File

@ -61,9 +61,10 @@
#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.
* 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
# define UAVCAN_TINY 0

View File

@ -86,13 +86,16 @@ class UAVCAN_EXPORT MapBase : Noncopyable
LinkedListRoot<KVGroup> list_;
IPoolAllocator& allocator_;
#if !UAVCAN_TINY
KVPair* const static_;
const unsigned num_static_entries_;
#endif
KVPair* find(const Key& key);
#if !UAVCAN_TINY
void optimizeStorage();
#endif
void compact();
struct YesPredicate
@ -101,6 +104,13 @@ class UAVCAN_EXPORT MapBase : Noncopyable
};
protected:
#if UAVCAN_TINY
MapBase(IPoolAllocator& allocator)
: allocator_(allocator)
{
assert(Key() == Key());
}
#else
MapBase(KVPair* static_buf, unsigned num_static_entries, IPoolAllocator& allocator)
: allocator_(allocator)
, static_(static_buf)
@ -108,6 +118,7 @@ protected:
{
assert(Key() == Key());
}
#endif
/// Derived class destructor must call removeAll();
~MapBase() { }
@ -149,11 +160,17 @@ class UAVCAN_EXPORT Map : public MapBase<Key, Value>
typename MapBase<Key, Value>::KVPair static_[NumStaticEntries];
public:
#if !UAVCAN_TINY
// This instantiation will not be valid in UAVCAN_TINY mode
Map(IPoolAllocator& allocator)
: MapBase<Key, Value>(static_, NumStaticEntries, allocator)
{ }
~Map() { this->removeAll(); }
#endif // !UAVCAN_TINY
};
@ -162,7 +179,11 @@ class UAVCAN_EXPORT Map<Key, Value, 0> : public MapBase<Key, Value>
{
public:
Map(IPoolAllocator& allocator)
#if UAVCAN_TINY
: MapBase<Key, Value>(allocator)
#else
: MapBase<Key, Value>(NULL, 0, allocator)
#endif
{ }
~Map() { this->removeAll(); }
@ -176,6 +197,7 @@ public:
template <typename Key, typename Value>
typename MapBase<Key, Value>::KVPair* MapBase<Key, Value>::find(const Key& key)
{
#if !UAVCAN_TINY
for (unsigned i = 0; i < num_static_entries_; i++)
{
if (static_[i].match(key))
@ -183,6 +205,7 @@ typename MapBase<Key, Value>::KVPair* MapBase<Key, Value>::find(const Key& key)
return static_ + i;
}
}
#endif
KVGroup* p = list_.get();
while (p)
@ -197,6 +220,8 @@ typename MapBase<Key, Value>::KVPair* MapBase<Key, Value>::find(const Key& key)
return NULL;
}
#if !UAVCAN_TINY
template <typename Key, typename Value>
void MapBase<Key, Value>::optimizeStorage()
{
@ -249,6 +274,8 @@ void MapBase<Key, Value>::optimizeStorage()
}
}
#endif // !UAVCAN_TINY
template <typename Key, typename Value>
void MapBase<Key, Value>::compact()
{
@ -313,7 +340,9 @@ void MapBase<Key, Value>::remove(const Key& key)
if (kv)
{
*kv = KVPair();
#if !UAVCAN_TINY
optimizeStorage();
#endif
compact();
}
}
@ -324,6 +353,7 @@ void MapBase<Key, Value>::removeWhere(Predicate predicate)
{
unsigned num_removed = 0;
#if !UAVCAN_TINY
for (unsigned i = 0; i < num_static_entries_; i++)
{
if (!static_[i].match(Key()))
@ -335,6 +365,7 @@ void MapBase<Key, Value>::removeWhere(Predicate predicate)
}
}
}
#endif
KVGroup* p = list_.get();
while (p)
@ -356,7 +387,9 @@ void MapBase<Key, Value>::removeWhere(Predicate predicate)
if (num_removed > 0)
{
#if !UAVCAN_TINY
optimizeStorage();
#endif
compact();
}
}
@ -365,6 +398,7 @@ template <typename Key, typename Value>
template <typename Predicate>
const Key* MapBase<Key, Value>::findFirstKey(Predicate predicate) const
{
#if !UAVCAN_TINY
for (unsigned i = 0; i < num_static_entries_; i++)
{
if (!static_[i].match(Key()))
@ -375,6 +409,7 @@ const Key* MapBase<Key, Value>::findFirstKey(Predicate predicate) const
}
}
}
#endif
KVGroup* p = list_.get();
while (p)
@ -411,6 +446,7 @@ template <typename Key, typename Value>
unsigned MapBase<Key, Value>::getNumStaticPairs() const
{
unsigned num = 0;
#if !UAVCAN_TINY
for (unsigned i = 0; i < num_static_entries_; i++)
{
if (!static_[i].match(Key()))
@ -418,6 +454,7 @@ unsigned MapBase<Key, Value>::getNumStaticPairs() const
num++;
}
}
#endif
return num;
}

View File

@ -98,11 +98,16 @@ class UAVCAN_EXPORT TransferListenerInstantiationHelper
enum { DataTypeMaxByteLen = BitLenToByteLen<DataStruct_::MaxBitLen>::Result };
enum { NeedsBuffer = int(DataTypeMaxByteLen) > int(MaxSingleFrameTransferPayloadLen) };
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:
// TODO: support for zero static bufs
typedef TransferListener<BufferSize, NumStaticBufs, NumStaticReceivers_ ? NumStaticReceivers_ : 1> Type;
typedef TransferListener<BufferSize, NumStaticBufs, NumStaticReceivers> Type;
};

View File

@ -30,8 +30,14 @@ namespace uavcan
{
template <std::size_t MemPoolSize_,
#if UAVCAN_TINY
unsigned OutgoingTransferRegistryStaticEntries = 0,
unsigned OutgoingTransferMaxPayloadLen = 264
#else
unsigned OutgoingTransferRegistryStaticEntries = 10,
unsigned OutgoingTransferMaxPayloadLen = MaxTransferPayloadLen>
unsigned OutgoingTransferMaxPayloadLen = MaxTransferPayloadLen
#endif
>
class UAVCAN_EXPORT Node : public INode
{
enum

View File

@ -27,8 +27,14 @@ template <typename DataType_,
typename Callback_ = void (*)(const ReceivedDataStructure<typename DataType_::Request>&,
typename DataType_::Response&),
#endif
#if UAVCAN_TINY
unsigned NumStaticReceivers = 0,
unsigned NumStaticBufs = 0
#else
unsigned NumStaticReceivers = 2,
unsigned NumStaticBufs = 1>
unsigned NumStaticBufs = 1
#endif
>
class UAVCAN_EXPORT ServiceServer
: public GenericSubscriber<DataType_, typename DataType_::Request,
typename TransferListenerInstantiationHelper<typename DataType_::Request,

View File

@ -25,8 +25,14 @@ template <typename DataType_,
#else
typename Callback_ = void (*)(const ReceivedDataStructure<DataType_>&),
#endif
#if UAVCAN_TINY
unsigned NumStaticReceivers = 0,
unsigned NumStaticBufs = 0
#else
unsigned NumStaticReceivers = 2,
unsigned NumStaticBufs = 1>
unsigned NumStaticBufs = 1
#endif
>
class UAVCAN_EXPORT Subscriber
: public GenericSubscriber<DataType_, DataType_,
typename TransferListenerInstantiationHelper<DataType_, NumStaticReceivers,

View File

@ -298,6 +298,9 @@ public:
TransferBufferManager(IPoolAllocator& 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();
}
};
@ -305,7 +308,7 @@ public:
template <uint16_t MaxBufSize>
class UAVCAN_EXPORT TransferBufferManager<MaxBufSize, 0> : public TransferBufferManagerImpl
{
StaticTransferBufferManagerEntry<MaxBufSize>* getStaticByIndex(uint16_t index) const
StaticTransferBufferManagerEntry<MaxBufSize>* getStaticByIndex(uint16_t) const
{
return NULL;
}

View File

@ -150,6 +150,10 @@ public:
, bufmgr_(allocator)
, receivers_(allocator)
{
#if UAVCAN_TINY
StaticAssert<NumStaticBufs == 0>::check();
StaticAssert<NumStaticReceivers == 0>::check();
#endif
StaticAssert<(NumStaticReceivers >= NumStaticBufs)>::check(); // Otherwise it would be meaningless
}
@ -164,7 +168,12 @@ public:
* This class should be derived by callers.
*/
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:
struct ExpectedResponseParams

View File

@ -10,7 +10,7 @@
namespace
{
typedef uavcan::Node<2048> Node;
typedef uavcan::Node<3584> Node;
Node& getNode()
{