Skip to content

Open-CMSIS-Pack/debug-adapter-registry

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

86 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

debug-adapter-registry

License Test and release

This repository contains the debug adapter registry and the CMSIS Solution extension specific adapter template files.

  πŸ“¦
  ┣ πŸ“‚ registry               shared debug adapter registry
  ┃ β”— πŸ“„ debug-adapters.yml    yaml document listing all available debug adapters
  β”— πŸ“‚ templates              command line tool source code
    ┣ πŸ“„ *.adapter.json       json template for vscode launch and task definitions per debug adapter
    β”— πŸ“„ ...

The adapter registry is used by CMSIS-Toolbox starting version 2.9.0 to generate <solution>+<target-type>.cbuild-run.yml files for the active target-set selected by

cbuild setup <solution> --active <target-type>[@<set>]

Available target-sets are listed by running

cbuild list target-sets <solution>

The <solution>+<target-type>.cbuild-run.yml file is then processed by the CMSIS Solution extension to generate launch.json and task.json files from the debug adapter template files.


Debug Adapter Specification

The registry/debug-adapters.yml lists out all known debug adapters with additional details according to the following schema:

debug-adapters:
  - name: <unique name>
    alias-name: [<alias name>, ... ]
    template: <adapter json template>
    gdbserver:
    defaults:
      <property>: <value>
    user-interface:
      - section: <section label>
        description: <section description>
        yaml-node: <optional section yaml node>
        options:
          - name: <property label>
            description: <property description>
            yml-node: <yaml node name>
            type: <input field type>
            range: [<min value for number fields>, <max value for number fields>]
            scale: <scale factor for number fields>
            default: <default value>
            values: [<values for enum fields>]
            values: # alternative long format
              - name: <display label for enum value, defaults to value>
                value: <yaml text for enum value, defaults to name>
                description: <optional description for enum value>
  YAML Node             Value Type         Description
 --------------------- ------------------ -----------------------------------------------------------------------
  debug-adapters        object             Top level node for debug-adapters.yml
  ┣ name                string             Unique name to identify a debug adapter
  ┣ alias-name          array of strings   Optional alias names to identify the debug adapter
  ┣ template            string             Reference to the .adapter.json template file
  ┣ gdbserver           object             Optional, once specified additional gdb server handling is triggered
  ┣ defaults            object             Optional default values for debug adapter specific settings
  β”— user-interface      array of objects   Definition for UI representation for relevant debug adapter settings
    ┣ section           string             Label for a UI settings section
    ┣ description       string             Optional section description β€―β€―
    ┣ yaml-node         string             Optional yaml node name to group section options
    β”— options           object             Options to group into the section
      ┣ name            string             UI label for the option
      ┣ description     string             UI description for the option (e.g., for tooltips)
      ┣ yaml-node       string             YAML node node name to store the option value to
      ┣ type            enum               UI input control type: string, number, file, enum
      ┣ range           [number, number]   Value range (for number type options)
      ┣ scale           number             Value display scale (for number type options)
      ┣ default         any                Default value used as UI preset
      β”— values          array of strings   Accepted values (for enum type options), short form.
        ┃               array of objects   Accepted values (for enum type options), long form.
        ┣ name          string             Display label for the enum value, if omitted value is used.
        ┣ value         string             Storage value for the enum value, if omitted name is used.
        β”— description   string             Optional description text.

Template Development

Template input files

The .adapter.json files provide snippets to be injected into the workspace launch.json and tasks.json files:

{
  "data": {
    "cwd": "${workspaceFolder}/<%= solution_folder %>"
  },
  "launch": {
    "singlecore-launch": {},
    "singlecore-attach": {},
    "multicore-start-launch": {},
    "multicore-start-attach": {},
    "multicore-other": {}
  },
  "tasks": [
    {
      "label": "CMSIS Erase"
    },
    {
      "label": "CMSIS Load"
    },
    {
      "label": "CMSIS Run"
    },
    {
      "label": "CMSIS Load+Run"
    },
    {
      "label": "CMSIS TargetInfo"
    }
  ]
}
  JSON Node                  Value Type         Description
 ---------------------      ------------------ -----------------------------------------------------------------------
  data                       object             User data processed on a global scope
  launch                     object             Template launch configurations
  ┣ singlecore-launch        object             Launch template for launching a single core debug session
  ┣ singlecore-attach        object             Launch template for attaching to a single core debug session
  ┣ multicore-start-launch   object             Launch template for launching a multi core debug session
  ┣ multicore-start-attach   object             Launch template for attaching to the primary core of a multi core debug session
  β”— multicore-other          object             Launch template for attaching to other cores of a multi core debug session
  tasks                      array of objects   Template tasks
  β”— label                    string             Unique name to identify the task, specific names are used for CMSIS debug related tasks

Template processing

All string elements are processed one-by-one with the ETA JS template engine. The data section is processed in the first pass and the result is passed into subsequent template processing. Hence, one can collect reused parts under data section to avoid duplication.

Arrays-of-strings loaded from the template are joined into a multi-line string, processed at once and split based on linebreaks after processing. This can be used to generate arrays using a multiline template if required:

{
  "template": ["<% for elem in array %> {", "<%= elem.name %>\\n", "<% } %>"]
}

Notice the explicit newline character inserted after the template tag. The implicit newline resulting from concatenation is swallowed by the template processing if a template output data tag runs until the end of a line.

Template output data tags are typically used to create strings, similar to JavaScript format strings (backtick notation). When outputting objects or arrays, these are stringified using JavaScript Object Notation (JSON). If JSON is detected in a resulting launch or task configuration object, its converted back. E.g., one can achieve the following:

{
  "data": {
    "shell": {
      "win32": {
        "executable": "cmd.exe",
        "args": ["/d", "/c"]
      },
      "linux": {
        "executable": "/bin/bash",
        "args": ["-c"]
      },
      "darwin": {
        "executable": "/bin/bash",
        "args": ["-c"]
      }
    }
  },
  "tasks": [
    {
      "options": {
        "shell": "<%= data.shell[process.platform] %>"
      }
    }
  ]
}

To be transformed into

{
  "tasks": [
    {
      "options": {
        "shell": {
          "executable": "cmd.exe",
          "args": ["/d", "/c"]
        }
      }
    }
  ]
}

Plain numbers and boolean representation strings are converted to plain data type by default. If instead the value is required as a quoted string, this needs to be enforced explicitly.

{
  "data": {
    "number": "3000",
    "flag": "true"
  },
  "tasks": [
    {
      "options": {
        "plain-num": "<%= data.number %>",
        "quoted-num": "\"<%= data.number %>\"",
        "plain-bool": "<%= data.flag %>",
        "quoted-bool": "\"<%= data.flag %>\""
      }
    }
  ]
}

To be transformed into

{
  "tasks": [
    {
      "options": {
        "plain-num": 3000,
        "quoted-num": "3000",
        "plain-bool": true,
        "quoted-bool": "true"
      }
    }
  ]
}

Dynamic data structure

The following data structure is available to the templates:

data: { <custom data as specified> }
platform: <JavaScript process.platform>
solution_path: <path to .csolution.yml relative to workspace>
solution_folder: <base directory of .csolution.yml relative to workspace>
device_name: <name of target device>
target_type: <name of active csolution target-type>
start_pname: <processor name of primary processor if multi core device>
image_files: # image files used to program the device (image, image+symbol)
  - file: <image file name relative to solution_folder>
    pname: <processor name>
symbol_files: # symbol files with debug information (symbol, image+symbol)
  - file: <symbol file name relative to solution_folder>
    pname: <processor name>
ports: # GDB debug port mapping for all processors
  <pname>: <gdb-port>
config: # entire debugger node from .cbuild-run.yml
processors: # List of processors on a multi-core system
  - <pname>

In template expressions all functions in JavaScript global scope can be used. In addition, the following helper functions are available:

Function Description
Array<T>.groupedBy((e: T) => string): Map<string, T[]> Group elements of an array into a Map according to the given key-generator function.
Map<K, V>.every((v: V, k: K) => boolean): boolean Determines if all elements satisfy the given condition.
Map<K, V>.mapValues<T>((v: V, k: K) => T): Map<K, T> Transforms all elements with given function.
Map<K, V>.toObject(): Record<string, T> Converts the Map into a JavaScript object

Validation

The CI worklow validates the debugger adapter registry and templates by running linter and schema checker. Such validation steps can be reproduced in the local environment according to the following instructions.

prerequisite: npm to be installed in the system.

Linter

tl:dr

npm install
npm run lint

Install eslint and json/yaml plugins:

npm install --save-dev eslint eslint-plugin-jsonc eslint-plugin-yml eslint-formatter-compact

Lint debug adapters registry:

npx eslint --no-config-lookup --format compact --parser yaml-eslint-parser --plugin yml --ext .yml \
  --rule 'yml/quotes: ["error", { prefer: "double" }]' \
  --rule 'yml/indent: ["error", 2]' \
  --rule 'no-trailing-spaces: "error"' \
  registry

Lint templates:

npx eslint --no-config-lookup --format compact --parser jsonc-eslint-parser --plugin jsonc --ext .json \
  --rule 'jsonc/quotes: ["error", "double"]' \
  --rule 'jsonc/indent: ["error", 4]' \
  --rule 'no-trailing-spaces: "error"' \
  templates

Schema check

tl:dr

npm install
npm run schema

Install ajv:

npm install --save-dev ajv ajv-cli

Check debug adapters registry schema:

npx ajv -s schemas/debug-adapters.schema.json -d registry/debug-adapters.yml --strict=false

Check templates schema:

npx ajv -s schemas/templates.schema.json -d "templates/*.json" --strict=false

About

Contains the debug adapter registry and adapter templates

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors