|
|
|
@ -68,6 +68,85 @@ uORB::FastRpcChannel::FastRpcChannel()
@@ -68,6 +68,85 @@ uORB::FastRpcChannel::FastRpcChannel()
|
|
|
|
|
_RemoteSubscribers.clear(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
//==============================================================================
|
|
|
|
|
int16_t uORB::FastRpcChannel::topic_advertised(const char *messageName) |
|
|
|
|
{ |
|
|
|
|
int16_t rc = 0; |
|
|
|
|
hrt_abstime t1, t2; |
|
|
|
|
static hrt_abstime check_time = 0; |
|
|
|
|
|
|
|
|
|
PX4_DEBUG("=========publish topic[%s] to remote...", messageName); |
|
|
|
|
|
|
|
|
|
t1 = hrt_absolute_time(); |
|
|
|
|
_QueueMutex.lock(); |
|
|
|
|
bool overwriteData = false; |
|
|
|
|
|
|
|
|
|
if (IsControlQFull()) { |
|
|
|
|
// queue is full. Overwrite the oldest data.
|
|
|
|
|
//PX4_WARN("[topic_advertised] Queue Full Overwrite the oldest data. in[%ld] out[%ld] max[%ld]",
|
|
|
|
|
// _ControlQInIndex, _ControlQOutIndex, _MAX_MSG_QUEUE_SIZE);
|
|
|
|
|
_ControlQOutIndex++; |
|
|
|
|
|
|
|
|
|
if (_ControlQOutIndex == _MAX_MSG_QUEUE_SIZE) { |
|
|
|
|
_ControlQOutIndex = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
overwriteData = true; |
|
|
|
|
_dropped_pkts++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_ControlMsgQueue[ _ControlQInIndex ]._Type = _CONTROL_MSG_TYPE_ADVERTISE; |
|
|
|
|
_ControlMsgQueue[ _ControlQInIndex ]._MsgName = messageName; |
|
|
|
|
|
|
|
|
|
_ControlQInIndex++; |
|
|
|
|
|
|
|
|
|
if (_ControlQInIndex == _MAX_MSG_QUEUE_SIZE) { |
|
|
|
|
_ControlQInIndex = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// the assumption here is that each caller reads only one data from either control or data queue.
|
|
|
|
|
//if (!overwriteData) {
|
|
|
|
|
if (ControlQSize() == 1 && DataQSize() == 0) { // post it only of the queue moves from empty to available.
|
|
|
|
|
_DataAvailableSemaphore.post(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((unsigned long)ControlQSize() < _min_q) { _min_q = (unsigned long)ControlQSize(); } |
|
|
|
|
|
|
|
|
|
if ((unsigned long)ControlQSize() > _max_q) { _max_q = (unsigned long)ControlQSize(); } |
|
|
|
|
|
|
|
|
|
_count++; |
|
|
|
|
_avg_q = ((double)((_avg_q * (_count - 1)) + (unsigned long)(ControlQSize()))) / (double)(_count); |
|
|
|
|
|
|
|
|
|
_QueueMutex.unlock(); |
|
|
|
|
t2 = hrt_absolute_time(); |
|
|
|
|
|
|
|
|
|
if ((unsigned long)(t2 - check_time) > 10000000) { |
|
|
|
|
//PX4_DEBUG("MsgName: %20s, t1: %lu, t2: %lu, dt: %lu",messageName, (unsigned long) t1, (unsigned long) t2, (unsigned long) (t2-t1));
|
|
|
|
|
//PX4_DEBUG("Q. Stats: min: %lu, max : %lu, avg: %lu count: %lu ", _min_q, _max_q, (unsigned long)(_avg_q * 1000.0), _count);
|
|
|
|
|
_min_q = _MAX_MSG_QUEUE_SIZE * 2; |
|
|
|
|
_max_q = 0; |
|
|
|
|
_avg_q = 0; |
|
|
|
|
_count = 0; |
|
|
|
|
check_time = t2; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return rc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
//==============================================================================
|
|
|
|
|
/*
|
|
|
|
|
//TODO: verify if needed
|
|
|
|
|
int16_t uORB::FastRpcChannel::topic_unadvertised(const char *messageName) |
|
|
|
|
{ |
|
|
|
|
int16_t rc = 0; |
|
|
|
|
|
|
|
|
|
PX4_DEBUG("=========unpublish topic[%s] to remote...", messageName); |
|
|
|
|
return rc; |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
//==============================================================================
|
|
|
|
|
int16_t uORB::FastRpcChannel::add_subscription(const char *messageName, int32_t msgRateInHz) |
|
|
|
@ -176,7 +255,7 @@ int16_t uORB::FastRpcChannel::send_message(const char *messageName, int32_t leng
@@ -176,7 +255,7 @@ int16_t uORB::FastRpcChannel::send_message(const char *messageName, int32_t leng
|
|
|
|
|
|
|
|
|
|
// the assumption here is that each caller reads only one data from either control or data queue.
|
|
|
|
|
//if (!overwriteData) {
|
|
|
|
|
if (DataQSize() == 1) { // post it only of the queue moves from empty to available.
|
|
|
|
|
if (DataQSize() == 1 && ControlQSize() == 0) { // post it only of the queue moves from empty to available.
|
|
|
|
|
_DataAvailableSemaphore.post(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -403,54 +482,103 @@ int16_t uORB::FastRpcChannel::get_bulk_data
@@ -403,54 +482,103 @@ int16_t uORB::FastRpcChannel::get_bulk_data
|
|
|
|
|
*topic_count = 0; |
|
|
|
|
int32_t topic_count_to_return = 0; |
|
|
|
|
|
|
|
|
|
if (DataQSize() != 0) { |
|
|
|
|
//PX4_DEBUG( "get_bulk_data: QSize: %d", DataQSize() );
|
|
|
|
|
topic_count_to_return = DataQSize(); |
|
|
|
|
|
|
|
|
|
while (DataQSize() != 0) { |
|
|
|
|
// this is a hack as we are using a counting semaphore. Should be re-implemented with cond_variable and wait.
|
|
|
|
|
//_DataAvailableSemaphore.wait();
|
|
|
|
|
if (get_data_msg_size_at(_DataQOutIndex) < (max_buffer_in_bytes - bytes_copied)) { |
|
|
|
|
// there is enough space in the buffer, copy the data.
|
|
|
|
|
//PX4_DEBUG( "Coping Data to buffer..." );
|
|
|
|
|
copy_result = copy_data_to_buffer(_DataQOutIndex, buffer, bytes_copied, max_buffer_in_bytes); |
|
|
|
|
if (DataQSize() != 0 || ControlQSize() != 0) { |
|
|
|
|
if (DataQSize() != 0) { |
|
|
|
|
//PX4_DEBUG( "get_bulk_data: QSize: %d", DataQSize() );
|
|
|
|
|
topic_count_to_return = DataQSize(); |
|
|
|
|
|
|
|
|
|
while (DataQSize() != 0) { |
|
|
|
|
// this is a hack as we are using a counting semaphore. Should be re-implemented with cond_variable and wait.
|
|
|
|
|
//_DataAvailableSemaphore.wait();
|
|
|
|
|
if (get_msg_size_at(true, _DataQOutIndex) < (max_buffer_in_bytes - bytes_copied)) { |
|
|
|
|
// there is enough space in the buffer, copy the data.
|
|
|
|
|
//PX4_DEBUG( "Coping Data to buffer..." );
|
|
|
|
|
copy_result = copy_msg_to_buffer(true, _DataQOutIndex, buffer, bytes_copied, max_buffer_in_bytes); |
|
|
|
|
|
|
|
|
|
if (copy_result == -1) { |
|
|
|
|
if (bytes_copied == 0) { |
|
|
|
|
rc = -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
//PX4_DEBUG( "[%d] %02x %02x %02x %02x", *topic_count,\
|
|
|
|
|
// buffer[bytes_copied], \
|
|
|
|
|
// buffer[bytes_copied+1], \
|
|
|
|
|
// buffer[bytes_copied+2], \
|
|
|
|
|
// buffer[bytes_copied+3] );
|
|
|
|
|
bytes_copied += copy_result; |
|
|
|
|
(*topic_count)++; |
|
|
|
|
*returned_bytes = bytes_copied; |
|
|
|
|
_DataQOutIndex++; |
|
|
|
|
|
|
|
|
|
if (_DataQOutIndex == _MAX_MSG_QUEUE_SIZE) { |
|
|
|
|
_DataQOutIndex = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (copy_result == -1) { |
|
|
|
|
} else { |
|
|
|
|
if (bytes_copied == 0) { |
|
|
|
|
rc = -1; |
|
|
|
|
PX4_WARN("ERROR: Insufficent space in data buffer, no topics returned"); |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
PX4_DEBUG("Exiting out of the while loop..."); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (ControlQSize() != 0) { |
|
|
|
|
//PX4_DEBUG( "get_bulk_data: QSize: %d", ControlQSize() );
|
|
|
|
|
topic_count_to_return += ControlQSize(); |
|
|
|
|
|
|
|
|
|
while (ControlQSize() != 0) { |
|
|
|
|
// this is a hack as we are using a counting semaphore. Should be re-implemented with cond_variable and wait.
|
|
|
|
|
//_DataAvailableSemaphore.wait();
|
|
|
|
|
if (get_msg_size_at(false, _ControlQOutIndex) < (max_buffer_in_bytes - bytes_copied)) { |
|
|
|
|
// there is enough space in the buffer, copy the data.
|
|
|
|
|
//PX4_DEBUG( "Coping Control msg to buffer..." );
|
|
|
|
|
copy_result = copy_msg_to_buffer(false, _ControlQOutIndex, buffer, bytes_copied, max_buffer_in_bytes); |
|
|
|
|
|
|
|
|
|
if (copy_result == -1) { |
|
|
|
|
if (bytes_copied == 0) { |
|
|
|
|
rc = -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
//PX4_DEBUG( "[%d] %02x %02x %02x %02x", *topic_count,\
|
|
|
|
|
// buffer[bytes_copied], \
|
|
|
|
|
// buffer[bytes_copied+1], \
|
|
|
|
|
// buffer[bytes_copied+2], \
|
|
|
|
|
// buffer[bytes_copied+3] );
|
|
|
|
|
bytes_copied += copy_result; |
|
|
|
|
(*topic_count)++; |
|
|
|
|
*returned_bytes = bytes_copied; |
|
|
|
|
_ControlQOutIndex++; |
|
|
|
|
|
|
|
|
|
if (_ControlQOutIndex == _MAX_MSG_QUEUE_SIZE) { |
|
|
|
|
_ControlQOutIndex = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
//PX4_DEBUG( "[%d] %02x %02x %02x %02x", *topic_count,\
|
|
|
|
|
// buffer[bytes_copied], \
|
|
|
|
|
// buffer[bytes_copied+1], \
|
|
|
|
|
// buffer[bytes_copied+2], \
|
|
|
|
|
// buffer[bytes_copied+3] );
|
|
|
|
|
bytes_copied += copy_result; |
|
|
|
|
(*topic_count)++; |
|
|
|
|
*returned_bytes = bytes_copied; |
|
|
|
|
_DataQOutIndex++; |
|
|
|
|
|
|
|
|
|
if (_DataQOutIndex == _MAX_MSG_QUEUE_SIZE) { |
|
|
|
|
_DataQOutIndex = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (bytes_copied == 0) { |
|
|
|
|
rc = -1; |
|
|
|
|
PX4_WARN("ERROR: Insufficent space in data buffer, no topics returned"); |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
if (bytes_copied == 0) { |
|
|
|
|
rc = -1; |
|
|
|
|
PX4_WARN("ERROR: Insufficent space in data buffer, no topics returned"); |
|
|
|
|
} else { |
|
|
|
|
PX4_DEBUG("Exiting out of the while loop..."); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
PX4_DEBUG("Exiting out of the while loop..."); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
PX4_ERR("[get_data_bulk] Error: Semaphore is up when there is no data on the control/data queues"); |
|
|
|
|
rc = -1; |
|
|
|
@ -488,20 +616,22 @@ int16_t uORB::FastRpcChannel::get_bulk_data
@@ -488,20 +616,22 @@ int16_t uORB::FastRpcChannel::get_bulk_data
|
|
|
|
|
return rc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int32_t uORB::FastRpcChannel::get_data_msg_size_at(int32_t index) |
|
|
|
|
int32_t uORB::FastRpcChannel::get_msg_size_at(bool isData, int32_t index) |
|
|
|
|
{ |
|
|
|
|
// the assumption here is that this is called within the context of semaphore,
|
|
|
|
|
// hence lock/unlock is not needed.
|
|
|
|
|
int32_t rc = 0; |
|
|
|
|
rc += _DataMsgQueue[ index ]._Length; |
|
|
|
|
rc += _DataMsgQueue[ index ]._MsgName.size() + 1; |
|
|
|
|
if (isData) { |
|
|
|
|
rc += _DataMsgQueue[ index ]._Length; |
|
|
|
|
rc += _DataMsgQueue[ index ]._MsgName.size() + 1; |
|
|
|
|
} else { |
|
|
|
|
rc += _ControlMsgQueue[ index ]._MsgName.size() + 1; |
|
|
|
|
} |
|
|
|
|
rc += _PACKET_HEADER_SIZE; |
|
|
|
|
return rc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int32_t uORB::FastRpcChannel::copy_data_to_buffer(int32_t src_index, uint8_t *dst_buffer, int32_t offset, |
|
|
|
|
int32_t uORB::FastRpcChannel::copy_msg_to_buffer(bool isData, int32_t src_index, uint8_t *dst_buffer, int32_t offset, |
|
|
|
|
int32_t dst_buffer_len) |
|
|
|
|
{ |
|
|
|
|
int32_t rc = -1; |
|
|
|
@ -510,12 +640,19 @@ int32_t uORB::FastRpcChannel::copy_data_to_buffer(int32_t src_index, uint8_t *ds
@@ -510,12 +640,19 @@ int32_t uORB::FastRpcChannel::copy_data_to_buffer(int32_t src_index, uint8_t *ds
|
|
|
|
|
// * sem_lock is acquired for data protection
|
|
|
|
|
// * the dst_buffer is validated to
|
|
|
|
|
|
|
|
|
|
uint16_t msg_size = (isData ? |
|
|
|
|
(uint16_t)(_DataMsgQueue[ src_index ]._MsgName.size()) : |
|
|
|
|
(uint16_t)(_ControlMsgQueue[ src_index ]._MsgName.size())); |
|
|
|
|
|
|
|
|
|
// compute the different offsets to pack the packets.
|
|
|
|
|
int32_t field_header_offset = offset; |
|
|
|
|
int32_t field_topic_name_offset = field_header_offset + sizeof(struct BulkTransferHeader); |
|
|
|
|
int32_t field_data_offset = field_topic_name_offset + _DataMsgQueue[ src_index ]._MsgName.size() + 1; |
|
|
|
|
int32_t field_data_offset = field_topic_name_offset + msg_size + 1; |
|
|
|
|
|
|
|
|
|
struct BulkTransferHeader header = { (uint16_t)(_DataMsgQueue[ src_index ]._MsgName.size() + 1), (uint16_t)(_DataMsgQueue[ src_index ]._Length) }; |
|
|
|
|
int16_t msg_type = isData ? _DATA_MSG_TYPE : _ControlMsgQueue[ src_index ]._Type; |
|
|
|
|
|
|
|
|
|
struct BulkTransferHeader header = { (uint16_t)msg_type,( uint16_t)(msg_size + 1), |
|
|
|
|
(uint16_t)(isData ? (_DataMsgQueue[ src_index ]._Length) : 0) }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//PX4_DEBUG( "Offsets: header[%d] name[%d] data[%d]",
|
|
|
|
@ -523,7 +660,7 @@ int32_t uORB::FastRpcChannel::copy_data_to_buffer(int32_t src_index, uint8_t *ds
@@ -523,7 +660,7 @@ int32_t uORB::FastRpcChannel::copy_data_to_buffer(int32_t src_index, uint8_t *ds
|
|
|
|
|
// field_topic_name_offset,
|
|
|
|
|
// field_data_offset );
|
|
|
|
|
|
|
|
|
|
if ((field_data_offset + _DataMsgQueue[ src_index ]._Length) < dst_buffer_len) { |
|
|
|
|
if (isData && (field_data_offset + _DataMsgQueue[ src_index ]._Length) < dst_buffer_len) { |
|
|
|
|
memmove(&(dst_buffer[field_header_offset]), (char *)(&header), sizeof(header)); |
|
|
|
|
// pack the data here.
|
|
|
|
|
memmove |
|
|
|
@ -541,10 +678,32 @@ int32_t uORB::FastRpcChannel::copy_data_to_buffer(int32_t src_index, uint8_t *ds
@@ -541,10 +678,32 @@ int32_t uORB::FastRpcChannel::copy_data_to_buffer(int32_t src_index, uint8_t *ds
|
|
|
|
|
memmove(&(dst_buffer[field_data_offset]), _DataMsgQueue[ src_index ]._Buffer, _DataMsgQueue[ src_index ]._Length); |
|
|
|
|
rc = field_data_offset + _DataMsgQueue[ src_index ]._Length - offset; |
|
|
|
|
|
|
|
|
|
} else if (field_data_offset < dst_buffer_len) { //This is a control message
|
|
|
|
|
memmove(&(dst_buffer[field_header_offset]), (char *)(&header), sizeof(header)); |
|
|
|
|
// pack the data here.
|
|
|
|
|
memmove |
|
|
|
|
( |
|
|
|
|
&(dst_buffer[field_topic_name_offset]), |
|
|
|
|
_ControlMsgQueue[ src_index ]._MsgName.c_str(), |
|
|
|
|
_ControlMsgQueue[ src_index ]._MsgName.size() |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
if (_ControlMsgQueue[ src_index ]._MsgName.size() == 0) { |
|
|
|
|
PX4_WARN("########## Error MsgName cannot be zero: "); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dst_buffer[ field_topic_name_offset + _ControlMsgQueue[ src_index ]._MsgName.size()] = '\0'; |
|
|
|
|
rc = field_data_offset - offset; |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
PX4_WARN("Error coping the DataMsg to dst buffer, insuffienct space. "); |
|
|
|
|
PX4_WARN("... offset[%ld] len[%ld] data_msg_len[%ld]", |
|
|
|
|
PX4_WARN("Error coping the Msg to dst buffer, insuffienct space. "); |
|
|
|
|
if (isData) { |
|
|
|
|
PX4_WARN("Data... offset[%ld] len[%ld] data_msg_len[%ld]", |
|
|
|
|
offset, dst_buffer_len, (field_data_offset - offset) + _DataMsgQueue[ src_index ]._Length); |
|
|
|
|
} else { |
|
|
|
|
PX4_WARN("ControlMsg... offset[%ld] len[%ld]", |
|
|
|
|
offset, dst_buffer_len, (field_data_offset - offset)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return rc; |
|
|
|
|