October 15, 2019, 5:13pm
Regarding the S32K driver layer for libuavcan, the current implementation uses an almost naive use of the deque STL for limiting the size of the RX queue as shown briefly next:
if (RX_ISRframeCount <= Frame_Capactiy )
/* Insert the frame into the queue */
And in the read function it will be inverted as shown:
/* Check if the ISR buffer isn't empty */
/* Get the front element of the queue buffer */
out_frames = FS32K_InterfaceManager::frame_ISRbuffer.front();
/* Pop the front element of the queue buffer */
/* Decrease frame count */
¿How can the deque STL be used while keeping a static deterministic ISR buffer?
Thank you in advance.
Hi Abraham. I am no
@scottdixon, but if I were impersonating him I would have probably said:
Replace the ellipsis with the appropriate parameters as needed. The second template parameter
libuavcan::platform::memory::PoolAllocator comes from:
This file has been truncated.
* Adapter to provide STL and other instances access to a shared memory pool.
* @tparam NumBlocksParam The number of blocks to allocate in the memory pool.
* @tparam BlockSizeParam The size in bytes of each block in the memory pool.
* @tparam T A type alias used to pretend that the pointers returned are pointers to
* this type. C++ requires typed pointers in allocators so setting this to
* void will fail for some uses of this allocator with STL.
* @tparam MemoryPoolType Object that must support our static memory pool accessor concept. This
* concept requires the following:
* 1. A static getReference() method that returns a reference to a memory
* allocator that shall remain value for at least the life of this instance.
* 2. An allocate(std::size_t size) method to allocate a single block of memory of at
* least size bytes.
* 3. A deallocate(void* p) method to deallocate memory returned from the allocate
* 4. allocate and deallocate shall be thread-safe.
* 5. sizeof(T) shall be >= BlockSizeParam.
template <std::size_t NumBlocksParam,
I assume here that the pool allocator is interrupt-safe. If you are uncomfortable with such assumptions, write your own queue instead, or just re-use this one:
This file has been truncated.
CanRxItem* const buf_;
const uavcan::uint8_t capacity_;
RxQueue(CanRxItem* buf, uavcan::uint8_t capacity)
https://github.com/UAVCAN/libuavcan_stm32/blob/4e0a24756090d218b469f561d7e0d35e5f2f5427/driver/src/uc_stm32_can.cpp#L126-L183; you will need to ensure synchronized access).
I don’t think you need
std::deque<>::size() instead or whatever queue class you’re using. Redundant state is bad.
I strongly recommend following a consistent naming style as described in the
Zubax C++ Conventions.
October 16, 2019, 5:22pm
The block allocator is ISR-safe (it uses an optimistic/lockless implementation to find free blocks) as long as you are
not compiling with
-fno-threadsafe-statics (which we are in our current example so we should change that).
In short, Pavel’s channeling of myself is correct.
October 18, 2019, 5:34pm
Thank you, the PoolAllocator fits as a plug & play custom allocator for the STL deque, the line would be as follows
/* Intermediate RX buffer for ISR reception with static memory pool */
static std::deque<FrameType, platform::PoolAllocator<S32K_FRAME_CAPACITY, sizeof(FrameType)> > frame_ISRbuffer;
This constant it’s a private member of S32K_InterfaceManager
/* Frame capacity for the intermediate ISR buffer */
constexpr static std::size_t S32K_FRAME_CAPACITY = 500;
And substituted the CAN::Frame with the “using” directive from the class template parameter at interfaces.hpp which solves to CAN::Frame< CAN::TypeFD::MaxFrameSizeBytes>
* The media-specific frame type exchanged across this interface.
using FrameType = FrameT;
The changes can be seen in