From bbf2d041da806fe01b379aa244ebb3dcdf21a1c1 Mon Sep 17 00:00:00 2001 From: Felipe Torrezan Date: Sun, 19 Mar 2023 16:59:32 +0100 Subject: [PATCH] Initial commit --- .gitignore | 14 + LICENSE | 27 + README.md | 177 +++++ examples/CMakeLists.txt | 34 + examples/README.md | 73 ++ examples/itm-logger.cpp | 160 ++++ examples/mem-reader.cpp | 114 +++ examples/mem-writer.cpp | 118 +++ target/README.md | 21 + target/demo.c | 41 ++ target/main.c | 16 + target/target.ewd | 1550 +++++++++++++++++++++++++++++++++++++++ target/target.ewp | 1064 +++++++++++++++++++++++++++ target/target.ewt | 1432 ++++++++++++++++++++++++++++++++++++ target/target.eww | 7 + 15 files changed, 4848 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 examples/CMakeLists.txt create mode 100644 examples/README.md create mode 100644 examples/itm-logger.cpp create mode 100644 examples/mem-reader.cpp create mode 100644 examples/mem-writer.cpp create mode 100644 target/README.md create mode 100644 target/demo.c create mode 100644 target/main.c create mode 100644 target/target.ewd create mode 100644 target/target.ewp create mode 100644 target/target.ewt create mode 100644 target/target.eww diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f029318 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.o +*.obj +*.log +*.out +*.elf +*.exe + +target/Simulator +target/settings +!target/settings/target.dnx +target/Backup* +target/*.dep + +examples/*build diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..84661e9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +IAR Source License + +The following license agreement applies to linker command files, +example projects (unless another license is explicitly stated), the +cstartup code, low_level_init.c, and some other low-level runtime +library files. + +Copyright 2014-2023 IAR Systems AB. + +This source code is the property of IAR Systems. The source code may only +be used together with the IAR Embedded Workbench. Redistribution and use +in source and binary forms, with or without modification, is permitted +provided that the following conditions are met: + +- Redistributions of source code, in whole or in part, must retain the +above copyright notice, this list of conditions and the disclaimer below. + +- IAR Systems name may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..483417e --- /dev/null +++ b/README.md @@ -0,0 +1,177 @@ +# Getting Started with the Target Access plugin for IAR Embedded Workbench + +The Target Access plugin for the C-SPY Debugger, alongside its SDK, are automatically installed with the IAR Embedded Workbench. + +The plugin provides a server that listens to the `9931/UDP` port and runs on top of the C-SPY Debugger. Its Target Access SDK provides an API for a third-party client to establish a network connection to the server and, from there, tap into a device target's memory to perform runtime read/write access. The SDK also provides capabilities for a client to monitor hardware ITM events. + +```mermaid +sequenceDiagram +autonumber +title C-SPY Target Access Plugin +participant Target Access Client +participant Target Access Server +participant C-SPY Debugger +participant Target Device + +note right of Target Access Client: 9931/UDP; +Target Access Client ->> Target Access Server: TargetAccess*(); +rect rgb(240, 240, 240) +note right of Target Access Server: Internally processed by C-SPY +Target Access Server ->> C-SPY Debugger: (TargetAccess*()); +alt R/W memory + C-SPY Debugger-->>Target Device: ; +else ITM listener + C-SPY Debugger-->>Target Device: ; +end +Target Device ->> C-SPY Debugger: (Output/Result); +C-SPY Debugger ->> Target Access Server: (Output/Result); +end +Target Access Server ->> Target Access Client: Output/Result; +``` + +This repository contains simple examples of client applications created with the Target Access SDK. They can connect to the server's UDP port, exposed by the Target Access Client DLL. + +The Target Access Plugin SDK is installed at `C:/path/to/IAR/Embedded/Workbench/arm/src/TargetAccessPlugin`. + +> __Note__ For more information on the SDK API details, refer to the _Getting Started Guide for the Target Access Plugin_, installed inside the _Target Access Plugin_ documentation folder (`C:/path/to/IAR/Embedded/Workbench/arm/src/TargetAccessPlugin/doc/TargetAccessPlugin.pdf`). + + +## Example programs + +### Building the example programs +To build the example programs you will need: +- [IAR Embedded Workbench for Arm](https://iar.com/ewarm) V9 or later +- [Microsoft Visual Studio 2022](https://visualstudio.microsoft.com/vs/) or later, installed for C++ Desktop Development + +1. Launch "Developer Command Prompt for VS 2022". +2. Clone this repository. +3. Build the examples: +``` +cd cspy-target-access-demo/examples +mkdir build && cd build +cmake .. -DTOOLKIT_DIR="C:/path/to/IAR/Embedded/Workbench/x.xx/arm" +cmake --build . --config Release +``` +>__Note__ `TOOLKIT_DIR` must point to the `arm` subdirectory in the installation directory of the IAR Embedded Workbench. + +Three example programs should be inside the __Release__ directory: `mem-reader.exe`, `mem-writer.exe` and `itm-logger.exe`. Also, a copy of the `TargetAccessClientSDK.dll` library was automatically placed together with these executables. + +>__Syntax notes__
+>``` +>mem-reader <32-bit address> +>``` +>``` +>mem-writer <32-bit address> <32-bit value> +>``` +>``` +>itm-logger +>``` +> +>__Note__ The `itm-logger` example requires an actual hardware target. + +### Running the memory access [example](examples#readme) programs +The memory access example programs can be used with the C-SPY Simulator (or adapted to run on hardware). + +1. In IAR Embedded Workbench, open the `cspy-target-access-demo\target\target.eww` workspace. +2. Choose __Project__ → __Download and Debug__ (Ctrl+D). +>__Note__ On the __Debug Log__ window, you shall see a message similar to: +> ``` +> Sun Jan 01, 2023 12:00:00: TargetAccessPlugin: Started listening on port 9931 +> ``` +3. Choose __View__ → __Live watch__ and `` `buffer` and `val`. +4. In "Developer Command Prompt for VS 2022", execute: +``` +.\Release\mem-reader 0x20001000 +.\Release\mem-reader 0x20002000 +.\Release\mem-writer 0x20001000 0x1000 +.\Release\mem-reader 0x20001000 +etc. +``` + +>__Note__ As you use the `mem-writer` application to modify the target's variables `buffer` or `val`, you shall see their updated values in the C-SPY __Live Watch__ window. +> +>![image](https://user-images.githubusercontent.com/54443595/226172125-2981bb40-b564-44b8-b9a9-0861f20179d2.png) + +### Running the itm-logger [example](examples#readme) program +For executing the ITM Logger example, you will need to create a new C Project in IAR Embedded Workbench. The program should configure the hardware device target clocks. You will also need a debug probe. For the best experience, we recommend the [IAR I-jet](https://iar.com/ijet). +>__Note__ It is assumed that the hardware provides the **I**nstrumentation **T**race **M**acrocell (for example Cortex-M4). + +1. Create/Generate a new C project that initializes the desired hardware target. If convenient, use the Code Generator provided by the silicon manufacturer. +2. Add `cspy-target-access-demo/target/demo.c` to the project. +3. On the created application's __main.c__ file, add `extern void demo(void);` so you can call `demo()` from the `main()` function, similar to what was done in [target/main.c](target/main.c). +4. Choose __Project__ → __Options__ (Alt+F7) → __Debugger__ → __Plugins__ and ☑️ __Target Access Server__. +>__Note__ If necessary, set up:
+> - __General Options__ → __Target__ → __Device__. +> - __Debugger__ → __Setup__ → __Driver__ → __I-jet__. +> - __I-jet__ → __Interface__ → __SWD__. +> - and any other relevant project options. + +5. Choose __Project__ → __Download and Debug__ (Ctrl+D). +6. Choose __I-jet__ → __SWO Configuration__. +7. Select the ITM ports `20` and `21` (23◼️◼️☑️☑️◼️◼️◼️◼️16) and deselect any others. + +![image](https://user-images.githubusercontent.com/54443595/226112292-fbc2d8e3-c0bd-452d-9aff-239b77bb362a.png) + +>__Note__ On Cortex-M devices, there are 32 ITM ports (0-31). ITM ports 0-19 are reserved by IAR Embedded Workbench. When creating client applications, make sure they only use the ITM ports 20-31. Using reserved ITM ports from external client applications may result in undefined behavior. + +8. Choose __Debug__ → __Go__ (F5). +9. In the "Developer Command Prompt for VS 2022", execute: +``` +.\Release\itm-logger.exe +``` + +
Output example (click to unfold): + +>``` +>[d47c6888e] ITM port 20: 0000005b (1 byte length) +>[d4950f8cb] ITM port 21: 0a3e35ec (4 bytes length) +>[d49ca33f3] ITM port 20: 0000006f (1 byte length) +>[d4b591c11] ITM port 20: 00000079 (1 byte length) +>[d4c90a7ed] ITM port 20: 0000003d (1 byte length) +>[d4c91500f] ITM port 21: 0a40b6a4 (4 bytes length) +>[d4e8fffe6] ITM port 21: 0a424244 (4 bytes length) +>[d4f966a5d] ITM port 21: 0a430c25 (4 bytes length) +>[d5136b290] ITM port 21: 0a444de9 (4 bytes length) +>[d52387343] ITM port 20: 00000079 (1 byte length) +>[d53fd977e] ITM port 20: 000000c9 (1 byte length) +>[d5576ae7d] ITM port 20: 00000083 (1 byte length) +>[d569365f0] ITM port 20: 000000ab (1 byte length) +>[d58422aa1] ITM port 20: 000000a1 (1 byte length) +>[d5947373e] ITM port 21: 0a4a8380 (4 bytes length) +>[d5aa61e0e] ITM port 20: 00000083 (1 byte length) +>[d5c678198] ITM port 21: 0a4cecb4 (4 bytes length) +>[d5de70463] ITM port 20: 000000b5 (1 byte length) +>[d5f36b798] ITM port 21: 0a4f1a09 (4 bytes length) +>[d60b272f0] ITM port 20: 000000d3 (1 byte length) +>[d61a267bb] ITM port 20: 00000047 (1 byte length) +>[d632a4982] ITM port 20: 000000e7 (1 byte length) +>[d6543181e] ITM port 21: 0a53c1f9 (4 bytes length) +>[d6562fe4b] ITM port 20: 00000029 (1 byte length) +>[d68113ea2] ITM port 21: 0a55eb00 (4 bytes length) +>[d68364bbd] ITM port 20: 000000bf (1 byte length) +>[d696e5913] ITM port 20: 0000008d (1 byte length) +>[d6ac34750] ITM port 20: 00000015 (1 byte length) +>[d6af3d321] ITM port 20: 00000001 (1 byte length) +>ITM Listener: on Channels: 0xffffffff Buffer capacity: 1000 Buffer size: 0 +>``` + +
+ + +## Target Access from `cspybat` +The Target Access Server plugin can also be used from the command line, with `cspybat`. + +Append the following parameter in the project's `settings/target.Simulator.general.xcl`: +``` +--plugin="C:/path/to/IAR/Embedded/Workbench/common/plugins/TargetAccessServer/TargetAccessServer.dll" +``` +So that the `settings/target.Simulator.cspy.bat` script will execute `cspybat` with Target Access support. + +>__Note__ Use `Ctrl-C` to terminate the batch job. + + +## Disclaimer +The information in this repository is subject to change without notice and does not represent a commitment on any part of IAR. While the information contained herein is assumed to be accurate, IAR assumes no responsibility for any errors or omissions. + +## Troubleshooting +If there are technical issues related to the IAR products and you are eligible for support, please get in touch with the IAR support services: https://iar.com/support. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..5508aed --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required (VERSION 3.25) + +project(TargetAccessPluginClientExamples CXX) + +if (NOT DEFINED TOOLKIT_DIR) + message(FATAL_ERROR "You must configure with -DTOOLKIT_DIR=\"C:/path/to/Embedded/Workbench/x.xx/arm\"") +endif() +find_library(TAC_Lib + NAMES TargetAccessClientSDK + PATHS "${TOOLKIT_DIR}/src/TargetAccessPlugin/lib" + REQUIRED) + +if(MSVC) + add_executable(mem-reader mem-reader.cpp) + add_executable(mem-writer mem-writer.cpp) + add_executable(itm-logger itm-logger.cpp) + set_target_properties( + mem-reader + mem-writer + itm-logger + PROPERTIES + INCLUDE_DIRECTORIES "${TOOLKIT_DIR}/src/TargetAccessPlugin/inc" + COMPILE_OPTIONS /Zi + LINK_OPTIONS /SUBSYSTEM:console + LINK_LIBRARIES ${TAC_Lib} ) + add_custom_command(TARGET itm-logger POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${TOOLKIT_DIR}/../common/bin/TargetAccessClientSDK.dll" + $) +endif() + + + + diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..0eb9b5e --- /dev/null +++ b/examples/README.md @@ -0,0 +1,73 @@ +# Example programs +The provided C++ example client programs are simple console applications for Windows. + +## Overview +The programs implement these functions: + +The `ConsoleCloseHandler()` function uses the Windows API for allowing a clean shutdown of the network connection when the console is closed. + +The `ReportError()` function relies on the API function `TargetAccessGetLastErrorMsg()`: +```c +size_t TargetAccessGetLastErrorMsg(char *errorMsg, + size_t bufSize) +``` +and is invoked upon a `DemoException` is catched to demonstrate how errors can be handled. + +All the programs initiate the Target Access Client in the `main()` function: +```c +int TargetAccessInitializeWithPort(const char *serverName, + int port) +``` +using the default Target Access plugin port `9931/UDP`, except if the environment variable `TARGET_ACCESS_PORT` specifies otherwise. + + +## Accessing Target Memory +### `mem-reader` +The [`mem-reader.cpp`](mem-reader.cpp) example application demonstrates how to read from the target device memory. It uses the `TargetAccessReadTargetMemory()` function +```c +int TargetAccessReadTargetMemory(TargetAccessAddr address, + unsigned char *buffer, + uint16_t numBytes) +``` +to read 4 bytes of memory at the `address`, entered as command line parameter. The `buffer` points to a string in the program. + + +### `mem-writer` +The [`mem-writer.cpp`](mem-writer.cpp) example application demonstrates how to write the target device memory. It uses the `TargetAccessWriteTargetMemory()` function +```c +int TargetAccessWriteTargetMemory(TargetAccessAddr address, + const unsigned char *buffer, + uint16_t numBytes) +``` +to write to a 32-bit `buffer` to the target's memory `address`. Both `address` and `buffer` are entered as command line parameters. + + +## ITM Events Listener +### `itm-logger` +The [`itm-logger.cpp`](itm-logger.cpp) example application implements a logger for ITM events. The most relevant code is in the `RunItmLogging()` function. + +The `TargetAccessConfigureItmListener()` API function +```c +int TargetAccessConfigureItmListener(uint32_t channels, + uint32_t bufferCapacity) +``` +starts by setting the ITM channels bit mask to `0xffffffff` and the buffer capacity to `1000` events. + +Within the `while(1)` loop, the API function +```c +int TargetAccessReadItmEvent(ITMEvent *itmEvent, + bool *isValid) +``` +polls for a new ITM event every `duration` seconds. The `ITMevent` block: +```c +struct ITMEvent +{ + uint8_t portId; + uint64_t timeStamp; + uint32_t dataLength; + uint8_t data[4]; +}; +``` +becomes invalid for the current iteration if the `isValid` argument is false and then `ReportITMStatus()` is executed. + +The program runs indefinitely until `Ctrl-C` is pressed or the console is closed, as implemented in the `ConsoleCloseHandler()`. diff --git a/examples/itm-logger.cpp b/examples/itm-logger.cpp new file mode 100644 index 0000000..85cef5f --- /dev/null +++ b/examples/itm-logger.cpp @@ -0,0 +1,160 @@ +/************************************************** + * + * ITM Logger example (itm-logger.cpp) + * + * Copyright (c) 2023 IAR Systems AB. + * + * See LICENSE for detailed license information. + * + **************************************************/ + +#include "TargetAccessClientSDK.h" + +#include +#include +#include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) +#include +BOOL WINAPI ConsoleCloseHandler(DWORD dwCtrlType) +{ + switch (dwCtrlType) + { + case CTRL_C_EVENT: + std::cout << "Ctrl-C detected." << std::setfill(' ') << + std::setw(50) << std::endl; + ::TargetAccessShutdown(); + return TRUE; + + case CTRL_CLOSE_EVENT: + std::cout << "TargetAccessClientITMdemo is shutting down" << + std::setfill(' ') << std::setw(50) << "" << std::endl; + ::TargetAccessShutdown(); + return TRUE; + + default: + return FALSE; + } +} +#endif + +class DemoException : public std::exception +{ +public: + DemoException() + { + } +}; + +void ReportITMStatus() +{ + ITMListenerStatus status; + + status.listening = 0; + status.channels = 0; + status.bufferCapacity = 0; + status.bufferSize = 0; + ::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"; +} + +void ReportError() +{ + std::string errorMsg; + + errorMsg.resize(512); + ::TargetAccessGetLastErrorMsg(const_cast(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; +} + +int RunItmLogging() +{ + if (::TargetAccessConfigureItmListener(0xffffffff, 1000) != 0) + throw DemoException(); + + if (::TargetAccessStartItmListener() != 0) + throw DemoException(); + + auto defaultDuration = std::chrono::seconds(1); + auto duration = defaultDuration; + bool isValid = false; + + 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(itmEvent.data); + break; + case 4: + value = *reinterpret_cast(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; +} + +int main(int argc, const char **argv) +{ +#if defined(_WIN32) || defined(_WIN64) + ::SetConsoleCtrlHandler(ConsoleCloseHandler, TRUE); +#endif + + char *portStr = nullptr; + size_t sz = 0; + int port = 9931; // server's default UDP port + if (_dupenv_s(&portStr, &sz, "TARGET_ACCESS_PORT") == 0 && portStr != nullptr) + { + port = std::stoi(portStr); + free(portStr); + } + try + { + // Initialize client + if (::TargetAccessInitializeWithPort("localhost", port) != TARGET_ACCESS_STATUS_OK) + { + throw DemoException(); + ::TargetAccessShutdown(); + return 1; + } + ::RunItmLogging(); + } + catch (const DemoException &) + { + ::ReportError(); + } + ::TargetAccessShutdown(); + return 0; +} diff --git a/examples/mem-reader.cpp b/examples/mem-reader.cpp new file mode 100644 index 0000000..4022a26 --- /dev/null +++ b/examples/mem-reader.cpp @@ -0,0 +1,114 @@ +/************************************************** + * + * Memory reader example (mem-reader.cpp) + * + * Copyright (c) 2023 IAR Systems AB. + * + * See LICENSE for detailed license information. + * + **************************************************/ + +#include "TargetAccessClientSDK.h" + +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) +#include +BOOL WINAPI ConsoleCloseHandler(DWORD dwCtrlType) +{ + switch (dwCtrlType) + { + case CTRL_C_EVENT: + std::cout << "Ctrl-C detected." << std::setfill(' ') << + std::setw(50) << std::endl; + ::TargetAccessShutdown(); + return TRUE; + + case CTRL_CLOSE_EVENT: + std::cout << "Target Access Client is shutting down" << + std::setfill(' ') << std::setw(50) << "" << std::endl; + ::TargetAccessShutdown(); + return TRUE; + + default: + return FALSE; + } +} +#endif + +class DemoException : public std::exception +{ +public: + DemoException() + { + } +}; + +void ReportError() +{ + std::string errorMsg; + + errorMsg.resize(512); + ::TargetAccessGetLastErrorMsg(const_cast(errorMsg.data()), errorMsg.size()); + std::cout << "Error: " << errorMsg << std::endl; +} + +int main(int argc, const char **argv) +{ +#if defined(_WIN32) || defined(_WIN64) + ::SetConsoleCtrlHandler(ConsoleCloseHandler, TRUE); +#endif + + char *portStr = nullptr; + size_t sz = 0; + int port = 9931; // server's default UDP port + if (_dupenv_s(&portStr, &sz, "TARGET_ACCESS_PORT") == 0 && portStr != nullptr) + { + port = std::stoi(portStr); + free(portStr); + } + try + { + if (argc < 2) + { + std::cout << "Usage: mem-reader <32-bit address>" << std::endl; + return 1; + } + TargetAccessAddr addr; + std::istringstream istr(argv[1]); + istr >> std::hex >> addr; + + // Initialize client + if (::TargetAccessInitializeWithPort("localhost", port) != TARGET_ACCESS_STATUS_OK) + { + throw DemoException(); + ::TargetAccessShutdown(); + return 1; + } + + union { + uint32_t value; + uint8_t buffer[4]; + } data; + + if (::TargetAccessReadTargetMemory(addr, data.buffer, sizeof(data.buffer)) != TARGET_ACCESS_STATUS_OK) + { + throw DemoException(); + ::TargetAccessShutdown(); + return 1; + } + std::cout << "Read: 0x" << std::hex << data.value << " @ 0x" << std::hex << addr << std::endl; + } + catch (const DemoException &) + { + ::ReportError(); + } + ::TargetAccessShutdown(); + return 0; +} + diff --git a/examples/mem-writer.cpp b/examples/mem-writer.cpp new file mode 100644 index 0000000..ef08cf0 --- /dev/null +++ b/examples/mem-writer.cpp @@ -0,0 +1,118 @@ +/************************************************** + * + * Memory writer example (mem-writer.cpp) + * + * Copyright (c) 2023 IAR Systems AB. + * + * See LICENSE for detailed license information. + * + **************************************************/ + +#include "TargetAccessClientSDK.h" + +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) +#include +BOOL WINAPI ConsoleCloseHandler(DWORD dwCtrlType) +{ + switch (dwCtrlType) + { + case CTRL_C_EVENT: + std::cout << "Ctrl-C detected." << std::setfill(' ') << + std::setw(50) << std::endl; + ::TargetAccessShutdown(); + return TRUE; + + case CTRL_CLOSE_EVENT: + std::cout << "Target Access Client is shutting down" << + std::setfill(' ') << std::setw(50) << "" << std::endl; + ::TargetAccessShutdown(); + return TRUE; + + default: + return FALSE; + } +} +#endif + +class DemoException : public std::exception +{ +public: + DemoException() + { + } +}; + +void ReportError() +{ + std::string errorMsg; + + errorMsg.resize(512); + ::TargetAccessGetLastErrorMsg(const_cast(errorMsg.data()), errorMsg.size()); + std::cout << "Error: " << errorMsg << std::endl; +} + +int main(int argc, const char **argv) +{ +#if defined(_WIN32) || defined(_WIN64) + ::SetConsoleCtrlHandler(ConsoleCloseHandler, TRUE); +#endif + + char *portStr = nullptr; + size_t sz = 0; + int port = 9931; // server's default UDP port + if (_dupenv_s(&portStr, &sz, "TARGET_ACCESS_PORT") == 0 && portStr != nullptr) + { + port = std::stoi(portStr); + free(portStr); + } + try + { + if (argc < 3) + { + std::cout << "Usage: mem-writer <32-bit address> <32-bit value>" << std::endl; + return 1; + } + TargetAccessAddr addr; + std::istringstream astr(argv[1]); + astr >> std::hex >> addr; + + union { + uint32_t value; + uint8_t buffer[4]; + } data; + + std::istringstream vstr(argv[2]); + vstr >> std::hex >> data.value; + + // Initialize client + if (::TargetAccessInitializeWithPort("localhost", port) != TARGET_ACCESS_STATUS_OK) + { + throw DemoException(); + ::TargetAccessShutdown(); + return 1; + } + for (size_t i = 0; i < 4; i++) + { + if (::TargetAccessWriteTargetMemory(addr, data.buffer, sizeof(data.buffer)) != TARGET_ACCESS_STATUS_OK) + { + throw DemoException(); + ::TargetAccessShutdown(); + return 1; + } + } + std::cout << "Wrote: 0x" << std::hex << data.value << " @ 0x" << std::hex << addr << std::endl; + } + catch (const DemoException &) + { + ::ReportError(); + } + ::TargetAccessShutdown(); + return 0; +} diff --git a/target/README.md b/target/README.md new file mode 100644 index 0000000..8a9d861 --- /dev/null +++ b/target/README.md @@ -0,0 +1,21 @@ +# Target Application Example + +The `arm_itm.h` header file (located in `arm/inc/c`) contains predefined preprocessor macros for setting ITM events. + +The following code shows a simple example of how these macros can be used in combination with the `itm-logger` program introduced in the previous section. Although only 2 `ITM_EVENT` macros are called, there are actually 3 ITM events set in the `while (1)` loop. +```c + /* ... */ + while (1) + { + if (value++ % 10 == 0) + { + sum += value; +#if !defined(SIMULATOR) + ITM_EVENT8(20, value); + ITM_EVENT32_WITH_PC(21, sum); +#endif + for (size_t i = 100; i > 0; --i); // Delay + } + } +``` +The reason is that the `ITM_EVENT32_WITH_PC()` macro also sets the current value of the PC register at ITM port 5. The `arm_itm.h` header file contains macros for 8, 16 and 32 bits; `ITM_EVENT8()`, `ITM_EVENT16()`, and `ITM_EVENT32()`, respectively. Each of these also has a corresponding macro setting the current `PC` value (`ITM_EVENT8_WITH_PC()`, `ITM_EVENT16_WITH_PC()` and `ITM_EVENT32_WITH_PC()`). diff --git a/target/demo.c b/target/demo.c new file mode 100644 index 0000000..da7b7a5 --- /dev/null +++ b/target/demo.c @@ -0,0 +1,41 @@ +/************************************************** + * + * Target Access Plugin demo (for Cortex-M) + * + * Copyright (c) 2023 IAR Systems AB. + * + * See LICENSE for detailed license information. + * + **************************************************/ + +#if !defined(SIMULATOR) // Set in `Preprocessor` +#include +#else +#warning "ITM events require hardware. No support provided in Simulator." +#endif +#include +#include + +__root uint8_t buffer[4] @ 0x20001000 = "ABCD"; +__root uint32_t val @ 0x20002000 = 0x48474645; + +void demo() +{ + uint8_t value = 0; + uint32_t sum = 0; + + while (1) + { + if (value++ % 10 == 0) + { + sum += value; + +#if !defined(SIMULATOR) + ITM_EVENT8(20, value); + ITM_EVENT32_WITH_PC(21, sum); +#endif + + for (size_t i = 100; i > 0; --i); // Delay + } + } +} diff --git a/target/main.c b/target/main.c new file mode 100644 index 0000000..defcd98 --- /dev/null +++ b/target/main.c @@ -0,0 +1,16 @@ +/************************************************** + * + * Target Access Plugin demo (main.c) + * + * Copyright (c) 2023 IAR Systems AB. + * + * See LICENSE for detailed license information. + * + **************************************************/ + +extern void demo(void); + +void main() +{ + demo(); +} diff --git a/target/target.ewd b/target/target.ewd new file mode 100644 index 0000000..4d4cc72 --- /dev/null +++ b/target/target.ewd @@ -0,0 +1,1550 @@ + + + 3 + + Simulator + + ARM + + 1 + + C-SPY + 2 + + 32 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 1 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 1 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + IJET_ID + 2 + + 9 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 3 + 1 + 1 + + + + + + + + + + + + + NULINK_ID + 2 + + 0 + 1 + 1 + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 1 + + + + + + + + STLINK_ID + 2 + + 7 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 1 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 9 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm9.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm9BE.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\vs.ewplugin + 0 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + diff --git a/target/target.ewp b/target/target.ewp new file mode 100644 index 0000000..a509aa7 --- /dev/null +++ b/target/target.ewp @@ -0,0 +1,1064 @@ + + + 3 + + Simulator + + ARM + + 1 + + General + 3 + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 37 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 11 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 80 + inputOutputBased + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 26 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + + $PROJ_DIR$\demo.c + + + $PROJ_DIR$\main.c + + diff --git a/target/target.ewt b/target/target.ewt new file mode 100644 index 0000000..2f9860d --- /dev/null +++ b/target/target.ewt @@ -0,0 +1,1432 @@ + + + 3 + + Simulator + + ARM + + 1 + + C-STAT + 516 + + 516 + + 0 + + 1 + 600 + 1 + 8 + 0 + 1 + 100 + Debug/C-STAT + + + 2.4.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RuntimeChecking + 0 + + 2 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + $PROJ_DIR$\demo.c + + + $PROJ_DIR$\main.c + + diff --git a/target/target.eww b/target/target.eww new file mode 100644 index 0000000..87bcb5b --- /dev/null +++ b/target/target.eww @@ -0,0 +1,7 @@ + + + + $WS_DIR$\target.ewp + + +