Skip to content

Commit 204afeb

Browse files
committed
ISSUE-214: Add Support for Power Tracing
This patch adds support to PyLink for using the Power Trace API.
1 parent 0b3e8ca commit 204afeb

File tree

6 files changed

+752
-2
lines changed

6 files changed

+752
-2
lines changed

pylink/__main__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717
import argparse
1818
import logging
1919
import os
20-
import six
2120
import sys
21+
try:
22+
from six.moves import with_metaclass
23+
except (AttributeError, ImportError):
24+
from six import with_metaclass
2225

2326

2427
class CommandMeta(type):
@@ -49,7 +52,7 @@ def __new__(cls, name, parents, dct):
4952
return newClass
5053

5154

52-
class Command(six.with_metaclass(CommandMeta)):
55+
class Command(with_metaclass(CommandMeta)):
5356
"""Base command-class.
5457
5558
All commands should inherit from this class.

pylink/enums.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,3 +722,27 @@ class JLinkRTTDirection(object):
722722
"""RTT Direction."""
723723
UP = 0
724724
DOWN = 1
725+
726+
727+
class JLinkPowerTraceCommand(object):
728+
"""Power trace commands."""
729+
SETUP = 0
730+
START = 1
731+
FLUSH = 2
732+
STOP = 3
733+
GET_CAPS = 4
734+
GET_CHANNEL_CAPS = 5
735+
GET_NUM_ITEMS = 6
736+
737+
class JLinkPowerTraceRef(object):
738+
"""Reference values to store on power trace capture.
739+
740+
Attributes:
741+
NONE: No reference value is stored.
742+
BYTES: Number of bytes transferred via SWO is stored since capturing
743+
started.
744+
TIME: Number of milliseconds since capturing started.
745+
"""
746+
NONE = 0
747+
BYTES = 1
748+
TIME = 2

pylink/jlink.py

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5250,3 +5250,213 @@ def cp15_register_write(self, cr_n, op_1, cr_m, op_2, value):
52505250
if res != 0:
52515251
raise errors.JLinkException(res)
52525252
return res
5253+
5254+
###############################################################################
5255+
#
5256+
# Power API
5257+
#
5258+
###############################################################################
5259+
@open_required
5260+
def power_trace_configure(self, channels, freq, ref, always):
5261+
"""Configures power tracing.
5262+
5263+
This method must be called before calling the other power trace APIs. It
5264+
is the responsibility of the calling application code to keep track of
5265+
which channels were enabled in order to determine which trace samples
5266+
correspond to which channels when read.
5267+
5268+
Args:
5269+
self (JLink): the ``JLink`` instance.
5270+
channels (list[int]): list specifying which channels to capture on (0-7).
5271+
freq (int): sampling frequency (in Hertz).
5272+
ref (JLinkPowerTraceRef): reference value to stored on capture.
5273+
always (bool): ``True`` to capture data even while CPU halted, otherwise ``False``.
5274+
5275+
Returns:
5276+
The sampling frequency (in Hz) for power sampling.
5277+
5278+
Raises:
5279+
JLinkException: on error
5280+
"""
5281+
if isinstance(channels, list):
5282+
channel_mask = 0x00
5283+
for channel in channels:
5284+
channel_mask |= (1 << channel)
5285+
else:
5286+
channel_mask = channels
5287+
5288+
setup = structs.JLinkPowerTraceSetup()
5289+
setup.ChannelMask = channel_mask
5290+
setup.SampleFreq = int(freq)
5291+
setup.RefSelect = int(ref)
5292+
setup.EnableCond = 0 if always else 1
5293+
5294+
res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.SETUP, ctypes.byref(setup), 0)
5295+
if res < 0:
5296+
raise errors.JLinkException(res)
5297+
return res
5298+
5299+
@open_required
5300+
def power_trace_start(self):
5301+
"""Starts capturing data on the channels enabled via ``power_trace_configure()``.
5302+
5303+
Args:
5304+
self (JLink): the ``JLink`` instance.
5305+
5306+
Returns:
5307+
``None``
5308+
5309+
Raises:
5310+
JLinkException: on error
5311+
"""
5312+
res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.START, 0, 0)
5313+
if res < 0:
5314+
raise errors.JLinkException(res)
5315+
5316+
@open_required
5317+
def power_trace_stop(self):
5318+
"""Stops a capture started by ``power_trace_start()``.
5319+
5320+
Args:
5321+
self (JLink): the ``JLink`` instance.
5322+
5323+
Returns:
5324+
``None``
5325+
5326+
Raises:
5327+
JLinkException: on error
5328+
"""
5329+
res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.STOP, 0, 0)
5330+
if res < 0:
5331+
raise errors.JLinkException(res)
5332+
5333+
@open_required
5334+
def power_trace_flush(self):
5335+
"""Flushes all capture data.
5336+
5337+
Any data that has not been read by ``power_trace_read()`` is dropped.
5338+
5339+
Args:
5340+
self (JLink): the ``JLink`` instance.
5341+
5342+
Returns:
5343+
``None``
5344+
5345+
Raises:
5346+
JLinkException: on error
5347+
"""
5348+
res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.FLUSH, 0, 0)
5349+
if res < 0:
5350+
raise errors.JLinkException(res)
5351+
5352+
@open_required
5353+
def power_trace_get_channels(self):
5354+
"""Returns a list of the available channels for power tracing.
5355+
5356+
This method returns a list of the available channels for power tracing.
5357+
The application code can use this to determine which channels to
5358+
enable for tracing.
5359+
5360+
Args:
5361+
self (JLink): the ``JLink`` instance.
5362+
5363+
Returns:
5364+
List of available channel identifiers.
5365+
5366+
Raises:
5367+
JLinkException: on error
5368+
"""
5369+
caps = structs.JLinkPowerTraceCaps()
5370+
res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.GET_CAPS, 0, ctypes.byref(caps))
5371+
if res < 0:
5372+
raise errors.JLinkException(res)
5373+
5374+
return [i for i in range(0, 32) if (caps.ChannelMask >> i) & 0x1]
5375+
5376+
@open_required
5377+
def power_trace_get_channel_capabilities(self, channels):
5378+
"""Returns the capabilities for the specified channels.
5379+
5380+
Args:
5381+
self (JLink): the ``JLink`` instance.
5382+
channels (list[int]): list specifying which channels to get capabilities for.
5383+
5384+
Returns:
5385+
Channel capabilities.
5386+
5387+
Raises:
5388+
JLinkException: on error
5389+
"""
5390+
if isinstance(channels, list):
5391+
channel_mask = 0x00
5392+
for channel in channels:
5393+
channel_mask |= (1 << channel)
5394+
else:
5395+
channel_mask = channels
5396+
5397+
channel_caps = structs.JLinkPowerTraceChannelCaps()
5398+
caps = structs.JLinkPowerTraceCaps()
5399+
caps.ChannelMask = channel_mask
5400+
5401+
res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.GET_CHANNEL_CAPS,
5402+
ctypes.byref(caps),
5403+
ctypes.byref(channel_caps))
5404+
if res < 0:
5405+
raise errors.JLinkException(res)
5406+
5407+
return channel_caps
5408+
5409+
@open_required
5410+
def power_trace_get_num_items(self):
5411+
"""Returns a count of the number of items in the power trace buffer.
5412+
5413+
Since each channel is sampled simulataneously, the count of number of
5414+
items per channel is the return value of this function divided by the
5415+
number of active channels.
5416+
5417+
Args:
5418+
self (JLink): the ``JLink`` instance.
5419+
5420+
Returns:
5421+
Number of items in the power trace buffer.
5422+
5423+
Raises:
5424+
JLinkException: on error
5425+
"""
5426+
res = self._dll.JLINK_POWERTRACE_Control(enums.JLinkPowerTraceCommand.GET_NUM_ITEMS, 0, 0)
5427+
if res < 0:
5428+
raise errors.JLinkException(res)
5429+
return res
5430+
5431+
@open_required
5432+
def power_trace_read(self, num_items=None):
5433+
"""Reads data from the power trace buffer.
5434+
5435+
Any read data is flushed from the power trace buffer.
5436+
5437+
Args:
5438+
self (JLink): the ``JLink`` instance.
5439+
num_items (int): the number of items to read (if not specified, reads all).
5440+
5441+
Returns:
5442+
List of ``JLinkPowerTraceItem``s.
5443+
5444+
Raises:
5445+
JLinkException: on error
5446+
"""
5447+
if num_items is None:
5448+
num_items = self.power_trace_get_num_items()
5449+
5450+
items = []
5451+
if num_items < 0:
5452+
raise ValueError("Invalid number of items requested, expected > 0, given %d" % num_items)
5453+
elif num_items > 0:
5454+
items = (structs.JLinkPowerTraceItem * num_items)()
5455+
res = self._dll.JLINK_POWERTRACE_Read(ctypes.byref(items), num_items)
5456+
if res < 0:
5457+
raise errors.JLinkException(res)
5458+
5459+
# Number of items may be less than the requested count, so clip the
5460+
# array here.
5461+
items = list(items)[:res]
5462+
return items

0 commit comments

Comments
 (0)