Target Access Plug in
Target Access Plug in
Target Access Plug in
IAR Systems, IAR Embedded Workbench, IAR Connect, C-SPY, C-RUN, C-STAT, IAR Visual State,
visualSTATE, IAR KickStart Kit, I-jet, I-jet Trace, I-scope, IAR Academy, IAR, and the logotype of IAR
Systems are trademarks or registered trademarks owned by IAR Systems AB.
All information is subject to change without notice. IAR Systems assumes no responsibility for errors and shall
not be liable for any damage or expenses.
© Copyright 2018 IAR Systems AB. Part number: GSTargetAccessPlugin-2. First edition: October 2017
GSTargetAccessPlugin-2
1
Getting Started Guide for Target Access plugin
Content
Content ............................................................................................................... 2
Description ......................................................................................................... 3
Functions..............................................................................................................................................................5
GSTargetAccessPlugin-2
2
Getting Started Guide for Target Access plugin
Description
The Target Access plugin is a generic server/client solution which allows third-party applications
to read from and write to memory locations on the target device via IAR Embedded Workbench
through a UDP connection. It also provides functions for monitoring ITM events. Note that ITM
ports 0-19 are reserved by IAR Embedded Workbench, which may result in undefined behavior
if those ports are used by client applications.
Start the server part by activating Target Access Server from the C-SPY plugin setup in IAR
Embedded Workbench or from cspybat. The plugin starts a UDP server that listens for
different commands.
The client is composed by the Target Access Client SDK (TargetAccessClientSDK.dll), which is
a library that exports the target commands through a set of C functions. An external application
can open communication to the server through this library which will be described in detail in
this guide.
Directory structure
Directory Description
The server plugin is included in the IAR Embedded Workbench distribution. To enable the
plugin select,
Project > Options > Debugger > Plugins > Target Access Server
To communicate with the server, a C language client SDK library is provided. This library
contains functions for connecting to the server plugin and for reading from and writing to
memory on the target device.
The library consists of the following files:
GSTargetAccessPlugin-2
3
Getting Started Guide for Target Access plugin
TargetAccessClientSDK.dll
TargetAccessClientSDK.h
TargetAccessClientErrorCodes.h
TargetAccessClientSDK.lib
Types
struct ITMEvent
{
uint8_t portId;
uint64_t timeStamp;
uint32_t dataLength;
uint8_t data[4];
};
When an ITM event has been recorded, this struct is populated with the port ID and the
applicable data payload. The portId member specifies the ITM port with range [0…31]
(although ports 0-19 are reserved by IAR Embedded Workbench). The data can be 1, 2 or 4
bytes long. The actual length is stored in the dataLength member. The timeStamp member
shows the timestamp for the event in nanoseconds as reported by the debug probe.
struct ITMListenerStatus
{
uint8_t listening;
uint32_t channels;
uint32_t bufferCapacity;
uint32_t bufferSize;
};
The ITMListenerStatus struct stores the status information collected when calling the
TargetAccessGetItmListenerStatus() function. The listening member is set to
1 when ITM listening is active, otherwise 0. The channels and bufferCapacity members
are the bit mask and buffer capacity set respectively when calling the
TargetAccessConfigureItmListener() function. If that function has not yet been
called, the default values of those members are 0. The bufferSize member shows the current
buffer size. When bufferSize == bufferCapacity, it can be assumed that ITM events
are being dropped.
GSTargetAccessPlugin-2
4
Getting Started Guide for Target Access plugin
Functions
Most of the following C functions all return 0 if successful, otherwise an error code. For more
information about the latest error, call the TargetAccessGetLastErrorMsg().
int TargetAccessInitialize(const char *serverName)
This function initializes the SDK and needs to be called before using any of the other functions.
serverName is the computer to connect to, e.g. localhost or 127.0.0.1 to connect to
the local computer.
int TargetAccessShutdown()
This function needs to be called when you no longer need to access the Target Access interface.
int TargetAccessGetClientProtocolVersion()
Returns the client version.
int TargetAccessGetServerProtocolVersion()
Returns the server version.
GSTargetAccessPlugin-2
5
Getting Started Guide for Target Access plugin
the ITM event at a specific port, it is important to have it selected both in the SWO
Configuration dialog box and as a set bit in the channels parameter.
The bufferCapacity parameter specifies how many events will be saved before they are
dropped.
The default values of channels and bufferCapacity are 0.
int TargetAccessStartItmListener()
This function starts the ITM event monitoring.
int TargetAccessStopItmListener()
This function stops the ITM event monitoring.
Example Programs
// Initialize client
res = TargetAccessInitialize("127.0.0.1");
if (res != TARGET_ACCESS_STATUS_OK)
{
TargetAccessGetLastErrorMsg(errorMsg, sizeof(errorMsg));
fprintf(stderr, "Error: %s\n", errorMsg);
TargetAccessShutdown();
return 1;
}
GSTargetAccessPlugin-2
6
Getting Started Guide for Target Access plugin
TargetAccessShutdown();
return 1;
}
#include <iostream>
#include <iomanip>
#include <string>
#include <thread>
#include <chrono>
#ifdef _WIN32
#include <Windows.h>
BOOL WINAPI ConsoleCloseHandler(DWORD dwCtrlType)
{
if (dwCtrlType == CTRL_CLOSE_EVENT)
{
std::cout << "TargetAccessClientITMdemo is shutting down" <<
std::setfill(' ') << std::setw(50) << "" << std::endl;
::TargetAccessShutdown();
}
return TRUE;
}
#endif
GSTargetAccessPlugin-2
7
Getting Started Guide for Target Access plugin
::TargetAccessGetItmListenerStatus(&status);
std::cout << "ITM Listener: " << (status.listening != 0 ? "on" : "off")
<< " ";
std::cout << "Channels: 0x" << std::hex << std::setfill('0') <<
std::setw(8) << status.channels << std::dec << " ";
std::cout << "Buffer capacity: " << status.bufferCapacity << " ";
std::cout << "Buffer size: " << status.bufferSize << "\r";
}
The ReportError() function shown below demonstrates how errors can be handled:
void ReportError()
{
std::string errorMsg;
errorMsg.resize(512);
::TargetAccessGetLastErrorMsg(const_cast<char *>(errorMsg.data()),
errorMsg.size());
std::cout << "Error: " << errorMsg << std::endl;
std::cout << "Client protocol version: " <<
::TargetAccessGetClientProtocolVersion() << std::endl;
std::cout << "Server protocol version: " <<
::TargetAccessGetServerProtocolVersion() << std::endl;
}
Next, we implement the main event loop. It starts by setting the ITM channels bit mask to
0xffffffff and the buffer capacity to 1000 events. Note that the duration variable
switches between 0 and 1 seconds depending on whether the ITM buffer is empty or not. If the
received ITMEvent block is invalid (the isValid argument is false), the wait time for the
next poll is set to 1 second.
int RunItmLogging()
{
if (::TargetAccessConfigureItmListener(0xffffffff, 1000) != 0)
throw DemoException();
if (::TargetAccessStartItmListener() != 0)
throw DemoException();
while (1)
{
ITMEvent itmEvent;
if (::TargetAccessReadItmEvent(&itmEvent, &isValid) !=
TARGET_ACCESS_STATUS_OK)
throw DemoException();
if (isValid)
{
std::cout << "[" << std::hex << itmEvent.timeStamp << std::dec <<
"] ITM port " << (int)itmEvent.portId << ": ";
uint32_t value = 0;
switch (itmEvent.dataLength)
{
case 1:
value = itmEvent.data[0];
break;
case 2:
value = *reinterpret_cast<uint16_t *>(itmEvent.data);
break;
GSTargetAccessPlugin-2
8
Getting Started Guide for Target Access plugin
case 4:
value = *reinterpret_cast<uint32_t *>(itmEvent.data);
break;
}
std::cout << std::hex << std::setfill('0') << std::setw(8) <<
value << std::dec;
std::cout << " (" << itmEvent.dataLength << " byte" <<
(itmEvent.dataLength > 1 ? "s" : "") << " length)";
std::cout << std::setw(50) << std::setfill(' ') << "" << std::endl;
duration = std::chrono::seconds(0); // Keep reading events until the
// buffer is empty
}
else
{
duration = defaultDuration; // Pause with 1 second delays when no
// data is recorded
::ReportITMStatus();
}
std::this_thread::sleep_for(duration);
}
return 0;
}
Finally, the entry function for the program sets up communication to the server and handles
errors. It also performs a clean shutdown before exiting:
try
{
if (argc > 1)
port = std::stoi(argv[1]);
// Initialize client
if (::TargetAccessInitializeWithPort("localhost", port) !=
TARGET_ACCESS_STATUS_OK)
throw DemoException();
::RunItmLogging();
}
catch (const DemoException &)
{
::ReportError();
}
::TargetAccessShutdown();
system("pause");
return 0;
}
GSTargetAccessPlugin-2
9
Getting Started Guide for Target Access plugin
void main()
{
ITM_EVENT8(20, 0);
ITM_EVENT32(21, 0);
uint8_t value = 0;
uint32_t sum = 0;
while (1)
{
if (value++ % 10 == 0)
{
sum += value;
ITM_EVENT8(20, value);
ITM_EVENT32_WITH_PC(21, sum);
for (int i = 10000; i > 0; --i); /* Delay */
}
}
}
GSTargetAccessPlugin-2
10