mirror of
https://github.com/nasa/fprime.git
synced 2025-12-10 16:29:04 -06:00
Add packetized telemetry option (#1776)
* manual packet gen * Added tlmPkt to deployment * Packet files * Fixes to packet gen script * format python, updated packet files * spelling fixes * integrating packet autocoder * final updates for telemetry packetization * formatting telemetry packetizer cpde * moving tlm packetizer configuration file * resetting stock telemetry channelizer * missed packetizer setup call * fixing autocoding miss-match with Svc::TlmChan Co-authored-by: M Starch <LeStarch@googlemail.com>
This commit is contained in:
parent
9409139668
commit
b7a25920a3
2
.gitignore
vendored
2
.gitignore
vendored
@ -82,3 +82,5 @@ depend
|
|||||||
|
|
||||||
/.idea/
|
/.idea/
|
||||||
/venv/
|
/venv/
|
||||||
|
|
||||||
|
Packet-Views
|
||||||
|
|||||||
@ -114,6 +114,8 @@ namespace ${packet_list_namespace} {
|
|||||||
PRINT = logging.getLogger("output")
|
PRINT = logging.getLogger("output")
|
||||||
DEBUG = logging.getLogger("debug")
|
DEBUG = logging.getLogger("debug")
|
||||||
|
|
||||||
|
PACKET_VIEW_DIR = "./Packet-Views"
|
||||||
|
|
||||||
|
|
||||||
class TlmPacketParseValueError(ValueError):
|
class TlmPacketParseValueError(ValueError):
|
||||||
pass
|
pass
|
||||||
@ -136,8 +138,8 @@ class TlmPacketParser(object):
|
|||||||
def get_type_size(self, type_name, size):
|
def get_type_size(self, type_name, size):
|
||||||
|
|
||||||
# switch based on type
|
# switch based on type
|
||||||
if type == "string":
|
if type_name == "string":
|
||||||
return size
|
return int(size) + 2 # plus 2 to store the string length
|
||||||
elif type_name == "I8":
|
elif type_name == "I8":
|
||||||
return 1
|
return 1
|
||||||
elif type_name == "I16":
|
elif type_name == "I16":
|
||||||
@ -163,28 +165,6 @@ class TlmPacketParser(object):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# def search_for_file(self,file_type, file_path):
|
|
||||||
# '''
|
|
||||||
# Searches for a given included port or serializable by looking in three places:
|
|
||||||
# - The specified BUILD_ROOT
|
|
||||||
# - The F Prime core
|
|
||||||
# - The exact specified path
|
|
||||||
# @param file_type: type of file searched for
|
|
||||||
# @param file_path: path to look for based on offset
|
|
||||||
# @return: full path of file
|
|
||||||
# '''
|
|
||||||
# core = os.environ.get("FPRIME_CORE_DIR", BUILD_ROOT)
|
|
||||||
# for possible in [BUILD_ROOT, core, None]:
|
|
||||||
# if not possible is None:
|
|
||||||
# checker = os.path.join(possible, file_path)
|
|
||||||
# else:
|
|
||||||
# checker = file_path
|
|
||||||
# if os.path.exists(checker):
|
|
||||||
# DEBUG.debug("%s xml type description file: %s" % (file_type,file_path))
|
|
||||||
# return checker
|
|
||||||
# else:
|
|
||||||
# return None
|
|
||||||
|
|
||||||
def generate_channel_size_dict(self, the_parsed_topology_xml, xml_filename):
|
def generate_channel_size_dict(self, the_parsed_topology_xml, xml_filename):
|
||||||
"""
|
"""
|
||||||
Generates GDS XML dictionary from parsed topology XML
|
Generates GDS XML dictionary from parsed topology XML
|
||||||
@ -224,7 +204,7 @@ class TlmPacketParser(object):
|
|||||||
|
|
||||||
for comp in the_parsed_topology_xml.get_instances():
|
for comp in the_parsed_topology_xml.get_instances():
|
||||||
comp_name = comp.get_name()
|
comp_name = comp.get_name()
|
||||||
comp_id = int(comp.get_base_id())
|
comp_id = int(comp.get_base_id(), 0)
|
||||||
comp_type = comp.get_type()
|
comp_type = comp.get_type()
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
PRINT.debug("Processing %s" % comp_name)
|
PRINT.debug("Processing %s" % comp_name)
|
||||||
@ -246,6 +226,9 @@ class TlmPacketParser(object):
|
|||||||
# if channel is enum
|
# if channel is enum
|
||||||
if type(chan_type) == type(tuple()):
|
if type(chan_type) == type(tuple()):
|
||||||
chan_size = 4
|
chan_size = 4
|
||||||
|
# if channel type is string
|
||||||
|
# elif chan_type == "string":
|
||||||
|
# chan_size = int(chan.get_size()) + 2 # FIXME: buffer size storage size magic number - needs to be turned into a constant
|
||||||
# if channel is serializable
|
# if channel is serializable
|
||||||
elif chan_type in self.size_dict:
|
elif chan_type in self.size_dict:
|
||||||
chan_size = self.size_dict[chan_type]
|
chan_size = self.size_dict[chan_type]
|
||||||
@ -266,7 +249,7 @@ class TlmPacketParser(object):
|
|||||||
|
|
||||||
def gen_packet_file(self, xml_filename):
|
def gen_packet_file(self, xml_filename):
|
||||||
|
|
||||||
view_path = "./Views"
|
view_path = PACKET_VIEW_DIR
|
||||||
|
|
||||||
if not os.path.exists(view_path):
|
if not os.path.exists(view_path):
|
||||||
os.mkdir(view_path)
|
os.mkdir(view_path)
|
||||||
@ -275,11 +258,6 @@ class TlmPacketParser(object):
|
|||||||
if not os.path.isfile(xml_filename):
|
if not os.path.isfile(xml_filename):
|
||||||
raise TlmPacketParseIOError("File %s does not exist!" % xml_filename)
|
raise TlmPacketParseIOError("File %s does not exist!" % xml_filename)
|
||||||
|
|
||||||
if not "PacketsAi" in xml_filename:
|
|
||||||
raise IOError(
|
|
||||||
"ERROR: Missing PacketsAi at end of file name %s" % xml_filename
|
|
||||||
)
|
|
||||||
|
|
||||||
fd = open(xml_filename, "r")
|
fd = open(xml_filename, "r")
|
||||||
xml_parser = etree.XMLParser(remove_comments=True)
|
xml_parser = etree.XMLParser(remove_comments=True)
|
||||||
element_tree = etree.parse(fd, parser=xml_parser)
|
element_tree = etree.parse(fd, parser=xml_parser)
|
||||||
@ -315,12 +293,12 @@ class TlmPacketParser(object):
|
|||||||
ht.num_packets = 0
|
ht.num_packets = 0
|
||||||
total_packet_size = 0
|
total_packet_size = 0
|
||||||
levels = []
|
levels = []
|
||||||
view_path = "./Views"
|
view_path = PACKET_VIEW_DIR
|
||||||
# find the topology import
|
# find the topology import
|
||||||
for entry in element_tree.getroot():
|
for entry in element_tree.getroot():
|
||||||
# read in topology file
|
# read in topology file
|
||||||
if entry.tag == "import_topology":
|
if entry.tag == "import_topology":
|
||||||
top_file = search_for_file("Packet", entry.text)
|
top_file = search_for_file("Topology", entry.text)
|
||||||
if top_file is None:
|
if top_file is None:
|
||||||
raise TlmPacketParseIOError(
|
raise TlmPacketParseIOError(
|
||||||
"import file %s not found" % entry.text
|
"import file %s not found" % entry.text
|
||||||
@ -424,12 +402,9 @@ class TlmPacketParser(object):
|
|||||||
"Invalid xml type %s" % element_tree.getroot().tag
|
"Invalid xml type %s" % element_tree.getroot().tag
|
||||||
)
|
)
|
||||||
|
|
||||||
output_file_base = os.path.splitext(os.path.basename(xml_filename))[0].replace(
|
output_file_base = os.path.splitext(os.path.basename(xml_filename))[0]
|
||||||
"Ai", ""
|
nearest_build_root = get_nearest_build_root(xml_filename)
|
||||||
)
|
file_dir = os.path.relpath(os.path.dirname(xml_filename), nearest_build_root)
|
||||||
file_dir = os.path.dirname(xml_filename).replace(
|
|
||||||
get_nearest_build_root(xml_filename) + os.sep, ""
|
|
||||||
)
|
|
||||||
|
|
||||||
missing_channels = False
|
missing_channels = False
|
||||||
|
|
||||||
@ -499,6 +474,7 @@ class TlmPacketParser(object):
|
|||||||
for (
|
for (
|
||||||
member_name,
|
member_name,
|
||||||
member_type,
|
member_type,
|
||||||
|
member_array_size,
|
||||||
member_size,
|
member_size,
|
||||||
member_format_specifier,
|
member_format_specifier,
|
||||||
member_comment,
|
member_comment,
|
||||||
@ -520,6 +496,8 @@ class TlmPacketParser(object):
|
|||||||
)
|
)
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
serializable_size += type_size
|
serializable_size += type_size
|
||||||
|
if member_array_size != None:
|
||||||
|
serializable_size *= member_array_size
|
||||||
self.add_type_size(serializable_type, serializable_size)
|
self.add_type_size(serializable_type, serializable_size)
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
print(
|
print(
|
||||||
@ -616,7 +594,7 @@ def main():
|
|||||||
print(f"Usage: {sys.argv[0]} [options] xml_filename")
|
print(f"Usage: {sys.argv[0]} [options] xml_filename")
|
||||||
return
|
return
|
||||||
elif len(args) == 1:
|
elif len(args) == 1:
|
||||||
xml_filename = args[0]
|
xml_filename = os.path.abspath(args[0])
|
||||||
else:
|
else:
|
||||||
print("ERROR: Too many filenames, should only have one")
|
print("ERROR: Too many filenames, should only have one")
|
||||||
return
|
return
|
||||||
|
|||||||
14
Autocoders/Python/bin/tlm_packet_gen.sh
Executable file
14
Autocoders/Python/bin/tlm_packet_gen.sh
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
script_dir=$(dirname $0)
|
||||||
|
|
||||||
|
# $0 = this script
|
||||||
|
# $1 = packet file
|
||||||
|
# $2 = deployment build cache (ex. Ref/build-fprime-automatic-native)
|
||||||
|
|
||||||
|
export PYTHONPATH=$script_dir/../src
|
||||||
|
export BUILD_ROOT=$script_dir/../../../:$2:$2/F-Prime
|
||||||
|
echo "BUILD_ROOT=$BUILD_ROOT"
|
||||||
|
|
||||||
|
# get python from the path
|
||||||
|
python3 $script_dir/tlm_packet_gen.py $1
|
||||||
@ -320,6 +320,6 @@ class XmlSerializeParser:
|
|||||||
|
|
||||||
def get_members(self):
|
def get_members(self):
|
||||||
"""
|
"""
|
||||||
Returns a list of member (name, type, optional size, optional format, optional comment) needed.
|
Returns a list of member (name, type, optional array size, optional size, optional format, optional comment) needed.
|
||||||
"""
|
"""
|
||||||
return self.__members
|
return self.__members
|
||||||
|
|||||||
@ -41,6 +41,7 @@ def get_nearest_build_root(path):
|
|||||||
:param path: path to find nearest build root to
|
:param path: path to find nearest build root to
|
||||||
:return: nearest build root
|
:return: nearest build root
|
||||||
"""
|
"""
|
||||||
|
path = os.path.abspath(path)
|
||||||
parents = filter(
|
parents = filter(
|
||||||
lambda build: os.path.commonpath([build, path]) == build, get_build_roots()
|
lambda build: os.path.commonpath([build, path]) == build, get_build_roots()
|
||||||
)
|
)
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/instances.fpp"
|
"${CMAKE_CURRENT_LIST_DIR}/instances.fpp"
|
||||||
|
"${CMAKE_CURRENT_LIST_DIR}/RefPackets.xml"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/topology.fpp"
|
"${CMAKE_CURRENT_LIST_DIR}/topology.fpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/RefTopology.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/RefTopology.cpp"
|
||||||
)
|
)
|
||||||
@ -18,4 +19,4 @@ set(MOD_DEPS
|
|||||||
Drv/TcpClient
|
Drv/TcpClient
|
||||||
)
|
)
|
||||||
|
|
||||||
register_fprime_module()
|
register_fprime_module()
|
||||||
|
|||||||
@ -18,8 +18,9 @@
|
|||||||
<channel name="fileUplinkBufferManager.HiBuffs"/>
|
<channel name="fileUplinkBufferManager.HiBuffs"/>
|
||||||
<channel name="fileDownlink.FilesSent"/>
|
<channel name="fileDownlink.FilesSent"/>
|
||||||
<channel name="fileDownlink.PacketsSent"/>
|
<channel name="fileDownlink.PacketsSent"/>
|
||||||
<channel name="pktTlm.TPK_SendLevel"/>
|
|
||||||
<channel name="fileManager.CommandsExecuted"/>
|
<channel name="fileManager.CommandsExecuted"/>
|
||||||
|
<!-- Uncomment to use Svc::TlmPacketizer -->
|
||||||
|
<!--channel name="tlmSend.SendLevel"/-->
|
||||||
</packet>
|
</packet>
|
||||||
|
|
||||||
<packet name="CDHErrors" id="2" level="1">
|
<packet name="CDHErrors" id="2" level="1">
|
||||||
@ -64,51 +65,83 @@
|
|||||||
<channel name="SG5.Type"/>
|
<channel name="SG5.Type"/>
|
||||||
</packet>
|
</packet>
|
||||||
|
|
||||||
<packet name="SigGen1Info" id="5" level="2">
|
<packet name="SystemRes1" id="5" level="2">
|
||||||
|
<channel name="systemResources.MEMORY_TOTAL"/>
|
||||||
|
<channel name="systemResources.MEMORY_USED"/>
|
||||||
|
<channel name="systemResources.NON_VOLATILE_TOTAL"/>
|
||||||
|
<channel name="systemResources.NON_VOLATILE_FREE"/>
|
||||||
|
</packet>
|
||||||
|
|
||||||
|
<packet name="SystemRes2" id="6" level="2">
|
||||||
|
<channel name="systemResources.FRAMEWORK_VERSION"/>
|
||||||
|
<channel name="systemResources.PROJECT_VERSION"/>
|
||||||
|
</packet>
|
||||||
|
|
||||||
|
<packet name="SystemRes3" id="7" level="2">
|
||||||
|
<channel name="systemResources.CPU"/>
|
||||||
|
<channel name="systemResources.CPU_00"/>
|
||||||
|
<channel name="systemResources.CPU_01"/>
|
||||||
|
<channel name="systemResources.CPU_02"/>
|
||||||
|
<channel name="systemResources.CPU_03"/>
|
||||||
|
<channel name="systemResources.CPU_04"/>
|
||||||
|
<channel name="systemResources.CPU_05"/>
|
||||||
|
<channel name="systemResources.CPU_06"/>
|
||||||
|
<channel name="systemResources.CPU_07"/>
|
||||||
|
<channel name="systemResources.CPU_08"/>
|
||||||
|
<channel name="systemResources.CPU_09"/>
|
||||||
|
<channel name="systemResources.CPU_10"/>
|
||||||
|
<channel name="systemResources.CPU_11"/>
|
||||||
|
<channel name="systemResources.CPU_12"/>
|
||||||
|
<channel name="systemResources.CPU_13"/>
|
||||||
|
<channel name="systemResources.CPU_14"/>
|
||||||
|
<channel name="systemResources.CPU_15"/>
|
||||||
|
</packet>
|
||||||
|
|
||||||
|
<packet name="SigGen1Info" id="10" level="2">
|
||||||
<channel name="SG1.Info"/>
|
<channel name="SG1.Info"/>
|
||||||
</packet>
|
</packet>
|
||||||
|
|
||||||
<packet name="SigGen2Info" id="6" level="2">
|
<packet name="SigGen2Info" id="11" level="2">
|
||||||
<channel name="SG2.Info"/>
|
<channel name="SG2.Info"/>
|
||||||
</packet>
|
</packet>
|
||||||
|
|
||||||
<packet name="SigGen3Info" id="7" level="2">
|
<packet name="SigGen3Info" id="12" level="2">
|
||||||
<channel name="SG3.Info"/>
|
<channel name="SG3.Info"/>
|
||||||
</packet>
|
</packet>
|
||||||
|
|
||||||
<packet name="SigGen4Info" id="8" level="2">
|
<packet name="SigGen4Info" id="13" level="2">
|
||||||
<channel name="SG4.Info"/>
|
<channel name="SG4.Info"/>
|
||||||
</packet>
|
</packet>
|
||||||
|
|
||||||
<packet name="SigGen5Info" id="9" level="2">
|
<packet name="SigGen5Info" id="14" level="2">
|
||||||
<channel name="SG5.Info"/>
|
<channel name="SG5.Info"/>
|
||||||
</packet>
|
</packet>
|
||||||
|
|
||||||
<packet name="SigGen1" id="10" level="3">
|
<packet name="SigGen1" id="15" level="3">
|
||||||
<channel name="SG1.PairOutput"/>
|
<channel name="SG1.PairOutput"/>
|
||||||
<channel name="SG1.History"/>
|
<channel name="SG1.History"/>
|
||||||
<channel name="SG1.PairHistory"/>
|
<channel name="SG1.PairHistory"/>
|
||||||
</packet>
|
</packet>
|
||||||
|
|
||||||
<packet name="SigGen2" id="11" level="3">
|
<packet name="SigGen2" id="16" level="3">
|
||||||
<channel name="SG2.PairOutput"/>
|
<channel name="SG2.PairOutput"/>
|
||||||
<channel name="SG2.History"/>
|
<channel name="SG2.History"/>
|
||||||
<channel name="SG2.PairHistory"/>
|
<channel name="SG2.PairHistory"/>
|
||||||
</packet>
|
</packet>
|
||||||
|
|
||||||
<packet name="SigGen3" id="12" level="3">
|
<packet name="SigGen3" id="17" level="3">
|
||||||
<channel name="SG3.PairOutput"/>
|
<channel name="SG3.PairOutput"/>
|
||||||
<channel name="SG3.History"/>
|
<channel name="SG3.History"/>
|
||||||
<channel name="SG3.PairHistory"/>
|
<channel name="SG3.PairHistory"/>
|
||||||
</packet>
|
</packet>
|
||||||
|
|
||||||
<packet name="SigGen4" id="13" level="3">
|
<packet name="SigGen4" id="18" level="3">
|
||||||
<channel name="SG4.PairOutput"/>
|
<channel name="SG4.PairOutput"/>
|
||||||
<channel name="SG4.History"/>
|
<channel name="SG4.History"/>
|
||||||
<channel name="SG4.PairHistory"/>
|
<channel name="SG4.PairHistory"/>
|
||||||
</packet>
|
</packet>
|
||||||
|
|
||||||
<packet name="SigGen5" id="14" level="3">
|
<packet name="SigGen5" id="19" level="3">
|
||||||
<channel name="SG5.PairOutput"/>
|
<channel name="SG5.PairOutput"/>
|
||||||
<channel name="SG5.History"/>
|
<channel name="SG5.History"/>
|
||||||
<channel name="SG5.PairHistory"/>
|
<channel name="SG5.PairHistory"/>
|
||||||
@ -10,6 +10,7 @@
|
|||||||
// ======================================================================
|
// ======================================================================
|
||||||
// Provides access to autocoded functions
|
// Provides access to autocoded functions
|
||||||
#include <Ref/Top/RefTopologyAc.hpp>
|
#include <Ref/Top/RefTopologyAc.hpp>
|
||||||
|
#include <Ref/Top/RefPacketsAc.hpp>
|
||||||
|
|
||||||
// Necessary project-specified types
|
// Necessary project-specified types
|
||||||
#include <Fw/Types/MallocAllocator.hpp>
|
#include <Fw/Types/MallocAllocator.hpp>
|
||||||
@ -60,7 +61,7 @@ enum TopologyConstants {
|
|||||||
// Ping entries are autocoded, however; this code is not properly exported. Thus, it is copied here.
|
// Ping entries are autocoded, however; this code is not properly exported. Thus, it is copied here.
|
||||||
Svc::Health::PingEntry pingEntries[] = {
|
Svc::Health::PingEntry pingEntries[] = {
|
||||||
{PingEntries::blockDrv::WARN, PingEntries::blockDrv::FATAL, "blockDrv"},
|
{PingEntries::blockDrv::WARN, PingEntries::blockDrv::FATAL, "blockDrv"},
|
||||||
{PingEntries::chanTlm::WARN, PingEntries::chanTlm::FATAL, "chanTlm"},
|
{PingEntries::tlmSend::WARN, PingEntries::tlmSend::FATAL, "chanTlm"},
|
||||||
{PingEntries::cmdDisp::WARN, PingEntries::cmdDisp::FATAL, "cmdDisp"},
|
{PingEntries::cmdDisp::WARN, PingEntries::cmdDisp::FATAL, "cmdDisp"},
|
||||||
{PingEntries::cmdSeq::WARN, PingEntries::cmdSeq::FATAL, "cmdSeq"},
|
{PingEntries::cmdSeq::WARN, PingEntries::cmdSeq::FATAL, "cmdSeq"},
|
||||||
{PingEntries::eventLogger::WARN, PingEntries::eventLogger::FATAL, "eventLogger"},
|
{PingEntries::eventLogger::WARN, PingEntries::eventLogger::FATAL, "eventLogger"},
|
||||||
@ -114,6 +115,9 @@ void configureTopology() {
|
|||||||
// Framer and Deframer components need to be passed a protocol handler
|
// Framer and Deframer components need to be passed a protocol handler
|
||||||
downlink.setup(framing);
|
downlink.setup(framing);
|
||||||
uplink.setup(deframing);
|
uplink.setup(deframing);
|
||||||
|
|
||||||
|
// Note: Uncomment when using Svc:TlmPacketizer
|
||||||
|
//tlmSend.setPacketList(RefPacketsPkts, RefPacketsIgnore, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public functions for use in main program are namespaced with deployment name Ref
|
// Public functions for use in main program are namespaced with deployment name Ref
|
||||||
|
|||||||
@ -56,7 +56,7 @@ namespace PingEntries {
|
|||||||
namespace blockDrv {
|
namespace blockDrv {
|
||||||
enum { WARN = 3, FATAL = 5 };
|
enum { WARN = 3, FATAL = 5 };
|
||||||
}
|
}
|
||||||
namespace chanTlm {
|
namespace tlmSend {
|
||||||
enum { WARN = 3, FATAL = 5 };
|
enum { WARN = 3, FATAL = 5 };
|
||||||
}
|
}
|
||||||
namespace cmdDisp {
|
namespace cmdDisp {
|
||||||
|
|||||||
@ -68,11 +68,20 @@ module Ref {
|
|||||||
stack size Default.STACK_SIZE \
|
stack size Default.STACK_SIZE \
|
||||||
priority 98
|
priority 98
|
||||||
|
|
||||||
instance chanTlm: Svc.TlmChan base id 0x0C00 \
|
# comment in Svc.TlmChan or Svc.TlmPacketizer
|
||||||
|
# depending on which form of telemetry downlink
|
||||||
|
# you wish to use
|
||||||
|
|
||||||
|
instance tlmSend: Svc.TlmChan base id 0x0C00 \
|
||||||
queue size Default.QUEUE_SIZE \
|
queue size Default.QUEUE_SIZE \
|
||||||
stack size Default.STACK_SIZE \
|
stack size Default.STACK_SIZE \
|
||||||
priority 97
|
priority 97
|
||||||
|
|
||||||
|
#instance tlmSend: Svc.TlmPacketizer base id 0x0C00 \
|
||||||
|
# queue size Default.QUEUE_SIZE \
|
||||||
|
# stack size Default.STACK_SIZE \
|
||||||
|
# priority 97
|
||||||
|
|
||||||
instance prmDb: Svc.PrmDb base id 0x0D00 \
|
instance prmDb: Svc.PrmDb base id 0x0D00 \
|
||||||
queue size Default.QUEUE_SIZE \
|
queue size Default.QUEUE_SIZE \
|
||||||
stack size Default.STACK_SIZE \
|
stack size Default.STACK_SIZE \
|
||||||
|
|||||||
@ -28,7 +28,7 @@ module Ref {
|
|||||||
instance SG4
|
instance SG4
|
||||||
instance SG5
|
instance SG5
|
||||||
instance blockDrv
|
instance blockDrv
|
||||||
instance chanTlm
|
instance tlmSend
|
||||||
instance cmdDisp
|
instance cmdDisp
|
||||||
instance cmdSeq
|
instance cmdSeq
|
||||||
instance comm
|
instance comm
|
||||||
@ -64,7 +64,7 @@ module Ref {
|
|||||||
|
|
||||||
param connections instance prmDb
|
param connections instance prmDb
|
||||||
|
|
||||||
telemetry connections instance chanTlm
|
telemetry connections instance tlmSend
|
||||||
|
|
||||||
text event connections instance textLogger
|
text event connections instance textLogger
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ module Ref {
|
|||||||
|
|
||||||
connections Downlink {
|
connections Downlink {
|
||||||
|
|
||||||
chanTlm.PktSend -> downlink.comIn
|
tlmSend.PktSend -> downlink.comIn
|
||||||
eventLogger.PktSend -> downlink.comIn
|
eventLogger.PktSend -> downlink.comIn
|
||||||
fileDownlink.bufferSendOut -> downlink.bufferIn
|
fileDownlink.bufferSendOut -> downlink.bufferIn
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ module Ref {
|
|||||||
rateGroupDriverComp.CycleOut[Ports_RateGroups.rateGroup1] -> rateGroup1Comp.CycleIn
|
rateGroupDriverComp.CycleOut[Ports_RateGroups.rateGroup1] -> rateGroup1Comp.CycleIn
|
||||||
rateGroup1Comp.RateGroupMemberOut[0] -> SG1.schedIn
|
rateGroup1Comp.RateGroupMemberOut[0] -> SG1.schedIn
|
||||||
rateGroup1Comp.RateGroupMemberOut[1] -> SG2.schedIn
|
rateGroup1Comp.RateGroupMemberOut[1] -> SG2.schedIn
|
||||||
rateGroup1Comp.RateGroupMemberOut[2] -> chanTlm.Run
|
rateGroup1Comp.RateGroupMemberOut[2] -> tlmSend.Run
|
||||||
rateGroup1Comp.RateGroupMemberOut[3] -> fileDownlink.Run
|
rateGroup1Comp.RateGroupMemberOut[3] -> fileDownlink.Run
|
||||||
rateGroup1Comp.RateGroupMemberOut[4] -> systemResources.run
|
rateGroup1Comp.RateGroupMemberOut[4] -> systemResources.run
|
||||||
|
|
||||||
|
|||||||
@ -8,391 +8,342 @@
|
|||||||
// ALL RIGHTS RESERVED. United States Government Sponsorship
|
// ALL RIGHTS RESERVED. United States Government Sponsorship
|
||||||
// acknowledged.
|
// acknowledged.
|
||||||
|
|
||||||
#include <Svc/TlmPacketizer/TlmPacketizer.hpp>
|
|
||||||
#include <FpConfig.hpp>
|
#include <FpConfig.hpp>
|
||||||
#include <Fw/Com/ComPacket.hpp>
|
#include <Fw/Com/ComPacket.hpp>
|
||||||
|
#include <Svc/TlmPacketizer/TlmPacketizer.hpp>
|
||||||
|
|
||||||
namespace Svc {
|
namespace Svc {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// Construction, initialization, and destruction
|
// Construction, initialization, and destruction
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
TlmPacketizer ::
|
TlmPacketizer ::TlmPacketizer(const char* const compName)
|
||||||
TlmPacketizer(
|
: TlmPacketizerComponentBase(compName), m_numPackets(0), m_configured(false), m_startLevel(0), m_maxLevel(0) {
|
||||||
const char *const compName
|
// clear slot pointers
|
||||||
) :
|
for (NATIVE_UINT_TYPE entry = 0; entry < TLMPACKETIZER_NUM_TLM_HASH_SLOTS; entry++) {
|
||||||
TlmPacketizerComponentBase(compName)
|
this->m_tlmEntries.slots[entry] = nullptr;
|
||||||
,m_numPackets(0)
|
}
|
||||||
,m_configured(false)
|
// clear buckets
|
||||||
,m_startLevel(0)
|
for (NATIVE_UINT_TYPE entry = 0; entry < TLMPACKETIZER_HASH_BUCKETS; entry++) {
|
||||||
,m_maxLevel(0)
|
this->m_tlmEntries.buckets[entry].used = false;
|
||||||
{
|
this->m_tlmEntries.buckets[entry].bucketNo = entry;
|
||||||
// clear slot pointers
|
this->m_tlmEntries.buckets[entry].next = nullptr;
|
||||||
for (NATIVE_UINT_TYPE entry = 0; entry < TLMPACKETIZER_NUM_TLM_HASH_SLOTS; entry++) {
|
this->m_tlmEntries.buckets[entry].id = 0;
|
||||||
this->m_tlmEntries.slots[entry] = nullptr;
|
}
|
||||||
}
|
// clear free index
|
||||||
// clear buckets
|
this->m_tlmEntries.free = 0;
|
||||||
for (NATIVE_UINT_TYPE entry = 0; entry < TLMPACKETIZER_HASH_BUCKETS; entry++) {
|
// clear missing tlm channel check
|
||||||
this->m_tlmEntries.buckets[entry].used = false;
|
for (NATIVE_UINT_TYPE entry = 0; entry < TLMPACKETIZER_MAX_MISSING_TLM_CHECK; entry++) {
|
||||||
this->m_tlmEntries.buckets[entry].bucketNo = entry;
|
this->m_missTlmCheck[entry].checked = false;
|
||||||
this->m_tlmEntries.buckets[entry].next = nullptr;
|
this->m_missTlmCheck[entry].id = 0;
|
||||||
this->m_tlmEntries.buckets[entry].id = 0;
|
}
|
||||||
}
|
|
||||||
// clear free index
|
|
||||||
this->m_tlmEntries.free = 0;
|
|
||||||
// clear missing tlm channel check
|
|
||||||
for (NATIVE_UINT_TYPE entry = 0; entry < TLMPACKETIZER_MAX_MISSING_TLM_CHECK; entry++) {
|
|
||||||
this->m_missTlmCheck[entry].checked = false;
|
|
||||||
this->m_missTlmCheck[entry].id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear packet buffers
|
// clear packet buffers
|
||||||
for (NATIVE_UINT_TYPE buffer = 0; buffer < MAX_PACKETIZER_PACKETS; buffer++) {
|
for (NATIVE_UINT_TYPE buffer = 0; buffer < MAX_PACKETIZER_PACKETS; buffer++) {
|
||||||
this->m_fillBuffers[buffer].updated = false;
|
this->m_fillBuffers[buffer].updated = false;
|
||||||
this->m_fillBuffers[buffer].requested = false;
|
this->m_fillBuffers[buffer].requested = false;
|
||||||
this->m_sendBuffers[buffer].updated = false;
|
this->m_sendBuffers[buffer].updated = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TlmPacketizer ::
|
void TlmPacketizer ::init(const NATIVE_INT_TYPE queueDepth, const NATIVE_INT_TYPE instance) {
|
||||||
init(
|
|
||||||
const NATIVE_INT_TYPE queueDepth,
|
|
||||||
const NATIVE_INT_TYPE instance
|
|
||||||
)
|
|
||||||
{
|
|
||||||
TlmPacketizerComponentBase::init(queueDepth, instance);
|
TlmPacketizerComponentBase::init(queueDepth, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
TlmPacketizer ::
|
TlmPacketizer ::~TlmPacketizer() {}
|
||||||
~TlmPacketizer()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
void TlmPacketizer::setPacketList(const TlmPacketizerPacketList& packetList,
|
||||||
|
const Svc::TlmPacketizerPacket& ignoreList,
|
||||||
|
const NATIVE_UINT_TYPE startLevel) {
|
||||||
|
FW_ASSERT(packetList.list);
|
||||||
|
FW_ASSERT(ignoreList.list);
|
||||||
|
FW_ASSERT(packetList.numEntries <= MAX_PACKETIZER_PACKETS, packetList.numEntries);
|
||||||
|
// validate packet sizes against maximum com buffer size and populate hash
|
||||||
|
// table
|
||||||
|
for (NATIVE_UINT_TYPE pktEntry = 0; pktEntry < packetList.numEntries; pktEntry++) {
|
||||||
|
// Initial size is packetized telemetry descriptor + size of time tag + sizeof packet ID
|
||||||
|
NATIVE_UINT_TYPE packetLen =
|
||||||
|
sizeof(FwPacketDescriptorType) + Fw::Time::SERIALIZED_SIZE + sizeof(FwTlmPacketizeIdType);
|
||||||
|
FW_ASSERT(packetList.list[pktEntry]->list, pktEntry);
|
||||||
|
// add up entries for each defined packet
|
||||||
|
for (NATIVE_UINT_TYPE tlmEntry = 0; tlmEntry < packetList.list[pktEntry]->numEntries; tlmEntry++) {
|
||||||
|
// get hash value for id
|
||||||
|
FwChanIdType id = packetList.list[pktEntry]->list[tlmEntry].id;
|
||||||
|
TlmEntry* entryToUse = this->findBucket(id);
|
||||||
|
// copy into entry
|
||||||
|
FW_ASSERT(entryToUse);
|
||||||
|
entryToUse->used = true;
|
||||||
|
// not ignored channel
|
||||||
|
entryToUse->ignored = false;
|
||||||
|
entryToUse->id = id;
|
||||||
|
// the offset into the buffer will be the current packet length
|
||||||
|
entryToUse->packetOffset[pktEntry] = packetLen;
|
||||||
|
|
||||||
void TlmPacketizer::setPacketList(
|
packetLen += packetList.list[pktEntry]->list[tlmEntry].size;
|
||||||
const TlmPacketizerPacketList& packetList,
|
|
||||||
const Svc::TlmPacketizerPacket& ignoreList,
|
|
||||||
const NATIVE_UINT_TYPE startLevel) {
|
|
||||||
|
|
||||||
FW_ASSERT(packetList.list);
|
} // end channel in packet
|
||||||
FW_ASSERT(ignoreList.list);
|
FW_ASSERT(packetLen <= FW_COM_BUFFER_MAX_SIZE, packetLen, pktEntry);
|
||||||
FW_ASSERT(packetList.numEntries <= MAX_PACKETIZER_PACKETS,packetList.numEntries);
|
// clear contents
|
||||||
// validate packet sizes against maximum com buffer size and populate hash
|
memset(this->m_fillBuffers[pktEntry].buffer.getBuffAddr(), 0, packetLen);
|
||||||
// table
|
// serialize packet descriptor and packet ID now since it will always be the same
|
||||||
for (NATIVE_UINT_TYPE pktEntry = 0; pktEntry < packetList.numEntries; pktEntry++) {
|
Fw::SerializeStatus stat = this->m_fillBuffers[pktEntry].buffer.serialize(
|
||||||
// Initial size is packetized telemetry descriptor + size of time tag + sizeof packet ID
|
static_cast<FwPacketDescriptorType>(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM));
|
||||||
NATIVE_UINT_TYPE packetLen = sizeof(FwPacketDescriptorType) + Fw::Time::SERIALIZED_SIZE + sizeof(FwTlmPacketizeIdType);
|
FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, stat);
|
||||||
FW_ASSERT(packetList.list[pktEntry]->list,pktEntry);
|
stat = this->m_fillBuffers[pktEntry].buffer.serialize(packetList.list[pktEntry]->id);
|
||||||
// add up entries for each defined packet
|
FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, stat);
|
||||||
for (NATIVE_UINT_TYPE tlmEntry = 0; tlmEntry < packetList.list[pktEntry]->numEntries; tlmEntry++) {
|
// set packet buffer length
|
||||||
// get hash value for id
|
stat = this->m_fillBuffers[pktEntry].buffer.setBuffLen(packetLen);
|
||||||
FwChanIdType id = packetList.list[pktEntry]->list[tlmEntry].id;
|
FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, stat);
|
||||||
TlmEntry *entryToUse = this->findBucket(id);
|
// save ID
|
||||||
// copy into entry
|
this->m_fillBuffers[pktEntry].id = packetList.list[pktEntry]->id;
|
||||||
FW_ASSERT(entryToUse);
|
// save level
|
||||||
entryToUse->used = true;
|
this->m_fillBuffers[pktEntry].level = packetList.list[pktEntry]->level;
|
||||||
// not ignored channel
|
// store max level
|
||||||
entryToUse->ignored = false;
|
if (packetList.list[pktEntry]->level > this->m_maxLevel) {
|
||||||
entryToUse->id = id;
|
this->m_maxLevel = packetList.list[pktEntry]->level;
|
||||||
// the offset into the buffer will be the current packet length
|
}
|
||||||
entryToUse->packetOffset[pktEntry] = packetLen;
|
// save start level
|
||||||
|
this->m_startLevel = startLevel;
|
||||||
|
|
||||||
packetLen += packetList.list[pktEntry]->list[tlmEntry].size;
|
} // end packet list
|
||||||
|
|
||||||
} // end channel in packet
|
// populate hash table with ignore list
|
||||||
FW_ASSERT(packetLen <= FW_COM_BUFFER_MAX_SIZE,packetLen,pktEntry);
|
for (NATIVE_UINT_TYPE channelEntry = 0; channelEntry < ignoreList.numEntries; channelEntry++) {
|
||||||
// clear contents
|
// get hash value for id
|
||||||
memset(this->m_fillBuffers[pktEntry].buffer.getBuffAddr(),0,packetLen);
|
FwChanIdType id = ignoreList.list[channelEntry].id;
|
||||||
// serialize packet descriptor and packet ID now since it will always be the same
|
|
||||||
Fw::SerializeStatus stat = this->m_fillBuffers[pktEntry].buffer.serialize(static_cast<FwPacketDescriptorType>(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM));
|
|
||||||
FW_ASSERT(Fw::FW_SERIALIZE_OK == stat,stat);
|
|
||||||
stat = this->m_fillBuffers[pktEntry].buffer.serialize(packetList.list[pktEntry]->id);
|
|
||||||
FW_ASSERT(Fw::FW_SERIALIZE_OK == stat,stat);
|
|
||||||
// set packet buffer length
|
|
||||||
stat = this->m_fillBuffers[pktEntry].buffer.setBuffLen(packetLen);
|
|
||||||
FW_ASSERT(Fw::FW_SERIALIZE_OK == stat,stat);
|
|
||||||
// save ID
|
|
||||||
this->m_fillBuffers[pktEntry].id = packetList.list[pktEntry]->id;
|
|
||||||
// save level
|
|
||||||
this->m_fillBuffers[pktEntry].level = packetList.list[pktEntry]->level;
|
|
||||||
// store max level
|
|
||||||
if (packetList.list[pktEntry]->level > this->m_maxLevel) {
|
|
||||||
this->m_maxLevel = packetList.list[pktEntry]->level;
|
|
||||||
}
|
|
||||||
// save start level
|
|
||||||
this->m_startLevel = startLevel;
|
|
||||||
|
|
||||||
} // end packet list
|
TlmEntry* entryToUse = this->findBucket(id);
|
||||||
|
|
||||||
// populate hash table with ignore list
|
// copy into entry
|
||||||
for (NATIVE_UINT_TYPE channelEntry = 0; channelEntry < ignoreList.numEntries; channelEntry++) {
|
FW_ASSERT(entryToUse);
|
||||||
// get hash value for id
|
entryToUse->used = true;
|
||||||
FwChanIdType id = ignoreList.list[channelEntry].id;
|
// is ignored channel
|
||||||
|
entryToUse->ignored = true;
|
||||||
|
entryToUse->id = id;
|
||||||
|
} // end ignore list
|
||||||
|
|
||||||
TlmEntry *entryToUse = this->findBucket(id);
|
// store number of packets
|
||||||
|
this->m_numPackets = packetList.numEntries;
|
||||||
|
|
||||||
// copy into entry
|
// indicate configured
|
||||||
FW_ASSERT(entryToUse);
|
this->m_configured = true;
|
||||||
entryToUse->used = true;
|
}
|
||||||
// is ignored channel
|
|
||||||
entryToUse->ignored = true;
|
|
||||||
entryToUse->id = id;
|
|
||||||
} // end ignore list
|
|
||||||
|
|
||||||
// store number of packets
|
TlmPacketizer::TlmEntry* TlmPacketizer::findBucket(FwChanIdType id) {
|
||||||
this->m_numPackets = packetList.numEntries;
|
NATIVE_UINT_TYPE index = this->doHash(id);
|
||||||
|
FW_ASSERT(index < TLMPACKETIZER_HASH_BUCKETS);
|
||||||
|
TlmEntry* entryToUse = nullptr;
|
||||||
|
TlmEntry* prevEntry = nullptr;
|
||||||
|
|
||||||
// indicate configured
|
// Search to see if channel has already been stored or a bucket needs to be added
|
||||||
this->m_configured = true;
|
if (this->m_tlmEntries.slots[index]) {
|
||||||
}
|
entryToUse = this->m_tlmEntries.slots[index];
|
||||||
|
for (NATIVE_UINT_TYPE bucket = 0; bucket < TLMPACKETIZER_HASH_BUCKETS; bucket++) {
|
||||||
|
if (entryToUse) {
|
||||||
|
if (entryToUse->id == id) { // found the matching entry
|
||||||
|
break;
|
||||||
|
} else { // try next entry
|
||||||
|
prevEntry = entryToUse;
|
||||||
|
entryToUse = entryToUse->next;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Make sure that we haven't run out of buckets
|
||||||
|
FW_ASSERT(this->m_tlmEntries.free < TLMPACKETIZER_HASH_BUCKETS, this->m_tlmEntries.free);
|
||||||
|
// add new bucket from free list
|
||||||
|
entryToUse = &this->m_tlmEntries.buckets[this->m_tlmEntries.free++];
|
||||||
|
// Coverity warning about null dereference - see if it happens
|
||||||
|
FW_ASSERT(prevEntry);
|
||||||
|
prevEntry->next = entryToUse;
|
||||||
|
// clear next pointer
|
||||||
|
entryToUse->next = nullptr;
|
||||||
|
// set all packet offsets to -1 for new entry
|
||||||
|
for (NATIVE_UINT_TYPE pktOffsetEntry = 0; pktOffsetEntry < MAX_PACKETIZER_PACKETS; pktOffsetEntry++) {
|
||||||
|
entryToUse->packetOffset[pktOffsetEntry] = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Make sure that we haven't run out of buckets
|
||||||
|
FW_ASSERT(this->m_tlmEntries.free < TLMPACKETIZER_HASH_BUCKETS, this->m_tlmEntries.free);
|
||||||
|
// create new entry at slot head
|
||||||
|
this->m_tlmEntries.slots[index] = &this->m_tlmEntries.buckets[this->m_tlmEntries.free++];
|
||||||
|
entryToUse = this->m_tlmEntries.slots[index];
|
||||||
|
entryToUse->next = nullptr;
|
||||||
|
// set all packet offsets to -1 for new entry
|
||||||
|
for (NATIVE_UINT_TYPE pktOffsetEntry = 0; pktOffsetEntry < MAX_PACKETIZER_PACKETS; pktOffsetEntry++) {
|
||||||
|
entryToUse->packetOffset[pktOffsetEntry] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TlmPacketizer::TlmEntry* TlmPacketizer::findBucket(FwChanIdType id) {
|
return entryToUse;
|
||||||
NATIVE_UINT_TYPE index = this->doHash(id);
|
}
|
||||||
FW_ASSERT(index < TLMPACKETIZER_HASH_BUCKETS);
|
|
||||||
TlmEntry* entryToUse = nullptr;
|
|
||||||
TlmEntry* prevEntry = nullptr;
|
|
||||||
|
|
||||||
// Search to see if channel has already been stored or a bucket needs to be added
|
// ----------------------------------------------------------------------
|
||||||
if (this->m_tlmEntries.slots[index]) {
|
// Handler implementations for user-defined typed input ports
|
||||||
entryToUse = this->m_tlmEntries.slots[index];
|
// ----------------------------------------------------------------------
|
||||||
for (NATIVE_UINT_TYPE bucket = 0; bucket < TLMPACKETIZER_HASH_BUCKETS; bucket++) {
|
|
||||||
if (entryToUse) {
|
|
||||||
if (entryToUse->id == id) { // found the matching entry
|
|
||||||
break;
|
|
||||||
} else { // try next entry
|
|
||||||
prevEntry = entryToUse;
|
|
||||||
entryToUse = entryToUse->next;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Make sure that we haven't run out of buckets
|
|
||||||
FW_ASSERT(this->m_tlmEntries.free < TLMPACKETIZER_HASH_BUCKETS,this->m_tlmEntries.free);
|
|
||||||
// add new bucket from free list
|
|
||||||
entryToUse = &this->m_tlmEntries.buckets[this->m_tlmEntries.free++];
|
|
||||||
// Coverity warning about null dereference - see if it happens
|
|
||||||
FW_ASSERT(prevEntry);
|
|
||||||
prevEntry->next = entryToUse;
|
|
||||||
// clear next pointer
|
|
||||||
entryToUse->next = nullptr;
|
|
||||||
// set all packet offsets to -1 for new entry
|
|
||||||
for (NATIVE_UINT_TYPE pktOffsetEntry = 0; pktOffsetEntry < MAX_PACKETIZER_PACKETS; pktOffsetEntry++) {
|
|
||||||
entryToUse->packetOffset[pktOffsetEntry] = -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Make sure that we haven't run out of buckets
|
|
||||||
FW_ASSERT(this->m_tlmEntries.free < TLMPACKETIZER_HASH_BUCKETS,this->m_tlmEntries.free);
|
|
||||||
// create new entry at slot head
|
|
||||||
this->m_tlmEntries.slots[index] = &this->m_tlmEntries.buckets[this->m_tlmEntries.free++];
|
|
||||||
entryToUse = this->m_tlmEntries.slots[index];
|
|
||||||
entryToUse->next = nullptr;
|
|
||||||
// set all packet offsets to -1 for new entry
|
|
||||||
for (NATIVE_UINT_TYPE pktOffsetEntry = 0; pktOffsetEntry < MAX_PACKETIZER_PACKETS; pktOffsetEntry++) {
|
|
||||||
entryToUse->packetOffset[pktOffsetEntry] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
void TlmPacketizer ::TlmRecv_handler(const NATIVE_INT_TYPE portNum,
|
||||||
|
FwChanIdType id,
|
||||||
|
Fw::Time& timeTag,
|
||||||
|
Fw::TlmBuffer& val) {
|
||||||
|
FW_ASSERT(this->m_configured);
|
||||||
|
// get hash value for id
|
||||||
|
NATIVE_UINT_TYPE index = this->doHash(id);
|
||||||
|
TlmEntry* entryToUse = nullptr;
|
||||||
|
|
||||||
return entryToUse;
|
// Search to see if the channel is being sent
|
||||||
}
|
entryToUse = this->m_tlmEntries.slots[index];
|
||||||
|
|
||||||
|
// if no entries at hash, channel not part of a packet or is not ignored
|
||||||
|
if (not entryToUse) {
|
||||||
|
this->missingChannel(id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (NATIVE_UINT_TYPE bucket = 0; bucket < TLMPACKETIZER_HASH_BUCKETS; bucket++) {
|
||||||
|
if (entryToUse) {
|
||||||
|
if (entryToUse->id == id) { // found the matching entry
|
||||||
|
// check to see if the channel is ignored. If so, just return.
|
||||||
|
if (entryToUse->ignored) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else { // try next entry
|
||||||
|
entryToUse = entryToUse->next;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// telemetry channel not in any packets
|
||||||
|
this->missingChannel(id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// copy telemetry value into active buffers
|
||||||
// Handler implementations for user-defined typed input ports
|
for (NATIVE_UINT_TYPE pkt = 0; pkt < MAX_PACKETIZER_PACKETS; pkt++) {
|
||||||
// ----------------------------------------------------------------------
|
// check if current packet has this channel
|
||||||
|
if (entryToUse->packetOffset[pkt] != -1) {
|
||||||
|
// get destination address
|
||||||
|
// printf("PK %d CH: %d\n",this->m_fillBuffers[pkt].id,id);
|
||||||
|
this->m_lock.lock();
|
||||||
|
this->m_fillBuffers[pkt].updated = true;
|
||||||
|
this->m_fillBuffers[pkt].latestTime = timeTag;
|
||||||
|
U8* ptr = &this->m_fillBuffers[pkt].buffer.getBuffAddr()[entryToUse->packetOffset[pkt]];
|
||||||
|
memcpy(ptr, val.getBuffAddr(), val.getBuffLength());
|
||||||
|
this->m_lock.unLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TlmPacketizer ::
|
void TlmPacketizer ::Run_handler(const NATIVE_INT_TYPE portNum, NATIVE_UINT_TYPE context) {
|
||||||
TlmRecv_handler(
|
FW_ASSERT(this->m_configured);
|
||||||
const NATIVE_INT_TYPE portNum,
|
|
||||||
FwChanIdType id,
|
|
||||||
Fw::Time &timeTag,
|
|
||||||
Fw::TlmBuffer &val
|
|
||||||
)
|
|
||||||
{
|
|
||||||
FW_ASSERT(this->m_configured);
|
|
||||||
// get hash value for id
|
|
||||||
NATIVE_UINT_TYPE index = this->doHash(id);
|
|
||||||
TlmEntry* entryToUse = nullptr;
|
|
||||||
|
|
||||||
// Search to see if the channel is being sent
|
// Only write packets if connected
|
||||||
entryToUse = this->m_tlmEntries.slots[index];
|
if (not this->isConnected_PktSend_OutputPort(0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// if no entries at hash, channel not part of a packet or is not ignored
|
// lock mutex long enough to modify active telemetry buffer
|
||||||
if (not entryToUse) {
|
// so the data can be read without worrying about updates
|
||||||
this->missingChannel(id);
|
this->m_lock.lock();
|
||||||
return;
|
// copy buffers from fill side to send side
|
||||||
}
|
for (NATIVE_UINT_TYPE pkt = 0; pkt < this->m_numPackets; pkt++) {
|
||||||
|
if ((this->m_fillBuffers[pkt].updated) and
|
||||||
|
((this->m_fillBuffers[pkt].level <= this->m_startLevel) or (this->m_fillBuffers[pkt].requested))) {
|
||||||
|
this->m_sendBuffers[pkt] = this->m_fillBuffers[pkt];
|
||||||
|
if (PACKET_UPDATE_ON_CHANGE == PACKET_UPDATE_MODE) {
|
||||||
|
this->m_fillBuffers[pkt].updated = false;
|
||||||
|
}
|
||||||
|
this->m_fillBuffers[pkt].requested = false;
|
||||||
|
// PACKET_UPDATE_AFTER_FIRST_CHANGE will be this case - updated flag will not be cleared
|
||||||
|
} else if ((PACKET_UPDATE_ALWAYS == PACKET_UPDATE_MODE) and
|
||||||
|
(this->m_fillBuffers[pkt].level <= this->m_startLevel)) {
|
||||||
|
this->m_sendBuffers[pkt] = this->m_fillBuffers[pkt];
|
||||||
|
this->m_sendBuffers[pkt].updated = true;
|
||||||
|
} else {
|
||||||
|
this->m_sendBuffers[pkt].updated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->m_lock.unLock();
|
||||||
|
|
||||||
for (NATIVE_UINT_TYPE bucket = 0; bucket < TLMPACKETIZER_HASH_BUCKETS; bucket++) {
|
// push all updated packet buffers
|
||||||
if (entryToUse) {
|
for (NATIVE_UINT_TYPE pkt = 0; pkt < this->m_numPackets; pkt++) {
|
||||||
if (entryToUse->id == id) { // found the matching entry
|
if (this->m_sendBuffers[pkt].updated) {
|
||||||
// check to see if the channel is ignored. If so, just return.
|
// serialize time into time offset in packet
|
||||||
if (entryToUse->ignored) {
|
Fw::ExternalSerializeBuffer buff(
|
||||||
return;
|
&this->m_sendBuffers[pkt]
|
||||||
}
|
.buffer.getBuffAddr()[sizeof(FwPacketDescriptorType) + sizeof(FwTlmPacketizeIdType)],
|
||||||
break;
|
Fw::Time::SERIALIZED_SIZE);
|
||||||
} else { // try next entry
|
Fw::SerializeStatus stat = buff.serialize(this->m_sendBuffers[pkt].latestTime);
|
||||||
entryToUse = entryToUse->next;
|
FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, stat);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// telemetry channel not in any packets
|
|
||||||
this->missingChannel(id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy telemetry value into active buffers
|
this->PktSend_out(0, this->m_sendBuffers[pkt].buffer, 0);
|
||||||
for (NATIVE_UINT_TYPE pkt = 0; pkt < MAX_PACKETIZER_PACKETS; pkt++) {
|
}
|
||||||
// check if current packet has this channel
|
}
|
||||||
if (entryToUse->packetOffset[pkt] != -1) {
|
}
|
||||||
// get destination address
|
|
||||||
// printf("PK %d CH: %d\n",this->m_fillBuffers[pkt].id,id);
|
|
||||||
this->m_lock.lock();
|
|
||||||
this->m_fillBuffers[pkt].updated = true;
|
|
||||||
this->m_fillBuffers[pkt].latestTime = timeTag;
|
|
||||||
U8* ptr = &this->m_fillBuffers[pkt].buffer.getBuffAddr()[entryToUse->packetOffset[pkt]];
|
|
||||||
memcpy(ptr,val.getBuffAddr(),val.getBuffLength());
|
|
||||||
this->m_lock.unLock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
void TlmPacketizer ::pingIn_handler(const NATIVE_INT_TYPE portNum, U32 key) {
|
||||||
|
// return key
|
||||||
|
this->pingOut_out(0, key);
|
||||||
|
}
|
||||||
|
|
||||||
void TlmPacketizer ::
|
// ----------------------------------------------------------------------
|
||||||
Run_handler(
|
// Command handler implementations
|
||||||
const NATIVE_INT_TYPE portNum,
|
// ----------------------------------------------------------------------
|
||||||
NATIVE_UINT_TYPE context
|
|
||||||
)
|
|
||||||
{
|
|
||||||
FW_ASSERT(this->m_configured);
|
|
||||||
|
|
||||||
// Only write packets if connected
|
void TlmPacketizer ::SET_LEVEL_cmdHandler(const FwOpcodeType opCode, const U32 cmdSeq, U32 level) {
|
||||||
if (not this->isConnected_PktSend_OutputPort(0)) {
|
this->m_startLevel = level;
|
||||||
return;
|
if (level > this->m_maxLevel) {
|
||||||
}
|
this->log_WARNING_LO_MaxLevelExceed(level, this->m_maxLevel);
|
||||||
|
}
|
||||||
|
this->tlmWrite_SendLevel(level);
|
||||||
|
this->log_ACTIVITY_HI_LevelSet(level);
|
||||||
|
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
|
||||||
|
}
|
||||||
|
|
||||||
// lock mutex long enough to modify active telemetry buffer
|
void TlmPacketizer ::SEND_PKT_cmdHandler(const FwOpcodeType opCode, const U32 cmdSeq, U32 id) {
|
||||||
// so the data can be read without worrying about updates
|
NATIVE_UINT_TYPE pkt = 0;
|
||||||
this->m_lock.lock();
|
for (pkt = 0; pkt < this->m_numPackets; pkt++) {
|
||||||
// copy buffers from fill side to send side
|
if (this->m_fillBuffers[pkt].id == id) {
|
||||||
for (NATIVE_UINT_TYPE pkt = 0; pkt < this->m_numPackets; pkt++) {
|
this->m_lock.lock();
|
||||||
if ((this->m_fillBuffers[pkt].updated) and
|
this->m_fillBuffers[pkt].updated = true;
|
||||||
((this->m_fillBuffers[pkt].level <= this->m_startLevel) or
|
this->m_fillBuffers[pkt].latestTime = this->getTime();
|
||||||
(this->m_fillBuffers[pkt].requested))) {
|
this->m_fillBuffers[pkt].requested = true;
|
||||||
|
this->m_lock.unLock();
|
||||||
|
|
||||||
this->m_sendBuffers[pkt] = this->m_fillBuffers[pkt];
|
this->log_ACTIVITY_LO_PacketSent(id);
|
||||||
if (PACKET_UPDATE_ON_CHANGE == PACKET_UPDATE_MODE) {
|
break;
|
||||||
this->m_fillBuffers[pkt].updated = false;
|
}
|
||||||
}
|
}
|
||||||
this->m_fillBuffers[pkt].requested = false;
|
|
||||||
// PACKET_UPDATE_AFTER_FIRST_CHANGE will be this case - updated flag will not be cleared
|
|
||||||
} else if ((PACKET_UPDATE_ALWAYS == PACKET_UPDATE_MODE) and (this->m_fillBuffers[pkt].level <= this->m_startLevel)) {
|
|
||||||
this->m_sendBuffers[pkt] = this->m_fillBuffers[pkt];
|
|
||||||
this->m_sendBuffers[pkt].updated = true;
|
|
||||||
} else {
|
|
||||||
this->m_sendBuffers[pkt].updated = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->m_lock.unLock();
|
|
||||||
|
|
||||||
// push all updated packet buffers
|
// couldn't find it
|
||||||
for (NATIVE_UINT_TYPE pkt = 0; pkt < this->m_numPackets; pkt++) {
|
if (pkt == this->m_numPackets) {
|
||||||
if (this->m_sendBuffers[pkt].updated) {
|
log_WARNING_LO_PacketNotFound(id);
|
||||||
// serialize time into time offset in packet
|
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
|
||||||
Fw::ExternalSerializeBuffer buff(&this->m_sendBuffers[pkt].buffer.getBuffAddr()
|
return;
|
||||||
[sizeof(FwPacketDescriptorType)+ sizeof(FwTlmPacketizeIdType)],Fw::Time::SERIALIZED_SIZE);
|
}
|
||||||
Fw::SerializeStatus stat = buff.serialize(this->m_sendBuffers[pkt].latestTime);
|
|
||||||
FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, stat);
|
|
||||||
this->PktSend_out(0,this->m_sendBuffers[pkt].buffer,0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TlmPacketizer ::
|
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
|
||||||
pingIn_handler(
|
}
|
||||||
const NATIVE_INT_TYPE portNum,
|
|
||||||
U32 key
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// return key
|
|
||||||
this->pingOut_out(0,key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
NATIVE_UINT_TYPE TlmPacketizer::doHash(FwChanIdType id) {
|
||||||
// Command handler implementations
|
return (id % TLMPACKETIZER_HASH_MOD_VALUE) % TLMPACKETIZER_NUM_TLM_HASH_SLOTS;
|
||||||
// ----------------------------------------------------------------------
|
}
|
||||||
|
|
||||||
void TlmPacketizer ::
|
void TlmPacketizer::missingChannel(FwChanIdType id) {
|
||||||
SET_LEVEL_cmdHandler(
|
// search to see if missing channel has already been sent
|
||||||
const FwOpcodeType opCode,
|
for (NATIVE_UINT_TYPE slot = 0; slot < TLMPACKETIZER_MAX_MISSING_TLM_CHECK; slot++) {
|
||||||
const U32 cmdSeq,
|
// if it's been checked, return
|
||||||
U32 level
|
if (this->m_missTlmCheck[slot].checked and (this->m_missTlmCheck[slot].id == id)) {
|
||||||
)
|
return;
|
||||||
{
|
} else if (not this->m_missTlmCheck[slot].checked) {
|
||||||
this->m_startLevel = level;
|
this->m_missTlmCheck[slot].checked = true;
|
||||||
if (level > this->m_maxLevel) {
|
this->m_missTlmCheck[slot].id = id;
|
||||||
this->log_WARNING_LO_MaxLevelExceed(level,this->m_maxLevel);
|
this->log_WARNING_LO_NoChan(id);
|
||||||
}
|
return;
|
||||||
this->tlmWrite_SendLevel(level);
|
}
|
||||||
this->log_ACTIVITY_HI_LevelSet(level);
|
}
|
||||||
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void TlmPacketizer ::
|
} // end namespace Svc
|
||||||
SEND_PKT_cmdHandler(
|
|
||||||
const FwOpcodeType opCode,
|
|
||||||
const U32 cmdSeq,
|
|
||||||
U32 id
|
|
||||||
)
|
|
||||||
{
|
|
||||||
NATIVE_UINT_TYPE pkt = 0;
|
|
||||||
for (pkt = 0; pkt < this->m_numPackets; pkt++) {
|
|
||||||
if (this->m_fillBuffers[pkt].id == id) {
|
|
||||||
|
|
||||||
this->m_lock.lock();
|
|
||||||
this->m_fillBuffers[pkt].updated = true;
|
|
||||||
this->m_fillBuffers[pkt].latestTime = this->getTime();
|
|
||||||
this->m_fillBuffers[pkt].requested = true;
|
|
||||||
this->m_lock.unLock();
|
|
||||||
|
|
||||||
this->log_ACTIVITY_LO_PacketSent(id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// couldn't find it
|
|
||||||
if (pkt == this->m_numPackets) {
|
|
||||||
log_WARNING_LO_PacketNotFound(id);
|
|
||||||
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NATIVE_UINT_TYPE TlmPacketizer::doHash(FwChanIdType id) {
|
|
||||||
return (id % TLMPACKETIZER_HASH_MOD_VALUE)%TLMPACKETIZER_NUM_TLM_HASH_SLOTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TlmPacketizer::missingChannel(FwChanIdType id) {
|
|
||||||
// search to see if missing channel has already been sent
|
|
||||||
for (NATIVE_UINT_TYPE slot = 0; slot < TLMPACKETIZER_MAX_MISSING_TLM_CHECK; slot++) {
|
|
||||||
// if it's been checked, return
|
|
||||||
if (this->m_missTlmCheck[slot].checked and (this->m_missTlmCheck[slot].id == id)) {
|
|
||||||
return;
|
|
||||||
} else if (not this->m_missTlmCheck[slot].checked) {
|
|
||||||
this->m_missTlmCheck[slot].checked = true;
|
|
||||||
this->m_missTlmCheck[slot].id = id;
|
|
||||||
this->log_WARNING_LO_NoChan(id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // end namespace Svc
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// ======================================================================
|
// ======================================================================
|
||||||
// \title TlmPacketizerImpl.hpp
|
// \title TlmPacketizerImpl.hpp
|
||||||
// \author tcanham
|
// \author tcanham
|
||||||
// \brief hpp file for TlmPacketizer component implementation class
|
// \brief hpp file for TlmPacketizer component implementation class
|
||||||
@ -11,147 +11,134 @@
|
|||||||
#ifndef TlmPacketizer_HPP
|
#ifndef TlmPacketizer_HPP
|
||||||
#define TlmPacketizer_HPP
|
#define TlmPacketizer_HPP
|
||||||
|
|
||||||
|
#include "Os/Mutex.hpp"
|
||||||
#include "Svc/TlmPacketizer/TlmPacketizerComponentAc.hpp"
|
#include "Svc/TlmPacketizer/TlmPacketizerComponentAc.hpp"
|
||||||
#include "Svc/TlmPacketizer/TlmPacketizerTypes.hpp"
|
#include "Svc/TlmPacketizer/TlmPacketizerTypes.hpp"
|
||||||
#include "Svc/TlmPacketizer/TlmPacketizerComponentImplCfg.hpp"
|
#include "TlmPacketizerCfg.hpp"
|
||||||
#include "Os/Mutex.hpp"
|
|
||||||
|
|
||||||
namespace Svc {
|
namespace Svc {
|
||||||
|
|
||||||
class TlmPacketizer :
|
class TlmPacketizer : public TlmPacketizerComponentBase {
|
||||||
public TlmPacketizerComponentBase
|
public:
|
||||||
{
|
// ----------------------------------------------------------------------
|
||||||
|
// Construction, initialization, and destruction
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
public:
|
//! Construct object TlmPacketizer
|
||||||
|
//!
|
||||||
|
TlmPacketizer(const char* const compName /*!< The component name*/
|
||||||
|
);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
//! Initialize object TlmPacketizer
|
||||||
// Construction, initialization, and destruction
|
//!
|
||||||
// ----------------------------------------------------------------------
|
void init(const NATIVE_INT_TYPE queueDepth, /*!< The queue depth*/
|
||||||
|
const NATIVE_INT_TYPE instance = 0 /*!< The instance number*/
|
||||||
|
);
|
||||||
|
|
||||||
//! Construct object TlmPacketizer
|
void setPacketList(
|
||||||
//!
|
const TlmPacketizerPacketList& packetList, // channels to packetize
|
||||||
TlmPacketizer(
|
const Svc::TlmPacketizerPacket& ignoreList, // channels to ignore (i.e. no warning event if not packetized)
|
||||||
const char *const compName /*!< The component name*/
|
const NATIVE_UINT_TYPE startLevel); // starting level of packets to send
|
||||||
);
|
|
||||||
|
|
||||||
//! Initialize object TlmPacketizer
|
//! Destroy object TlmPacketizer
|
||||||
//!
|
//!
|
||||||
void init(
|
~TlmPacketizer(void);
|
||||||
const NATIVE_INT_TYPE queueDepth, /*!< The queue depth*/
|
|
||||||
const NATIVE_INT_TYPE instance = 0 /*!< The instance number*/
|
|
||||||
);
|
|
||||||
|
|
||||||
void setPacketList(
|
PRIVATE:
|
||||||
const TlmPacketizerPacketList& packetList, // channels to packetize
|
// ----------------------------------------------------------------------
|
||||||
const Svc::TlmPacketizerPacket& ignoreList, // channels to ignore (i.e. no warning event if not packetized)
|
// Handler implementations for user-defined typed input ports
|
||||||
const NATIVE_UINT_TYPE startLevel); // starting level of packets to send
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
//! Destroy object TlmPacketizer
|
//! Handler implementation for TlmRecv
|
||||||
//!
|
//!
|
||||||
~TlmPacketizer(void);
|
void TlmRecv_handler(const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
||||||
|
FwChanIdType id, /*!< Telemetry Channel ID*/
|
||||||
|
Fw::Time& timeTag, /*!< Time Tag*/
|
||||||
|
Fw::TlmBuffer& val /*!< Buffer containing serialized telemetry value*/
|
||||||
|
);
|
||||||
|
|
||||||
PRIVATE:
|
//! Handler implementation for Run
|
||||||
|
//!
|
||||||
|
void Run_handler(const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
||||||
|
NATIVE_UINT_TYPE context /*!< The call order*/
|
||||||
|
);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
//! Handler implementation for pingIn
|
||||||
// Handler implementations for user-defined typed input ports
|
//!
|
||||||
// ----------------------------------------------------------------------
|
void pingIn_handler(const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
||||||
|
U32 key /*!< Value to return to pinger*/
|
||||||
|
);
|
||||||
|
|
||||||
//! Handler implementation for TlmRecv
|
//! Implementation for SET_LEVEL command handler
|
||||||
//!
|
//! Set telemetry send leve
|
||||||
void TlmRecv_handler(
|
void SET_LEVEL_cmdHandler(const FwOpcodeType opCode, /*!< The opcode*/
|
||||||
const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
const U32 cmdSeq, /*!< The command sequence number*/
|
||||||
FwChanIdType id, /*!< Telemetry Channel ID*/
|
U32 level /*!< The I32 command argument*/
|
||||||
Fw::Time &timeTag, /*!< Time Tag*/
|
);
|
||||||
Fw::TlmBuffer &val /*!< Buffer containing serialized telemetry value*/
|
|
||||||
);
|
|
||||||
|
|
||||||
//! Handler implementation for Run
|
//! Implementation for SEND_PKT command handler
|
||||||
//!
|
//! Force a packet to be sent
|
||||||
void Run_handler(
|
void SEND_PKT_cmdHandler(const FwOpcodeType opCode, /*!< The opcode*/
|
||||||
const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
const U32 cmdSeq, /*!< The command sequence number*/
|
||||||
NATIVE_UINT_TYPE context /*!< The call order*/
|
U32 id /*!< The packet ID*/
|
||||||
);
|
);
|
||||||
|
|
||||||
//! Handler implementation for pingIn
|
// number of packets to fill
|
||||||
//!
|
NATIVE_UINT_TYPE m_numPackets;
|
||||||
void pingIn_handler(
|
// Array of packet buffers to send
|
||||||
const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
// Double-buffered to fill one while sending one
|
||||||
U32 key /*!< Value to return to pinger*/
|
|
||||||
);
|
|
||||||
|
|
||||||
//! Implementation for SET_LEVEL command handler
|
|
||||||
//! Set telemetry send leve
|
|
||||||
void SET_LEVEL_cmdHandler(
|
|
||||||
const FwOpcodeType opCode, /*!< The opcode*/
|
|
||||||
const U32 cmdSeq, /*!< The command sequence number*/
|
|
||||||
U32 level /*!< The I32 command argument*/
|
|
||||||
);
|
|
||||||
|
|
||||||
//! Implementation for SEND_PKT command handler
|
|
||||||
//! Force a packet to be sent
|
|
||||||
void SEND_PKT_cmdHandler(
|
|
||||||
const FwOpcodeType opCode, /*!< The opcode*/
|
|
||||||
const U32 cmdSeq, /*!< The command sequence number*/
|
|
||||||
U32 id /*!< The packet ID*/
|
|
||||||
);
|
|
||||||
|
|
||||||
// number of packets to fill
|
|
||||||
NATIVE_UINT_TYPE m_numPackets;
|
|
||||||
// Array of packet buffers to send
|
|
||||||
// Double-buffered to fill one while sending one
|
|
||||||
|
|
||||||
struct BufferEntry {
|
|
||||||
Fw::ComBuffer buffer; //!< buffer for packetized channels
|
|
||||||
Fw::Time latestTime; //!< latest update time
|
|
||||||
NATIVE_UINT_TYPE id; //!< channel id
|
|
||||||
NATIVE_UINT_TYPE level; //!< channel level
|
|
||||||
bool updated; //!< if packet had any updates during last cycle
|
|
||||||
bool requested; //!< if the packet was requested with SEND_PKT in the last cycle
|
|
||||||
};
|
|
||||||
|
|
||||||
// buffers for filling with telemetry
|
|
||||||
BufferEntry m_fillBuffers[MAX_PACKETIZER_PACKETS];
|
|
||||||
// buffers for sending - will be copied from fill buffers
|
|
||||||
BufferEntry m_sendBuffers[MAX_PACKETIZER_PACKETS];
|
|
||||||
|
|
||||||
struct TlmEntry {
|
|
||||||
FwChanIdType id; //!< telemetry id stored in slot
|
|
||||||
// Offsets into packet buffers.
|
|
||||||
// -1 means that channel is not in that packet
|
|
||||||
NATIVE_INT_TYPE packetOffset[MAX_PACKETIZER_PACKETS];
|
|
||||||
TlmEntry* next; //!< pointer to next bucket in table
|
|
||||||
bool used; //!< if entry has been used
|
|
||||||
bool ignored; //!< ignored packet id
|
|
||||||
NATIVE_UINT_TYPE bucketNo; //!< for testing
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TlmSet {
|
|
||||||
TlmEntry* slots[TLMPACKETIZER_NUM_TLM_HASH_SLOTS]; //!< set of hash slots in hash table
|
|
||||||
TlmEntry buckets[TLMPACKETIZER_HASH_BUCKETS]; //!< set of buckets used in hash table
|
|
||||||
NATIVE_UINT_TYPE free; //!< next free bucket
|
|
||||||
} m_tlmEntries;
|
|
||||||
|
|
||||||
// hash function for looking up telemetry channel
|
|
||||||
NATIVE_UINT_TYPE doHash(FwChanIdType id);
|
|
||||||
|
|
||||||
Os::Mutex m_lock; //!< used to lock access to packet buffers
|
|
||||||
|
|
||||||
bool m_configured; //!< indicates a table has been passed and packets configured
|
|
||||||
|
|
||||||
struct MissingTlmChan {
|
|
||||||
FwChanIdType id;
|
|
||||||
bool checked;
|
|
||||||
} m_missTlmCheck[TLMPACKETIZER_MAX_MISSING_TLM_CHECK];
|
|
||||||
|
|
||||||
void missingChannel(FwChanIdType id); //!< Helper to check to see if missing channel warning was sent
|
|
||||||
|
|
||||||
TlmEntry* findBucket(FwChanIdType id);
|
|
||||||
|
|
||||||
NATIVE_UINT_TYPE m_startLevel; //!< initial level for sending packets
|
|
||||||
NATIVE_UINT_TYPE m_maxLevel; //!< maximum level in all packets
|
|
||||||
|
|
||||||
|
struct BufferEntry {
|
||||||
|
Fw::ComBuffer buffer; //!< buffer for packetized channels
|
||||||
|
Fw::Time latestTime; //!< latest update time
|
||||||
|
NATIVE_UINT_TYPE id; //!< channel id
|
||||||
|
NATIVE_UINT_TYPE level; //!< channel level
|
||||||
|
bool updated; //!< if packet had any updates during last cycle
|
||||||
|
bool requested; //!< if the packet was requested with SEND_PKT in the last cycle
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace Svc
|
// buffers for filling with telemetry
|
||||||
|
BufferEntry m_fillBuffers[MAX_PACKETIZER_PACKETS];
|
||||||
|
// buffers for sending - will be copied from fill buffers
|
||||||
|
BufferEntry m_sendBuffers[MAX_PACKETIZER_PACKETS];
|
||||||
|
|
||||||
|
struct TlmEntry {
|
||||||
|
FwChanIdType id; //!< telemetry id stored in slot
|
||||||
|
// Offsets into packet buffers.
|
||||||
|
// -1 means that channel is not in that packet
|
||||||
|
NATIVE_INT_TYPE packetOffset[MAX_PACKETIZER_PACKETS];
|
||||||
|
TlmEntry* next; //!< pointer to next bucket in table
|
||||||
|
bool used; //!< if entry has been used
|
||||||
|
bool ignored; //!< ignored packet id
|
||||||
|
NATIVE_UINT_TYPE bucketNo; //!< for testing
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TlmSet {
|
||||||
|
TlmEntry* slots[TLMPACKETIZER_NUM_TLM_HASH_SLOTS]; //!< set of hash slots in hash table
|
||||||
|
TlmEntry buckets[TLMPACKETIZER_HASH_BUCKETS]; //!< set of buckets used in hash table
|
||||||
|
NATIVE_UINT_TYPE free; //!< next free bucket
|
||||||
|
} m_tlmEntries;
|
||||||
|
|
||||||
|
// hash function for looking up telemetry channel
|
||||||
|
NATIVE_UINT_TYPE doHash(FwChanIdType id);
|
||||||
|
|
||||||
|
Os::Mutex m_lock; //!< used to lock access to packet buffers
|
||||||
|
|
||||||
|
bool m_configured; //!< indicates a table has been passed and packets configured
|
||||||
|
|
||||||
|
struct MissingTlmChan {
|
||||||
|
FwChanIdType id;
|
||||||
|
bool checked;
|
||||||
|
} m_missTlmCheck[TLMPACKETIZER_MAX_MISSING_TLM_CHECK];
|
||||||
|
|
||||||
|
void missingChannel(FwChanIdType id); //!< Helper to check to see if missing channel warning was sent
|
||||||
|
|
||||||
|
TlmEntry* findBucket(FwChanIdType id);
|
||||||
|
|
||||||
|
NATIVE_UINT_TYPE m_startLevel; //!< initial level for sending packets
|
||||||
|
NATIVE_UINT_TYPE m_maxLevel; //!< maximum level in all packets
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace Svc
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* TlmPacketizerComponentImplCfg.hpp
|
|
||||||
*
|
|
||||||
* Created on: Dec 10, 2017
|
|
||||||
* Author: tim
|
|
||||||
*/
|
|
||||||
|
|
||||||
// \copyright
|
|
||||||
// Copyright 2009-2015, by the California Institute of Technology.
|
|
||||||
// ALL RIGHTS RESERVED. United States Government Sponsorship
|
|
||||||
// acknowledged.
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef SVC_TLMPACKETIZER_TLMPACKETIZERCOMPONENTIMPLCFG_HPP_
|
|
||||||
#define SVC_TLMPACKETIZER_TLMPACKETIZERCOMPONENTIMPLCFG_HPP_
|
|
||||||
|
|
||||||
#include <FpConfig.hpp>
|
|
||||||
|
|
||||||
namespace Svc {
|
|
||||||
static const NATIVE_UINT_TYPE MAX_PACKETIZER_PACKETS = 200;
|
|
||||||
static const NATIVE_UINT_TYPE TLMPACKETIZER_NUM_TLM_HASH_SLOTS = 15; // !< Number of slots in the hash table.
|
|
||||||
// Works best when set to about twice the number of components producing telemetry
|
|
||||||
static const NATIVE_UINT_TYPE TLMPACKETIZER_HASH_MOD_VALUE = 99; // !< The modulo value of the hashing function.
|
|
||||||
// Should be set to a little below the ID gaps to spread the entries around
|
|
||||||
|
|
||||||
static const NATIVE_UINT_TYPE TLMPACKETIZER_HASH_BUCKETS = 1000; // !< Buckets assignable to a hash slot.
|
|
||||||
// Buckets must be >= number of telemetry channels in system
|
|
||||||
static const NATIVE_UINT_TYPE TLMPACKETIZER_MAX_MISSING_TLM_CHECK = 25; // !< Maximum number of missing telemetry channel checks
|
|
||||||
|
|
||||||
// packet update mode
|
|
||||||
enum PacketUpdateMode {
|
|
||||||
PACKET_UPDATE_ALWAYS, // Always send packets, even if no changes to channel data
|
|
||||||
PACKET_UPDATE_ON_CHANGE, // Only send packets if any of the channels updates
|
|
||||||
PACKET_UPDATE_AFTER_FIRST_CHANGE, // Always send packets, but only after first channel has been updated
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PacketUpdateMode PACKET_UPDATE_MODE = PACKET_UPDATE_ON_CHANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* SVC_TLMPACKETIZER_TLMPACKETIZERCOMPONENTIMPLCFG_HPP_ */
|
|
||||||
@ -10,31 +10,30 @@
|
|||||||
// ALL RIGHTS RESERVED. United States Government Sponsorship
|
// ALL RIGHTS RESERVED. United States Government Sponsorship
|
||||||
// acknowledged.
|
// acknowledged.
|
||||||
|
|
||||||
|
|
||||||
#ifndef SVC_TLMPACKETIZER_TLMPACKETIZERTYPES_HPP_
|
#ifndef SVC_TLMPACKETIZER_TLMPACKETIZERTYPES_HPP_
|
||||||
#define SVC_TLMPACKETIZER_TLMPACKETIZERTYPES_HPP_
|
#define SVC_TLMPACKETIZER_TLMPACKETIZERTYPES_HPP_
|
||||||
|
|
||||||
#include <FpConfig.hpp>
|
#include <FpConfig.hpp>
|
||||||
#include <Svc/TlmPacketizer/TlmPacketizerComponentImplCfg.hpp>
|
#include <TlmPacketizerCfg.hpp>
|
||||||
|
|
||||||
namespace Svc {
|
namespace Svc {
|
||||||
|
|
||||||
struct TlmPacketizerChannelEntry {
|
struct TlmPacketizerChannelEntry {
|
||||||
FwChanIdType id; //!< Id of channel
|
FwChanIdType id; //!< Id of channel
|
||||||
NATIVE_UINT_TYPE size; //!< serialized size of channel in bytes
|
NATIVE_UINT_TYPE size; //!< serialized size of channel in bytes
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TlmPacketizerPacket {
|
struct TlmPacketizerPacket {
|
||||||
const TlmPacketizerChannelEntry* list; //!< pointer to a channel entry
|
const TlmPacketizerChannelEntry* list; //!< pointer to a channel entry
|
||||||
FwTlmPacketizeIdType id; //!< packet ID
|
FwTlmPacketizeIdType id; //!< packet ID
|
||||||
NATIVE_UINT_TYPE level; //!< packet level - used to select set of packets to send
|
NATIVE_UINT_TYPE level; //!< packet level - used to select set of packets to send
|
||||||
NATIVE_UINT_TYPE numEntries; //!< number of channels in packet
|
NATIVE_UINT_TYPE numEntries; //!< number of channels in packet
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TlmPacketizerPacketList {
|
struct TlmPacketizerPacketList {
|
||||||
const TlmPacketizerPacket* list[MAX_PACKETIZER_PACKETS]; //!<
|
const TlmPacketizerPacket* list[MAX_PACKETIZER_PACKETS]; //!<
|
||||||
NATIVE_UINT_TYPE numEntries;
|
NATIVE_UINT_TYPE numEntries;
|
||||||
};
|
};
|
||||||
}
|
} // namespace Svc
|
||||||
|
|
||||||
#endif /* SVC_TLMPACKETIZER_TLMPACKETIZERTYPES_HPP_ */
|
#endif /* SVC_TLMPACKETIZER_TLMPACKETIZERTYPES_HPP_ */
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -16,135 +16,121 @@
|
|||||||
|
|
||||||
namespace Svc {
|
namespace Svc {
|
||||||
|
|
||||||
class Tester :
|
class Tester : public TlmPacketizerGTestBase {
|
||||||
public TlmPacketizerGTestBase
|
// ----------------------------------------------------------------------
|
||||||
{
|
// Construction and destruction
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
public:
|
||||||
// Construction and destruction
|
//! Construct object Tester
|
||||||
// ----------------------------------------------------------------------
|
//!
|
||||||
|
Tester(void);
|
||||||
|
|
||||||
public:
|
//! Destroy object Tester
|
||||||
|
//!
|
||||||
|
~Tester(void);
|
||||||
|
|
||||||
//! Construct object Tester
|
public:
|
||||||
//!
|
// ----------------------------------------------------------------------
|
||||||
Tester(void);
|
// Tests
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
//! Destroy object Tester
|
//! Initialization test
|
||||||
//!
|
//!
|
||||||
~Tester(void);
|
void initTest(void);
|
||||||
|
|
||||||
public:
|
//! push telemetry test
|
||||||
|
//!
|
||||||
|
void pushTlmTest(void);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
//! send packets test
|
||||||
// Tests
|
//!
|
||||||
// ----------------------------------------------------------------------
|
void sendPacketsTest(void);
|
||||||
|
|
||||||
//! Initialization test
|
//! send packets with levels test
|
||||||
//!
|
//!
|
||||||
void initTest(void);
|
void sendPacketLevelsTest(void);
|
||||||
|
|
||||||
//! push telemetry test
|
//! update packets test
|
||||||
//!
|
//!
|
||||||
void pushTlmTest(void);
|
void updatePacketsTest(void);
|
||||||
|
|
||||||
//! send packets test
|
//! non-packetized channel test
|
||||||
//!
|
//!
|
||||||
void sendPacketsTest(void);
|
void nonPacketizedChannelTest(void);
|
||||||
|
|
||||||
//! send packets with levels test
|
//! ping test
|
||||||
//!
|
//!
|
||||||
void sendPacketLevelsTest(void);
|
void pingTest(void);
|
||||||
|
|
||||||
//! update packets test
|
//! ignore test
|
||||||
//!
|
//!
|
||||||
void updatePacketsTest(void);
|
void ignoreTest(void);
|
||||||
|
|
||||||
//! non-packetized channel test
|
//! manually send packet test
|
||||||
//!
|
//!
|
||||||
void nonPacketizedChannelTest(void);
|
void sendManualPacketTest(void);
|
||||||
|
|
||||||
//! ping test
|
//! set packet level test
|
||||||
//!
|
//!
|
||||||
void pingTest(void);
|
void setPacketLevelTest(void);
|
||||||
|
|
||||||
//! ignore test
|
private:
|
||||||
//!
|
// ----------------------------------------------------------------------
|
||||||
void ignoreTest(void);
|
// Handlers for typed from ports
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
//! manually send packet test
|
//! Handler for from_Time
|
||||||
//!
|
//!
|
||||||
void sendManualPacketTest(void);
|
void from_Time_handler(const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
||||||
|
Fw::Time& time /*!< The U32 cmd argument*/
|
||||||
|
);
|
||||||
|
|
||||||
//! set packet level test
|
//! Handler for from_PktSend
|
||||||
//!
|
//!
|
||||||
void setPacketLevelTest(void);
|
void from_PktSend_handler(const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
||||||
|
Fw::ComBuffer& data, /*!< Buffer containing packet data*/
|
||||||
|
U32 context /*!< Call context value; meaning chosen by user*/
|
||||||
|
);
|
||||||
|
|
||||||
private:
|
//! Handler for from_pingOut
|
||||||
|
//!
|
||||||
|
void from_pingOut_handler(const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
||||||
|
U32 key /*!< Value to return to pinger*/
|
||||||
|
);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
virtual void textLogIn(const FwEventIdType id, /*!< The event ID*/
|
||||||
// Handlers for typed from ports
|
Fw::Time& timeTag, /*!< The time*/
|
||||||
// ----------------------------------------------------------------------
|
const Fw::LogSeverity severity, /*!< The severity*/
|
||||||
|
const Fw::TextLogString& text /*!< The event string*/
|
||||||
|
);
|
||||||
|
|
||||||
//! Handler for from_Time
|
private:
|
||||||
//!
|
// ----------------------------------------------------------------------
|
||||||
void from_Time_handler(
|
// Helper methods
|
||||||
const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
// ----------------------------------------------------------------------
|
||||||
Fw::Time &time /*!< The U32 cmd argument*/
|
|
||||||
);
|
|
||||||
|
|
||||||
//! Handler for from_PktSend
|
//! Connect ports
|
||||||
//!
|
//!
|
||||||
void from_PktSend_handler(
|
void connectPorts(void);
|
||||||
const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
|
||||||
Fw::ComBuffer &data, /*!< Buffer containing packet data*/
|
|
||||||
U32 context /*!< Call context value; meaning chosen by user*/
|
|
||||||
);
|
|
||||||
|
|
||||||
//! Handler for from_pingOut
|
//! Initialize components
|
||||||
//!
|
//!
|
||||||
void from_pingOut_handler(
|
void initComponents(void);
|
||||||
const NATIVE_INT_TYPE portNum, /*!< The port number*/
|
|
||||||
U32 key /*!< Value to return to pinger*/
|
|
||||||
);
|
|
||||||
|
|
||||||
virtual void textLogIn(
|
private:
|
||||||
const FwEventIdType id, /*!< The event ID*/
|
// ----------------------------------------------------------------------
|
||||||
Fw::Time& timeTag, /*!< The time*/
|
// Variables
|
||||||
const Fw::LogSeverity severity, /*!< The severity*/
|
// ----------------------------------------------------------------------
|
||||||
const Fw::TextLogString& text /*!< The event string*/
|
|
||||||
);
|
|
||||||
|
|
||||||
|
//! The component under test
|
||||||
|
//!
|
||||||
|
TlmPacketizer component;
|
||||||
|
|
||||||
private:
|
Fw::Time m_testTime; //!< store test time for packets
|
||||||
|
bool m_timeSent; //!< flag when time was sent
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
} // end namespace Svc
|
||||||
// Helper methods
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
//! Connect ports
|
|
||||||
//!
|
|
||||||
void connectPorts(void);
|
|
||||||
|
|
||||||
//! Initialize components
|
|
||||||
//!
|
|
||||||
void initComponents(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// Variables
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
//! The component under test
|
|
||||||
//!
|
|
||||||
TlmPacketizer component;
|
|
||||||
|
|
||||||
Fw::Time m_testTime; //!< store test time for packets
|
|
||||||
bool m_timeSent; //!< flag when time was sent
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace Svc
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -3,64 +3,55 @@
|
|||||||
// ALL RIGHTS RESERVED. United States Government Sponsorship
|
// ALL RIGHTS RESERVED. United States Government Sponsorship
|
||||||
// acknowledged.
|
// acknowledged.
|
||||||
|
|
||||||
|
|
||||||
#include "Tester.hpp"
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <Fw/Test/UnitTest.hpp>
|
#include <Fw/Test/UnitTest.hpp>
|
||||||
|
#include "Tester.hpp"
|
||||||
|
|
||||||
TEST(TestNominal,Initialization) {
|
TEST(TestNominal, Initialization) {
|
||||||
|
TEST_CASE(100.1.1, "Initialization");
|
||||||
TEST_CASE(100.1.1,"Initialization");
|
|
||||||
Svc::Tester tester;
|
Svc::Tester tester;
|
||||||
tester.initTest();
|
tester.initTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(TestNominal, PushTlm) {
|
||||||
TEST(TestNominal,PushTlm) {
|
TEST_CASE(100.1.2, "Push Telemetry");
|
||||||
|
|
||||||
TEST_CASE(100.1.2,"Push Telemetry");
|
|
||||||
Svc::Tester tester;
|
Svc::Tester tester;
|
||||||
tester.pushTlmTest();
|
tester.pushTlmTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TestNominal,SendPackets) {
|
TEST(TestNominal, SendPackets) {
|
||||||
|
TEST_CASE(100.1.2, "Send Packets");
|
||||||
TEST_CASE(100.1.2,"Send Packets");
|
|
||||||
Svc::Tester tester;
|
Svc::Tester tester;
|
||||||
tester.sendPacketsTest();
|
tester.sendPacketsTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
//TEST(TestNominal,SendPacketLevels) {
|
// TEST(TestNominal,SendPacketLevels) {
|
||||||
//
|
//
|
||||||
// TEST_CASE(100.1.3,"Send Packets with levels");
|
// TEST_CASE(100.1.3,"Send Packets with levels");
|
||||||
// Svc::Tester tester;
|
// Svc::Tester tester;
|
||||||
// tester.sendPacketLevelsTest();
|
// tester.sendPacketLevelsTest();
|
||||||
//}
|
// }
|
||||||
|
|
||||||
TEST(TestNominal,UpdatePacketsTest) {
|
TEST(TestNominal, UpdatePacketsTest) {
|
||||||
|
TEST_CASE(100.1.4, "Update Packets");
|
||||||
TEST_CASE(100.1.4,"Update Packets");
|
|
||||||
Svc::Tester tester;
|
Svc::Tester tester;
|
||||||
tester.updatePacketsTest();
|
tester.updatePacketsTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TestNominal,PingTest) {
|
TEST(TestNominal, PingTest) {
|
||||||
|
TEST_CASE(100.1.5, "Ping");
|
||||||
TEST_CASE(100.1.5,"Ping");
|
|
||||||
Svc::Tester tester;
|
Svc::Tester tester;
|
||||||
tester.pingTest();
|
tester.pingTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TestNominal,IgnoredChannelTest) {
|
TEST(TestNominal, IgnoredChannelTest) {
|
||||||
|
TEST_CASE(100.1.6, "Ignored Channels");
|
||||||
TEST_CASE(100.1.6,"Ignored Channels");
|
|
||||||
Svc::Tester tester;
|
Svc::Tester tester;
|
||||||
tester.ignoreTest();
|
tester.ignoreTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TestNominal,SendPacketTest) {
|
TEST(TestNominal, SendPacketTest) {
|
||||||
|
TEST_CASE(100.1.7, "Manually sent packets");
|
||||||
TEST_CASE(100.1.7,"Manually sent packets");
|
|
||||||
Svc::Tester tester;
|
Svc::Tester tester;
|
||||||
tester.sendManualPacketTest();
|
tester.sendManualPacketTest();
|
||||||
}
|
}
|
||||||
@ -72,9 +63,8 @@ TEST(TestNominal,SetPacketLevelTest) {
|
|||||||
tester.setPacketLevelTest();
|
tester.setPacketLevelTest();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
TEST(TestOffNominal,NonPacketizedChannelTest) {
|
TEST(TestOffNominal, NonPacketizedChannelTest) {
|
||||||
|
TEST_CASE(100.2.1, "Non-packetized Channels");
|
||||||
TEST_CASE(100.2.1,"Non-packetized Channels");
|
|
||||||
Svc::Tester tester;
|
Svc::Tester tester;
|
||||||
tester.nonPacketizedChannelTest();
|
tester.nonPacketizedChannelTest();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,6 +69,7 @@ register_fprime_target(target/fpp_locs)
|
|||||||
register_fprime_target(target/build)
|
register_fprime_target(target/build)
|
||||||
register_fprime_build_autocoder(autocoder/fpp)
|
register_fprime_build_autocoder(autocoder/fpp)
|
||||||
register_fprime_build_autocoder(autocoder/ai_xml)
|
register_fprime_build_autocoder(autocoder/ai_xml)
|
||||||
|
register_fprime_build_autocoder(autocoder/packets)
|
||||||
register_fprime_target(target/noop)
|
register_fprime_target(target/noop)
|
||||||
register_fprime_target(target/version)
|
register_fprime_target(target/version)
|
||||||
register_fprime_target(target/dict)
|
register_fprime_target(target/dict)
|
||||||
|
|||||||
63
cmake/autocoder/packets.cmake
Normal file
63
cmake/autocoder/packets.cmake
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
####
|
||||||
|
# autocoder/packets.cmake
|
||||||
|
#
|
||||||
|
# Packets autocoder.
|
||||||
|
#####
|
||||||
|
include(utilities)
|
||||||
|
include(autocoder/helpers)
|
||||||
|
include(autocoder/ai-shared)
|
||||||
|
|
||||||
|
set(PACKETS_AUTOCODER_SCRIPT "${FPRIME_FRAMEWORK_PATH}/Autocoders/Python/bin/tlm_packet_gen.py")
|
||||||
|
|
||||||
|
autocoder_setup_for_individual_sources()
|
||||||
|
####
|
||||||
|
# `packets_is_supported`:
|
||||||
|
#
|
||||||
|
# Required function, processes Ai.xml files.
|
||||||
|
# `AC_INPUT_FILE` potential input to the autocoder
|
||||||
|
# ...: any number of arguments representing a list of previously generated files
|
||||||
|
####
|
||||||
|
function(packets_is_supported AC_INPUT_FILE)
|
||||||
|
autocoder_support_by_suffix("Packets.xml" "${AC_INPUT_FILE}" TRUE)
|
||||||
|
endfunction (packets_is_supported)
|
||||||
|
|
||||||
|
####
|
||||||
|
# `determine_topology_files`:
|
||||||
|
#
|
||||||
|
# Get topology determined from packet file.
|
||||||
|
####
|
||||||
|
function(determine_topology_files AC_INPUT_FILE)
|
||||||
|
file(READ "${AC_INPUT_FILE}" FILE_CONTENTS)
|
||||||
|
string(REGEX REPLACE ".*<import_topology>([^>]*)</import_topology>.*" "\\1" TOPOLOGY_FILE "${FILE_CONTENTS}")
|
||||||
|
# This will work as long as the topology ai file is not part of the fprime core "library" code
|
||||||
|
set(FULL_TOPOLOGY_FILE "${CMAKE_BINARY_DIR}/${TOPOLOGY_FILE}" PARENT_SCOPE)
|
||||||
|
endfunction(determine_topology_files)
|
||||||
|
|
||||||
|
####
|
||||||
|
# `packets_setup_autocode`:
|
||||||
|
#
|
||||||
|
# Required function, sets up a custom command to produce Ac.hpp and Ac.cpp files.
|
||||||
|
####
|
||||||
|
function(packets_setup_autocode AC_INPUT_FILE)
|
||||||
|
determine_topology_files("${AC_INPUT_FILE}")
|
||||||
|
get_filename_component(AC_INPUT_FILE_NO_PATH "${AC_INPUT_FILE}" NAME)
|
||||||
|
|
||||||
|
string(REPLACE ";" ":" FPRIME_BUILD_LOCATIONS_SEP "${FPRIME_BUILD_LOCATIONS}")
|
||||||
|
string(REPLACE "Packets.xml" "PacketsAc.cpp" CPP_FILE "${AC_INPUT_FILE_NO_PATH}")
|
||||||
|
string(REPLACE "Packets.xml" "PacketsAc.hpp" HPP_FILE "${AC_INPUT_FILE_NO_PATH}")
|
||||||
|
|
||||||
|
set(GENERATED_FILES
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${CPP_FILE}"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${HPP_FILE}"
|
||||||
|
)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${GENERATED_FILES}
|
||||||
|
COMMAND
|
||||||
|
PYTHONPATH=${PYTHON_AUTOCODER_DIR}/src:${PYTHON_AUTOCODER_DIR}/utils
|
||||||
|
BUILD_ROOT=${FPRIME_BUILD_LOCATIONS_SEP}:${CMAKE_BINARY_DIR}:${CMAKE_BINARY_DIR}/F-Prime
|
||||||
|
"${PYTHON}" "${PACKETS_AUTOCODER_SCRIPT}" "${AC_INPUT_FILE}"
|
||||||
|
DEPENDS "${AC_INPUT_FILE}" "${FULL_TOPOLOGY_FILE}"
|
||||||
|
)
|
||||||
|
set(AUTOCODER_GENERATED "${GENERATED_FILES}" PARENT_SCOPE)
|
||||||
|
set(AUTOCODER_DEPENDENCIES "" PARENT_SCOPE)
|
||||||
|
endfunction(packets_setup_autocode)
|
||||||
@ -385,6 +385,22 @@ function (read_from_lines CONTENT)
|
|||||||
endforeach()
|
endforeach()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
####
|
||||||
|
# Function `full_path_from_build_relative_path`:
|
||||||
|
#
|
||||||
|
# Creates a full path from the shortened build-relative path.
|
||||||
|
# -**SHORT_PATH:** build relative path
|
||||||
|
# Return: full path from relative path
|
||||||
|
####
|
||||||
|
function(full_path_from_build_relative_path SHORT_PATH OUTPUT_VARIABLE)
|
||||||
|
foreach(FPRIME_LOCATION IN LISTS FPRIME_BUILD_LOCATIONS)
|
||||||
|
if (EXISTS "${FPRIME_LOCATION}/${SHORT_PATH}")
|
||||||
|
set("${OUTPUT_VARIABLE}" "${FPRIME_LOCATION}/${SHORT_PATH}" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
set("${OUTPUT_VARIABLE}" "" PARENT_SCOPE)
|
||||||
|
endfunction(full_path_from_build_relative_path)
|
||||||
|
|
||||||
####
|
####
|
||||||
# Function `get_nearest_build_root`:
|
# Function `get_nearest_build_root`:
|
||||||
|
|||||||
43
config/TlmPacketizerCfg.hpp
Normal file
43
config/TlmPacketizerCfg.hpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* TlmPacketizerComponentImplCfg.hpp
|
||||||
|
*
|
||||||
|
* Created on: Dec 10, 2017
|
||||||
|
* Author: tim
|
||||||
|
*/
|
||||||
|
|
||||||
|
// \copyright
|
||||||
|
// Copyright 2009-2015, by the California Institute of Technology.
|
||||||
|
// ALL RIGHTS RESERVED. United States Government Sponsorship
|
||||||
|
// acknowledged.
|
||||||
|
|
||||||
|
#ifndef SVC_TLMPACKETIZER_TLMPACKETIZERCOMPONENTIMPLCFG_HPP_
|
||||||
|
#define SVC_TLMPACKETIZER_TLMPACKETIZERCOMPONENTIMPLCFG_HPP_
|
||||||
|
|
||||||
|
#include <FpConfig.hpp>
|
||||||
|
|
||||||
|
namespace Svc {
|
||||||
|
static const NATIVE_UINT_TYPE MAX_PACKETIZER_PACKETS = 200;
|
||||||
|
static const NATIVE_UINT_TYPE TLMPACKETIZER_NUM_TLM_HASH_SLOTS =
|
||||||
|
15; // !< Number of slots in the hash table.
|
||||||
|
// Works best when set to about twice the number of components producing telemetry
|
||||||
|
static const NATIVE_UINT_TYPE TLMPACKETIZER_HASH_MOD_VALUE =
|
||||||
|
99; // !< The modulo value of the hashing function.
|
||||||
|
// Should be set to a little below the ID gaps to spread the entries around
|
||||||
|
|
||||||
|
static const NATIVE_UINT_TYPE TLMPACKETIZER_HASH_BUCKETS =
|
||||||
|
1000; // !< Buckets assignable to a hash slot.
|
||||||
|
// Buckets must be >= number of telemetry channels in system
|
||||||
|
static const NATIVE_UINT_TYPE TLMPACKETIZER_MAX_MISSING_TLM_CHECK =
|
||||||
|
25; // !< Maximum number of missing telemetry channel checks
|
||||||
|
|
||||||
|
// packet update mode
|
||||||
|
enum PacketUpdateMode {
|
||||||
|
PACKET_UPDATE_ALWAYS, // Always send packets, even if no changes to channel data
|
||||||
|
PACKET_UPDATE_ON_CHANGE, // Only send packets if any of the channels updates
|
||||||
|
PACKET_UPDATE_AFTER_FIRST_CHANGE, // Always send packets, but only after first channel has been updated
|
||||||
|
};
|
||||||
|
|
||||||
|
static const PacketUpdateMode PACKET_UPDATE_MODE = PACKET_UPDATE_ON_CHANGE;
|
||||||
|
} // namespace Svc
|
||||||
|
|
||||||
|
#endif /* SVC_TLMPACKETIZER_TLMPACKETIZERCOMPONENTIMPLCFG_HPP_ */
|
||||||
@ -14,8 +14,8 @@ Flask==1.1.4
|
|||||||
Flask-Compress==1.12
|
Flask-Compress==1.12
|
||||||
Flask-RESTful==0.3.9
|
Flask-RESTful==0.3.9
|
||||||
fprime-fpp==1.1.0
|
fprime-fpp==1.1.0
|
||||||
fprime-gds==3.1.4
|
fprime-gds==3.1.5a1
|
||||||
fprime-tools==3.1.1
|
fprime-tools==3.1.2a1
|
||||||
gcovr==5.1
|
gcovr==5.1
|
||||||
idna==3.3
|
idna==3.3
|
||||||
importlib-metadata==4.11.4
|
importlib-metadata==4.11.4
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user