diff --git a/pylink/__main__.py b/pylink/__main__.py index 8d60002..0ba5b09 100644 --- a/pylink/__main__.py +++ b/pylink/__main__.py @@ -17,8 +17,11 @@ import argparse import logging import os -import six import sys +try: + from six.moves import with_metaclass +except (AttributeError, ImportError): + from six import with_metaclass class CommandMeta(type): @@ -49,7 +52,7 @@ def __new__(cls, name, parents, dct): return newClass -class Command(six.with_metaclass(CommandMeta)): +class Command(with_metaclass(CommandMeta)): """Base command-class. All commands should inherit from this class. diff --git a/pylink/enums.py b/pylink/enums.py index 27b23af..ec8914e 100644 --- a/pylink/enums.py +++ b/pylink/enums.py @@ -722,3 +722,28 @@ class JLinkRTTDirection(object): """RTT Direction.""" UP = 0 DOWN = 1 + + +class JLinkPowerTraceCommand(object): + """Power trace commands.""" + SETUP = 0 + START = 1 + FLUSH = 2 + STOP = 3 + GET_CAPS = 4 + GET_CHANNEL_CAPS = 5 + GET_NUM_ITEMS = 6 + + +class JLinkPowerTraceRef(object): + """Reference values to store on power trace capture. + + Attributes: + NONE: No reference value is stored. + BYTES: Number of bytes transferred via SWO is stored since capturing + started. + TIME: Number of milliseconds since capturing started. + """ + NONE = 0 + BYTES = 1 + TIME = 2 diff --git a/pylink/jlink.py b/pylink/jlink.py index ab22b9d..2db289d 100644 --- a/pylink/jlink.py +++ b/pylink/jlink.py @@ -5250,3 +5250,221 @@ def cp15_register_write(self, cr_n, op_1, cr_m, op_2, value): if res != 0: raise errors.JLinkException(res) return res + +############################################################################### +# +# Power API +# +############################################################################### + @open_required + def power_trace_configure(self, channels, freq, ref, always): + """Configures power tracing. + + This method must be called before calling the other power trace APIs. It + is the responsibility of the calling application code to keep track of + which channels were enabled in order to determine which trace samples + correspond to which channels when read. + + Args: + self (JLink): the ``JLink`` instance. + channels (list[int]): list specifying which channels to capture on (0 - 7). + freq (int): sampling frequency (in Hertz). + ref (JLinkPowerTraceRef): reference value to stored on capture. + always (bool): ``True`` to capture data even while CPU halted, otherwise ``False``. + + Returns: + The sampling frequency (in Hz) for power sampling. + + Raises: + JLinkException: on error + ValueError: invalid channels specified + """ + if isinstance(channels, list): + channel_mask = 0x00 + for channel in channels: + channel_mask |= (1 << channel) + else: + channel_mask = channels + + if channel_mask > 0xFF: + raise ValueError("Channels must be in range 0 - 7") + + setup = structs.JLinkPowerTraceSetup() + setup.ChannelMask = channel_mask + setup.SampleFreq = int(freq) + setup.RefSelect = int(ref) + setup.EnableCond = 0 if always else 1 + + res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.SETUP, ctypes.byref(setup), 0) + if res < 0: + raise errors.JLinkException(res) + return res + + @open_required + def power_trace_start(self): + """Starts capturing data on the channels enabled via ``power_trace_configure()``. + + Args: + self (JLink): the ``JLink`` instance. + + Returns: + ``None`` + + Raises: + JLinkException: on error + """ + res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.START, 0, 0) + if res < 0: + raise errors.JLinkException(res) + + @open_required + def power_trace_stop(self): + """Stops a capture started by ``power_trace_start()``. + + Args: + self (JLink): the ``JLink`` instance. + + Returns: + ``None`` + + Raises: + JLinkException: on error + """ + res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.STOP, 0, 0) + if res < 0: + raise errors.JLinkException(res) + + @open_required + def power_trace_flush(self): + """Flushes all capture data. + + Any data that has not been read by ``power_trace_read()`` is dropped. + + Args: + self (JLink): the ``JLink`` instance. + + Returns: + ``None`` + + Raises: + JLinkException: on error + """ + res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.FLUSH, 0, 0) + if res < 0: + raise errors.JLinkException(res) + + @open_required + def power_trace_get_channels(self): + """Returns a list of the available channels for power tracing. + + This method returns a list of the available channels for power tracing. + The application code can use this to determine which channels to + enable for tracing. + + Args: + self (JLink): the ``JLink`` instance. + + Returns: + List of available channel identifiers. + + Raises: + JLinkException: on error + """ + caps = structs.JLinkPowerTraceCaps() + res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.GET_CAPS, 0, ctypes.byref(caps)) + if res < 0: + raise errors.JLinkException(res) + + return [i for i in range(0, 32) if (caps.ChannelMask >> i) & 0x1] + + @open_required + def power_trace_get_channel_capabilities(self, channels): + """Returns the capabilities for the specified channels. + + Args: + self (JLink): the ``JLink`` instance. + channels (list[int]): list specifying which channels to get capabilities for. + + Returns: + Channel capabilities. + + Raises: + JLinkException: on error + ValueError: invalid channels specified + """ + if isinstance(channels, list): + channel_mask = 0x00 + for channel in channels: + channel_mask |= (1 << channel) + else: + channel_mask = channels + + if channel_mask > 0xFF: + raise ValueError("Channels must be in range 0 - 7") + + channel_caps = structs.JLinkPowerTraceChannelCaps() + caps = structs.JLinkPowerTraceCaps() + caps.ChannelMask = channel_mask + + res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.GET_CHANNEL_CAPS, + ctypes.byref(caps), + ctypes.byref(channel_caps)) + if res < 0: + raise errors.JLinkException(res) + + return channel_caps + + @open_required + def power_trace_get_num_items(self): + """Returns a count of the number of items in the power trace buffer. + + Since each channel is sampled simulataneously, the count of number of + items per channel is the return value of this function divided by the + number of active channels. + + Args: + self (JLink): the ``JLink`` instance. + + Returns: + Number of items in the power trace buffer. + + Raises: + JLinkException: on error + """ + res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.GET_NUM_ITEMS, 0, 0) + if res < 0: + raise errors.JLinkException(res) + return res + + @open_required + def power_trace_read(self, num_items=None): + """Reads data from the power trace buffer. + + Any read data is flushed from the power trace buffer. + + Args: + self (JLink): the ``JLink`` instance. + num_items (int): the number of items to read (if not specified, reads all). + + Returns: + List of ``JLinkPowerTraceItem``s. + + Raises: + JLinkException: on error + """ + if num_items is None: + num_items = self.power_trace_get_num_items() + + items = [] + if num_items < 0: + raise ValueError("Invalid number of items requested, expected > 0, given %d" % num_items) + elif num_items > 0: + items = (structs.JLinkPowerTraceItem * num_items)() + res = self._dll.JLINK_POWERTRACE_Read(ctypes.byref(items), num_items) + if res < 0: + raise errors.JLinkException(res) + + # Number of items may be less than the requested count, so clip the + # array here. + items = list(items)[:res] + return items diff --git a/pylink/structs.py b/pylink/structs.py index 51bbc23..d1b0d71 100644 --- a/pylink/structs.py +++ b/pylink/structs.py @@ -1261,3 +1261,210 @@ def __str__(self): return 'Status ' % (self.NumUpBuffers, self.NumDownBuffers, self.IsRunning) + + +class JLinkPowerTraceSetup(ctypes.Structure): + """Structure used to setup the power tracing. + + Attributes: + SizeOfStruct: Size of the struct (DO NOT CHANGE). + ChannelMask: Bitmask indicating which channels to enable for capturing. + SampleFreq: Sampling frequency in Hertz. + RefSelect: Identifier of the reference value stored with every trace + (see ``enums.JLinkPowerTraceRef``). + EnableCond: `1` is tracing is only captured when CPU is running. + """ + _fields_ = [ + ('SizeOfStruct', ctypes.c_int32), + ('ChannelMask', ctypes.c_uint32), + ('SampleFreq', ctypes.c_uint32), + ('RefSelect', ctypes.c_int32), + ('EnableCond', ctypes.c_int32) + ] + + def __init__(self): + """Initializes the ``JLinkPowerTraceSetup`` instance. + + Sets the size of the structure. + + Args: + self (JLinkPowerTraceSetup): the power trace instance. + + Returns: + ``None`` + """ + super(JLinkPowerTraceSetup, self).__init__() + self.SizeOfStruct = ctypes.sizeof(self) + + def __repr__(self): + """Returns a string representation of the instance. + + Args: + self (JLinkPowerTraceSetup): the ``JLinkPowerTraceSetup`` instance + + Returns: + String representation of the instance. + """ + return self.__str__() + + def __str__(self): + """Returns this instance formatted as a string. + + Args: + self (JLinkPowerTraceSetup): the ``JLinkPowerTraceSetup`` instance + + Returns: + String formatted instance. + """ + return '%s(Channel Mask=%s, Freq=%uHz)' % (self.__class__.__name__, bin(self.ChannelMask), self.SampleFreq) + + +class JLinkPowerTraceItem(ctypes.Structure): + """Structure used to represent a stored power trace item. + + Attributes: + RefValue: the stored reference value. + Value: the actual recorded trace value. + """ + _fields_ = [ + ('RefValue', ctypes.c_uint32), + ('Value', ctypes.c_uint32) + ] + + def __repr__(self): + """Returns a string representation of the instance. + + Args: + self (JLinkPowerTraceItem): the ``JLinkPowerTraceItem`` instance + + Returns: + String representation of the instance. + """ + return self.__str__() + + def __str__(self): + """Returns this instance formatted as a string. + + Args: + self (JLinkPowerTraceItem): the ``JLinkPowerTraceItem`` instance + + Returns: + String formatted instance. + """ + return '%s(Value=%u, Reference=%u)' % (self.__class__.__name__, self.Value, self.RefValue) + + +class JLinkPowerTraceCaps(ctypes.Structure): + """Structure used to retrieve or specify available power tracing channels. + + Attributes: + SizeOfStruct: the size of this structure (in bytes). + ChannelMask: bitmask of available channels. + """ + _fields_ = [ + ('SizeOfStruct', ctypes.c_int32), + ('ChannelMask', ctypes.c_uint32) + ] + + def __init__(self): + """Initializes the ``JLinkPowerTraceCaps`` instance. + + Sets the size of the structure. + + Args: + self (JLinkPowerTraceCaps): the power trace caps instance. + + Returns: + ``None`` + """ + super(JLinkPowerTraceCaps, self).__init__() + self.SizeOfStruct = ctypes.sizeof(self) + + def __repr__(self): + """Returns a string representation of the instance. + + Args: + self (JLinkPowerTraceCaps): the caps instance. + + Returns: + String representation of the instance. + """ + return self.__str__() + + def __str__(self): + """Returns this instance formatted as a string. + + Args: + self (JLinkPowerTraceCaps): the caps instance. + + Returns: + String formatted instance. + """ + return '%s(Channel Mask=%s)' % (self.__class__.__name__, bin(self.ChannelMask)) + + +class JLinkPowerTraceChannelCaps(ctypes.Structure): + """Structure representing the capabilities for the queried channels. + + Attributes: + SizeOfStruct: the size of this structure (in bytes). + BaseSampleFreq: the base sampling frequeny (in Hertz). + MinDiv: the minimum divider of the base sampling frequency. + """ + _fields_ = [ + ('SizeOfStruct', ctypes.c_int32), + ('BaseSampleFreq', ctypes.c_uint32), + ('MinDiv', ctypes.c_uint32) + ] + + def __init__(self): + """Initializes the ``JLinkPowerTraceChannelCaps`` instance. + + Sets the size of the structure. + + Args: + self (JLinkPowerTraceChannelCaps): the channel capabilities. + + Returns: + ``None`` + """ + super(JLinkPowerTraceChannelCaps, self).__init__() + self.SizeOfStruct = ctypes.sizeof(self) + + @property + def max_sample_freq(self): + """Returns the maximum sample frequency that can be used. + + The maximum sampling frequency is the largest frequency that can be + specified when configuring power tracing, and is computed based on the + minimum divider and base sampling frequency. + + Args: + self (JLinkPowerTraceChannelCaps): the channel capabilities. + + Returns: + ``float`` + """ + return (self.BaseSampleFreq * 1.0) / self.MinDiv + + def __repr__(self): + """Returns a string representation of the instance. + + Args: + self (JLinkPowerTraceChannelCaps): the channel capabilities. + + Returns: + String representation of the instance. + """ + return self.__str__() + + def __str__(self): + """Returns this instance formatted as a string. + + Args: + self (JLinkPowerTraceChannelCaps): the channel capabilities. + + Returns: + String formatted instance. + """ + return '%s(SampleFreq=%uHz, MinDiv=%u)' % (self.__class__.__name__, self.BaseSampleFreq, self.MinDiv) diff --git a/tests/unit/test_jlink.py b/tests/unit/test_jlink.py index f5f0dce..4543c60 100644 --- a/tests/unit/test_jlink.py +++ b/tests/unit/test_jlink.py @@ -27,6 +27,7 @@ except ImportError: import io as StringIO import ctypes +import functools import itertools import unittest @@ -6163,6 +6164,7 @@ def test_cp15_present_returns_true(self): """Tests that cp15_present returns ``True`` when CP15_IsPresent returns a value different from 0 and ``False`` when CP15_IsPresent returns a value equal to 0. + Args: self (TestJLink): the ``TestJLink`` instance @@ -6177,6 +6179,7 @@ def test_cp15_present_returns_true(self): def test_cp15_register_read_returns_result_from_JLINKARM_CP15_ReadEx(self): """Tests that cp15_register_read returns whatever value CP15_ReadEx returns. + Args: self (TestJLink): the ``TestJLink`` instance @@ -6196,6 +6199,7 @@ def read_data(cr_n, cr_m, op_1, op_2, value): def test_cp15_register_read_raises_exception_if_CP15_ReadEx_fails(self): """Tests that cp15_register_read raises a JLinkException on failure. + Args: self (TestJLink): the ``TestJLink`` instance @@ -6208,6 +6212,7 @@ def test_cp15_register_read_raises_exception_if_CP15_ReadEx_fails(self): def test_cp15_register_write_success(self): """Tests that cp15_register_write uses provided parameters. + Args: self (TestJLink): the ``TestJLink`` instance @@ -6250,6 +6255,7 @@ def test_set_log_file_success(self): def test_set_log_file_raises_exception_if_SetLogFile_fails(self): """Tests that set_log_file raises a JLinkException on failure. + Args: self (TestJLink): the ``TestJLink`` instance @@ -6279,6 +6285,7 @@ def test_set_script_file_success(self): def test_set_script_file_raises_exception_if_exec_command_fails(self): """Tests that set_script_file raises a JLinkException on failure. + Args: self (TestJLink): the ``TestJLink`` instance @@ -6290,6 +6297,242 @@ def test_set_script_file_raises_exception_if_exec_command_fails(self): with self.assertRaises(JLinkException): self.jlink.set_script_file('my/file/path') + def test_power_trace_configure(self): + """Tests configuring power trace. + + Args: + self (TestJLink): the ``TestJLink`` instance + + Returns: + ``None`` + """ + channel_mask = 0x3E + freq = 400 + expected_freq = 500 + + def _powertrace_control(command, in_ptr, out_ptr): + self.assertEqual(enums.JLinkPowerTraceCommand.SETUP, command) + self.assertEqual(0, out_ptr) + + setup = ctypes.cast(in_ptr, ctypes.POINTER(structs.JLinkPowerTraceSetup))[0] + self.assertEqual(channel_mask, setup.ChannelMask) + self.assertEqual(freq, setup.SampleFreq) + self.assertEqual(0, setup.RefSelect) + self.assertEqual(0, setup.EnableCond) + + return expected_freq + + self.dll.JLINK_POWERTRACE_Control.side_effect = _powertrace_control + self.assertEqual(expected_freq, self.jlink.power_trace_configure([1, 2, 3, 4, 5], 400, 0, True)) + + def test_power_trace_start(self): + """Tests starting power trace. + + Args: + self (TestJLink): the ``TestJLink`` instance + + Returns: + ``None`` + """ + def _powertrace_control(command, in_ptr, out_ptr): + self.assertEqual(enums.JLinkPowerTraceCommand.START, command) + self.assertEqual(0, in_ptr) + self.assertEqual(0, out_ptr) + self.dll.JLINK_POWERTRACE_Control.side_effect = [-1] + return 0 + + self.dll.JLINK_POWERTRACE_Control.side_effect = _powertrace_control + + self.assertEqual(None, self.jlink.power_trace_start()) + + with self.assertRaises(JLinkException): + self.jlink.power_trace_start() + + def test_power_trace_stop(self): + """Tests stopping power trace. + + Args: + self (TestJLink): the ``TestJLink`` instance + + Returns: + ``None`` + """ + def _powertrace_control(command, in_ptr, out_ptr): + self.assertEqual(enums.JLinkPowerTraceCommand.STOP, command) + self.assertEqual(0, in_ptr) + self.assertEqual(0, out_ptr) + self.dll.JLINK_POWERTRACE_Control.side_effect = [-1] + return 0 + + self.dll.JLINK_POWERTRACE_Control.side_effect = _powertrace_control + + self.assertEqual(None, self.jlink.power_trace_stop()) + + with self.assertRaises(JLinkException): + self.jlink.power_trace_stop() + + def test_power_trace_flush(self): + """Tests flushing the power trace buffer. + + Args: + self (TestJLink): the ``TestJLink`` instance + + Returns: + ``None`` + """ + def _powertrace_control(command, in_ptr, out_ptr): + self.assertEqual(enums.JLinkPowerTraceCommand.FLUSH, command) + self.assertEqual(0, in_ptr) + self.assertEqual(0, out_ptr) + self.dll.JLINK_POWERTRACE_Control.side_effect = [-1] + return 0 + + self.dll.JLINK_POWERTRACE_Control.side_effect = _powertrace_control + + self.assertEqual(None, self.jlink.power_trace_flush()) + + with self.assertRaises(JLinkException): + self.jlink.power_trace_flush() + + def test_power_trace_get_channels(self): + """Tests getting the available channels. + + Args: + self (TestJLink): the ``TestJLink`` instance + + Returns: + ``None`` + """ + channel_mask = 0x3E + + def _powertrace_control(command, in_ptr, out_ptr): + self.assertEqual(enums.JLinkPowerTraceCommand.GET_CAPS, command) + self.assertEqual(0, in_ptr) + + caps = ctypes.cast(out_ptr, ctypes.POINTER(structs.JLinkPowerTraceCaps))[0] + caps.ChannelMask = channel_mask + + return 0 + + self.dll.JLINK_POWERTRACE_Control.side_effect = _powertrace_control + + channels = self.jlink.power_trace_get_channels() + self.assertEqual([1, 2, 3, 4, 5], channels) + + def test_power_trace_get_channel_caps(self): + """Tests getting capabilities for the specified channels. + + Args: + self (TestJLink): the ``TestJLink`` instance + + Returns: + ``None`` + """ + channel_mask = 0x3E + sample_freq = 1000 + min_div = 2 + + def _powertrace_control(command, in_ptr, out_ptr): + self.assertEqual(enums.JLinkPowerTraceCommand.GET_CHANNEL_CAPS, command) + + caps = ctypes.cast(in_ptr, ctypes.POINTER(structs.JLinkPowerTraceCaps))[0] + channel_caps = ctypes.cast(out_ptr, ctypes.POINTER(structs.JLinkPowerTraceChannelCaps))[0] + + self.assertEqual(channel_mask, caps.ChannelMask) + + channel_caps.BaseSampleFreq = sample_freq + channel_caps.MinDiv = min_div + + return 0 + + self.dll.JLINK_POWERTRACE_Control.side_effect = _powertrace_control + + channel_caps = self.jlink.power_trace_get_channel_capabilities([1, 2, 3, 4, 5]) + self.assertEqual(sample_freq, channel_caps.BaseSampleFreq) + self.assertEqual(min_div, channel_caps.MinDiv) + self.assertEqual(500, channel_caps.max_sample_freq) + + def test_power_trace_get_num_items(self): + """Tests failing to read the number of items. + + Args: + self (TestJLink): the ``TestJLink`` instance + + Returns: + ``None`` + """ + def _powertrace_control(command, in_ptr, out_ptr): + self.assertEqual(enums.JLinkPowerTraceCommand.GET_NUM_ITEMS, command) + return -1 + + self.dll.JLINK_POWERTRACE_Control.side_effect = _powertrace_control + + with self.assertRaises(JLinkException): + _ = self.jlink.power_trace_get_num_items() + + def test_power_trace_read(self): + """Tests reading power trace data. + + Args: + self (TestJLink): the ``TestJLink`` instance + + Returns: + ``None`` + """ + actual_items = [] + for _ in range(2): + items = [] + for i in range(3): + item = structs.JLinkPowerTraceItem() + item.RefValue = (1 << i) + item.Value = (1 << (i + 1)) + items.append(item) + actual_items.append(items) + + def _powertrace_control(actual_items, command, in_ptr, out_ptr): + self.assertEqual(enums.JLinkPowerTraceCommand.GET_NUM_ITEMS, command) + if actual_items: + return len(actual_items[0]) + return 0 + + def _powertrace_read(actual_items, item_ptr, num_items): + if not actual_items: + return 0 + + to_read = min(len(actual_items[0]), num_items) + read_items = [] + for _ in range(to_read): + read_items.append(actual_items[0].pop(0)) + + if len(actual_items[0]) == 0: + actual_items.pop(0) + + if to_read > 0: + item_array = ctypes.cast(item_ptr, ctypes.POINTER(structs.JLinkPowerTraceItem * num_items))[0] + item_array[:to_read] = read_items + return to_read + + self.dll.JLINK_POWERTRACE_Control.side_effect = functools.partial(_powertrace_control, actual_items) + self.dll.JLINK_POWERTRACE_Read.side_effect = functools.partial(_powertrace_read, actual_items) + + read_items = self.jlink.power_trace_read() + self.assertEqual(3, len(read_items)) + self.assertEqual(1, read_items[0].RefValue) + self.assertEqual(2, read_items[1].RefValue) + self.assertEqual(4, read_items[2].RefValue) + + read_items = self.jlink.power_trace_read(2) + self.assertEqual(2, len(read_items)) + self.assertEqual(1, read_items[0].RefValue) + self.assertEqual(2, read_items[1].RefValue) + + read_items = self.jlink.power_trace_read(100) + self.assertEqual(1, len(read_items)) + self.assertEqual(4, read_items[0].RefValue) + + read_items = self.jlink.power_trace_read(10) + self.assertEqual(0, len(read_items)) + if __name__ == '__main__': unittest.main() diff --git a/tests/unit/test_structs.py b/tests/unit/test_structs.py index 3186db5..8c88338 100644 --- a/tests/unit/test_structs.py +++ b/tests/unit/test_structs.py @@ -464,6 +464,69 @@ def test_jlink_rtt_terminal_stat(self): self.assertEqual('JLinkRTTerminalStatus(NumUpBuffers=3, NumDownBuffers=3)', repr(stat)) self.assertEqual('Status ', str(stat)) + def test_jlink_power_trace_setup(self): + """Validates the ``JLinkPowerTraceSetup`` serializes correctly. + + Args: + self (TestStructs): the ``TestStructs`` instance + + Returns: + ``None`` + """ + setup = structs.JLinkPowerTraceSetup() + setup.ChannelMask = 0x3 + setup.SampleFreq = 1000 + + self.assertEqual(20, setup.SizeOfStruct) + self.assertEqual('JLinkPowerTraceSetup(Channel Mask=0b11, Freq=1000Hz)', repr(setup)) + + def test_jlink_power_trace_item(self): + """Validates the ``JLinkPowerTraceItem`` serializes correctly. + + Args: + self (TestStructs): the ``TestStructs`` instance + + Returns: + ``None`` + """ + item = structs.JLinkPowerTraceItem() + item.RefValue = 0xDEADBEEF + item.Value = 13 + + self.assertEqual('JLinkPowerTraceItem(Value=13, Reference=3735928559)', repr(item)) + + def test_jlink_power_trace_caps(self): + """Validates that the ``JLinkPowerTraceCaps`` serializes correctly. + + Args: + self (TestStructs): the ``TestStructs`` instance + + Returns: + ``None`` + """ + caps = structs.JLinkPowerTraceCaps() + caps.ChannelMask = 0x3 + + self.assertEqual(8, caps.SizeOfStruct) + self.assertEqual('JLinkPowerTraceCaps(Channel Mask=0b11)', repr(caps)) + + def test_jlink_power_trace_channel_caps(self): + """Validates the ``JLinkPowerTraceChannelCaps`` instance. + + Args: + self (TestStructs): the ``TestStructs`` instance + + Returns: + ``None`` + """ + channel_caps = structs.JLinkPowerTraceChannelCaps() + channel_caps.BaseSampleFreq = 1000 + channel_caps.MinDiv = 4 + + self.assertEqual(12, channel_caps.SizeOfStruct) + self.assertEqual(250, channel_caps.max_sample_freq) + self.assertEqual('JLinkPowerTraceChannelCaps(SampleFreq=1000Hz, MinDiv=4)', repr(channel_caps)) + if __name__ == '__main__': unittest.main()