Repository navigation
feat(services): add hil terminal services for hardware-in-the-loop validation - #152
Merged
Merged
Conversation
…lidation services.hil provides a line-based OK/ERR/EVT command terminal (HilTerminal, Response, Arguments, PinNaming, PinPool, SystemCommands); services.hil.commands adds per-peripheral command groups written against hal:: interfaces, with HAL-supplied factories for opening drivers. TerminalWithCommandsImplBase gains command start/end and unrecognized-command hooks; CanMock, Ethernet mocks and SynchronousAdcMock are added to the test doubles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014WbtsfrCF7vqzVkHsKYMoX
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014WbtsfrCF7vqzVkHsKYMoX
Contributor
✅
|
| Descriptor | Linter | Files | Fixed | Errors | Max errors | Warnings | Elapsed time |
|---|---|---|---|---|---|---|---|
| ✅ ACTION | actionlint | 5 | 0 | 0 | 0.11s | ||
| ✅ ACTION | zizmor | 5 | 0 | 0 | 0 | 2.87s | |
| ✅ CPP | clang-format | 1317 | 10 | 0 | 0 | 9.57s | |
| ✅ DOCKERFILE | hadolint | 1 | 0 | 0 | 0.04s | ||
| ✅ JSON | jsonlint | 8 | 0 | 0 | 0.1s | ||
| ✅ JSON | prettier | 8 | 7 | 0 | 0 | 0.43s | |
| markdownlint | 30 | 7 | 52 | 0 | 2.15s | ||
| ✅ MARKDOWN | markdown-table-formatter | 30 | 7 | 0 | 0 | 0.36s | |
| betterleaks | yes | 1 | 4 | 1.19s | |||
| ✅ REPOSITORY | checkov | yes | no | no | 36.95s | ||
| ✅ REPOSITORY | git_diff | yes | no | no | 0.1s | ||
| ✅ REPOSITORY | grype | yes | no | no | 113.56s | ||
| ✅ REPOSITORY | ls-lint | yes | no | no | 0.02s | ||
| ✅ REPOSITORY | secretlint | yes | no | no | 68.61s | ||
| ✅ REPOSITORY | syft | yes | no | no | 1.7s | ||
| ✅ REPOSITORY | trivy | yes | no | no | 14.77s | ||
| ✅ REPOSITORY | trivy-sbom | yes | no | no | 0.32s | ||
| ✅ REPOSITORY | trufflehog | yes | no | no | 4.27s | ||
| lychee | 215 | 2 | 0 | 97.98s | |||
| ✅ YAML | prettier | 8 | 8 | 0 | 0 | 0.55s | |
| ✅ YAML | v8r | 8 | 0 | 0 | 6.62s | ||
| ✅ YAML | yamllint | 8 | 0 | 0 | 0.55s |
Detailed Issues
⚠️ REPOSITORY / betterleaks - 1 error
warning: private-key has detected secret for file services/network/tls/test_doubles/Certificates.cpp.
┌─ services/network/tls/test_doubles/Certificates.cpp:56:15
│
56 │ "HIDDEN_BY_MEGALINTER\r\n";
│ ╰──────────────────────────────────────────^
warning: private-key has detected secret for file services/network/tls/test_doubles/Certificates.cpp.
┌─ services/network/tls/test_doubles/Certificates.cpp:108:15
│
108 │ "HIDDEN_BY_MEGALINTER\r\n";
│ ╰──────────────────────────────────────────^
warning: private-key has detected secret for file services/network/tls/CertificatesMbedTls.cpp.
┌─ services/network/tls/CertificatesMbedTls.cpp:125:21
│
125 │ stream << "HIDDEN_BY_MEGALINTER\r\n";
│ ╰────────────────────────────────────────────────^
warning: generic-api-key has detected secret for file services/network/websocket/WebSocket.cpp.
┌─ services/network/websocket/WebSocket.cpp:81:64
│
81 │ headers.push_back(services::HttpHeader("Sec-Websocket-Key", "AQIDBAUGBbgJCgsMDQ4PEC=="));
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: 4 warnings emitted
⚠️ SPELL / lychee - 2 errors
📝 Summary
---------------------
🔍 Total..........489
🔗 Unique.........448
✅ Successful.....487
⏳ Timeouts.........0
🔀 Redirected.....188
👻 Excluded.........0
❓ Unknown..........0
🚫 Errors...........2
⛔ Unsupported......2
Errors in docs/index.md
[404] https://github.com/embedded-pro/embeddedinfralib/issues/37 (at 41:167) | Rejected status code: 404 Not Found
Errors in external/protoc/CMakeLists.txt
[404] https://github.com/protocolbuffers/protobuf/releases/download/v$%7Bprotobuf_tag%7D/protoc-$%7Bprotobuf_version%7D-$%7Bos_postfix%7D.zip (at 18:13) | Rejected status code: 404 Not Found
Hint: Followed 188 redirects. You might want to consider replacing redirecting URLs with the resolved URLs. Use verbose mode (`-v`/`-vv`) to see redirection details.
Hint: You can configure accepted/rejected response codes with `-a` or `--accept`
⚠️ MARKDOWN / markdownlint - 52 errors
.claude/agents/executor.md:7 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "You are the executor agent for..."]
.claude/agents/orchestrator.md:7 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "You are the orchestrator agent..."]
.claude/agents/planner.md:7 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "You are the planner agent for ..."]
.claude/agents/reviewer.md:7 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "You are the reviewer agent for..."]
.github/agents/executor.agent.md:11 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "You are the executor agent for..."]
.github/agents/executor.agent.md:108:401 error MD013/line-length Line length [Expected: 400; Actual: 416]
.github/agents/orchestrator.agent.md:18 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "You are the orchestrator agent..."]
.github/agents/planner.agent.md:11 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "You are the planner agent for ..."]
.github/agents/planner.agent.md:89:401 error MD013/line-length Line length [Expected: 400; Actual: 609]
.github/agents/reviewer.agent.md:14 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "You are the reviewer agent for..."]
.github/agents/reviewer.agent.md:116:401 error MD013/line-length Line length [Expected: 400; Actual: 514]
.github/prompts/orchestrate.prompt.md:8 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "Analyze the following task for..."]
docs/Ble.md:156:401 error MD013/line-length Line length [Expected: 400; Actual: 545]
docs/CodingStandard.md:98:401 error MD013/line-length Line length [Expected: 400; Actual: 457]
docs/CodingStandard.md:481:401 error MD013/line-length Line length [Expected: 400; Actual: 670]
docs/Containers.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 537]
docs/Containers.md:11:401 error MD013/line-length Line length [Expected: 400; Actual: 566]
docs/Containers.md:24:401 error MD013/line-length Line length [Expected: 400; Actual: 454]
docs/Containers.md:46:401 error MD013/line-length Line length [Expected: 400; Actual: 812]
docs/Containers.md:86:401 error MD013/line-length Line length [Expected: 400; Actual: 557]
docs/Echo.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 508]
docs/Echo.md:7:401 error MD013/line-length Line length [Expected: 400; Actual: 416]
docs/Echo.md:38:401 error MD013/line-length Line length [Expected: 400; Actual: 511]
docs/Echo.md:49:401 error MD013/line-length Line length [Expected: 400; Actual: 476]
docs/Echo.md:53:401 error MD013/line-length Line length [Expected: 400; Actual: 554]
docs/Echo.md:59 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/Echo.md:65 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/Echo.md:73:401 error MD013/line-length Line length [Expected: 400; Actual: 887]
docs/ExecutionModel.md:7:401 error MD013/line-length Line length [Expected: 400; Actual: 632]
docs/ExecutionModel.md:9:401 error MD013/line-length Line length [Expected: 400; Actual: 834]
docs/ExecutionModel.md:11:401 error MD013/line-length Line length [Expected: 400; Actual: 642]
docs/ExecutionModel.md:15:401 error MD013/line-length Line length [Expected: 400; Actual: 812]
docs/ExecutionModel.md:19:401 error MD013/line-length Line length [Expected: 400; Actual: 456]
docs/ExecutionModel.md:27:401 error MD013/line-length Line length [Expected: 400; Actual: 724]
docs/index.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 570]
docs/index.md:9 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/MemoryRange.md:3:401 error MD013/line-length Line length [Expected: 400; Actual: 862]
docs/MemoryRange.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 441]
docs/NetworkConnections.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 439]
docs/NetworkConnections.md:9:401 error MD013/line-length Line length [Expected: 400; Actual: 496]
docs/Sesame.md:9 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/Sesame.md:25:401 error MD013/line-length Line length [Expected: 400; Actual: 445]
docs/Sesame.md:29 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/Sesame.md:41 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/Sesame.md:58 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/Sesame.md:73 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/Sesame.md:91 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/Sesame.md:120 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
external/crypto/tiny-aes128/README.md:1 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "### Tiny AES128 in C"]
external/crypto/tiny-aes128/README.md:29 error MD046/code-block-style Code block style [Expected: fenced; Actual: indented]
external/crypto/tiny-aes128/README.md:39 error MD046/code-block-style Code block style [Expected: fenced; Actual: indented]
external/crypto/tiny-aes128/README.md:49 error MD046/code-block-style Code block style [Expected: fenced; Actual: indented]
Notices
REPOSITORY_GITLEAKS, REPOSITORY_KICS. See Removed linters to find their replacements.
See detailed reports in MegaLinter artifacts
Your project could benefit from a custom flavor, which would allow you to run only the linters you need, and thus improve runtime performances. (Skip this info by defining FLAVOR_SUGGESTIONS: false)
- Documentation: Custom Flavors
- Command:
npx mega-linter-runner@10.0.0 --custom-flavor-setup --custom-flavor-linters ACTION_ACTIONLINT,ACTION_ZIZMOR,CPP_CLANG_FORMAT,DOCKERFILE_HADOLINT,JSON_JSONLINT,JSON_PRETTIER,MARKDOWN_MARKDOWNLINT,MARKDOWN_MARKDOWN_TABLE_FORMATTER,REPOSITORY_CHECKOV,REPOSITORY_GIT_DIFF,REPOSITORY_BETTERLEAKS,REPOSITORY_GRYPE,REPOSITORY_LS_LINT,REPOSITORY_SECRETLINT,REPOSITORY_SYFT,REPOSITORY_TRIVY,REPOSITORY_TRIVY_SBOM,REPOSITORY_TRUFFLEHOG,SPELL_LYCHEE,YAML_PRETTIER,YAML_YAMLLINT,YAML_V8R

Show us your support by starring ⭐ the repository
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014WbtsfrCF7vqzVkHsKYMoX
…efix Types move from services::hil to services and carry a Hil prefix (HilResponse, HilArguments, HilGpioCommands, HilUartFactory, ...); files are renamed to match. Also addresses SonarCloud findings: default memory order on atomics, explicit optional has_value checks, no side effects in logical operands, no strlen, const member functions, ranges algorithms, and explicit narrowing in TerminalBase. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014WbtsfrCF7vqzVkHsKYMoX
- HilInstanceFactory and HilSingleInstanceGroup share the open/close lifecycle of the single-instance groups - HilPendingOperation replaces four copies of busy/timeout/generation handling (uart send, spi transfer, can send, eeprom) - reuse infra::AtomicTriggerScheduler (watchdog early warning) and infra::TimerLimitedRepeating (gpio pulse) - HilEdge/HilEdgeCounter shared by gpio and comparator - hal::DutyCycle::FromRatio, used by FromPercent and duty parsing - uart receive uses ContiguousRange/Consume; can uses the BoundedVector range constructor - SynchronousPwmMock gets its own header guard and a real base - link docs/Hil.md from the README Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014WbtsfrCF7vqzVkHsKYMoX
Subclasses reach the context, instance and pin owner through protected accessors; uart queue consumption narrows explicitly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014WbtsfrCF7vqzVkHsKYMoX
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Adds
services/hil, a HAL-independent command terminal for hardware-in-the-loop validation. It was extracted from hal-ti's validation firmware (embedded-pro/hal-ti#120), so any HAL, e.g. hal-st, can expose its drivers to a host test bench such as ad3-waveforms-bench.A HAL supplies only three things:
*.openarguments to the driver'sConfigEverything lives directly in
namespace services. Public types carry aHilprefix, following the existingSesame*/Http*convention. Documentation is indocs/Hil.md, linked from the README anddocs/index.md.services.hil: frameworkHilTerminal: aTerminalWithCommandsImplBasethat brackets each command line and answersERR usageto unknown commands.HilResponse: the line protocol.OK [k=v...]/ERR <reason>/EVT <peripheral> [k=v...]\r\nprefix on lines produced outside a commandHilArguments: parses positionals andkey=value,0xnumbers, hex payloads (-for empty), duty cycles, choice tables and pins.HilPinId,HilPullandHilPinNaming(HilPinNamingDefaultis configurable for TivaPF1(0–7) or STM32PA15)HilPinPool: owner bitmask, analog sharing, reserved pins, over an injectedHilPinFactoryHilSystemCommands:ping,delay,reset(viahal::Reset),info,board.pins, and theEVT bootline, usingHilBoardInfo.HilBind, which has a const-method overload,HilWithDriverandHilDeadlineTimeKeeper.services.hil.commands: per-peripheral groups overhal::interfaceshal::GpioPin(config, set, get, pulse, interrupts with edge counters)hal::SerialCommunication,SynchronousSerialCommunicationhal::SpiMaster,SynchronousSpihal::AdcMultiChannel,SynchronousAdc; the HAL defines the instance keyhal::Can; receive and errorEVTshal::Eeprom; always answers from the completion callbackHilPwmHandle+HilPwmAdapter<Driver>overSingle…FourChannelsPwm(sync or async)SynchronousQuadratureEncoderAnalogComparator,SynchronousAnalogComparatorhal::Watchdog; early-warningEVT, auto-feedHilEthernetMonitoroverEthernetSmi/EthernetMacHilUnsupportedCommandsanswersERR unsupportedfor peripherals the running MCU lacks.Shared building blocks:
HilInstanceFactory+HilSingleInstanceGroup: one open/close lifecycle shared by six groups.PreparethenOpen, so argument errors come beforebusyand pins are claimed only after it.HilPendingOperation: one busy/timeout/stale-completion helper, used by UART, SPI, CAN and EEPROM.HilEdge/HilEdgeCounter: shared by GPIO and the comparator.Reuses existing EMIL facilities:
infra::AtomicTriggerScheduler,infra::TimerLimitedRepeating,QueueForOneReaderOneIrqWriter::ContiguousRange/Consume, theBoundedVectorrange constructor,infra::AsHex,infra::TokenizerandTracer::Continue.Changes to existing code
TerminalWithCommandsImplBasegains protected virtualOnCommandStart(),OnCommandEnd()andOnUnrecognizedCommand(); the defaults keep today's behaviour.TerminalBasenarrowing conversions are now explicit.hal::DutyCycle::FromRatio(numerator, denominator):FromPercentuses it, with identical results.CanMock,EthernetSmiMock/EthernetMacMock,SynchronousAdcMock.SynchronousPwmMock.hppshared the header guardHAL_PWM_MOCK_HPPwithPwmMock.hpp, so including both silently dropped one. It also mockedStartwithout overriding anything. It now has its own guard and derives fromSynchronousSingleChannelPwm.TerminalCommandsStubinTestTerminal.cppkept its commands in astaticarray whose lambdas captured the first instance'sthis. The array is now a member.Verification
host-single-Debug(warnings as errors):services.hil_test: 133/133services.util_test: 149/149hal.interfaces_test: 73/73embeddedpreset (Cortex-M4): both libraries compile with warnings as errors.claude/hil-on-emil-services, pinned to this PR's head) builds from a clean FetchContent for TM4C123 and TM4C129.eeprom.readnow answers as a deferred line.Notes
docs/Hil.mdsays so.hal::cortex::Reset::ResetModulewrites AIRCR with no__DSB()and then returns, unlikeNVIC_SystemReset.🤖 Generated with Claude Code
https://claude.ai/code/session_014WbtsfrCF7vqzVkHsKYMoX