Using legacy libuavcan and the stm32 baremetal driver, I am making a driver for a rangefinder. I have got everything to work as I like, except for if I start the program before connecting it to another CAN device (in my case a Pixhawk Cube). If I power up my rangefinder and stm32 disconnected it runs for about 1 second (aka my TxTimeout) and then throws the bellow assertion. Decreasing my TxTimeout makes the assertion pop up faster, and starting it plugged into the Pixhawk results in it working whether or not I disconnect it after a second or two, publishing my rangefinder data at ~30Hz.
assertion "used_blocks_ > 0" failed: file "../libuavcan/libuavcan/libuavcan/src/uc_dynamic_memory.cpp", line 29, function: virtual void uavcan::LimitedPoolAllocator::deallocate(const void*)
Any ideas on whats happening or how I could prevent this?
-Ian
As the assertion check suggests, you are dealing with a double-free problem. Try tracing your memory allocations (e.g., by printing via serial port or using GDB trace points) to see what is causing the problem.
Ah, meant to also post the stack trace. It seems to be within the TxQueue but I am still a bit lost.
Thread #1 [main] 1 [core: 0] (Suspended : Breakpoint)
_exit() at syscalls.c:66 0x8012b12
abort() at 0x8035cac
__assert_func() at 0x8035cd0
uavcan::LimitedPoolAllocator::deallocate() at uc_dynamic_memory.cpp:29 0x80220a2
uavcan::AvlTree<uavcan::CanTxQueueEntry>::deleteNode() at avl_tree.hpp:74 0x801c1aa
uavcan::AvlTree<uavcan::CanTxQueueEntry>::deleteFromList() at avl_tree.hpp:186 0x801c21a
uavcan::AvlTree<uavcan::CanTxQueueEntry>::removeNode() at avl_tree.hpp:267 0x801bcca
uavcan::CanTxQueue::searchForNonExpiredMax() at uc_can_io.cpp:175 0x801b03e
uavcan::CanTxQueue::searchForNonExpiredMax() at uc_can_io.cpp:179 0x801b064
uavcan::CanTxQueue::searchForNonExpiredMax() at uc_can_io.cpp:179 0x801b064
uavcan::CanTxQueue::searchForNonExpiredMax() at uc_can_io.cpp:179 0x801b064
....
....
....
uavcan::CanTxQueue::searchForNonExpiredMax() at uc_can_io.cpp:179 0x801b064
uavcan::CanTxQueue::searchForNonExpiredMax() at uc_can_io.cpp:179 0x801b064
uavcan::CanTxQueue::searchForNonExpiredMax() at uc_can_io.cpp:179 0x801b064
uavcan::CanTxQueue::peek() at uc_can_io.cpp:144 0x801af16
uavcan::CanIOManager::receive() at uc_can_io.cpp:425 0x801b898
uavcan::Dispatcher::spin() at uc_dispatcher.cpp:228 0x801cb54
uavcan::Scheduler::spin() at uc_scheduler.cpp:169 0x801923c
uavcan::INode::spin() at abstract_node.hpp:76 0x80110dc
uavcan::Node<16384u>::spin() at node.hpp:133 0x80114c8
main() at main.cpp:46 0x80111cc
Specifically in
uavcan::AvlTree<uavcan::CanTxQueueEntry>::Node* CanTxQueue::searchForNonExpiredMax(Node* n) {
if (n == UAVCAN_NULLPTR) {
return UAVCAN_NULLPTR;
}
const MonotonicTime timestamp = sysclock_.getMonotonic();
while(n->data->isExpired(timestamp)) {
remove(n->data);
return searchForNonExpiredMax(root_);
}
while(n->right != UAVCAN_NULLPTR && n->right->data->isExpired(timestamp)) {
CanTxQueueEntry* expiredEntry = n->data;
n->right = this->AvlTree::removeNode(n, n->data); //assert is caused here.........
CanTxQueueEntry::destroy(expiredEntry, allocator_);
}
Node* r = searchForNonExpiredMax(n->right); //recusion making up most of the stack
if (r != UAVCAN_NULLPTR) {
return r;
}
return n;
}
You might have run into a banal stack overflow.