Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix corrupted compound command results #127

Merged
merged 1 commit into from
Nov 9, 2021

Conversation

MisterHW
Copy link
Contributor

@MisterHW MisterHW commented Nov 6, 2021

When compound commands are used, e.g. in a scenario where the application controls hardware with multiple channels we found that some some parts go missing. *IDN?;*IDN? works, other queries that would return "0;1;2" only return "0;".

fix:
use netconn_write(u->io, data, len, NETCONN_COPY). NETCONN_NOCOPY is not allowed here, as data doesn't stay valid until sending is complete. See https://doc.ecoscentric.com/ref/lwip-api-sequential-netconn-write.html for details.

enhancement:
provide SCPI_ResultCommand() to facilitate prepending results with the command in question.

example: MEAS:VOLT:CH1?;CH2?;CH3?;CH4?:MEAS:CURR:CH1?
reply (prepend on): MEAS:VOLT:CH1,0.123;MEAS:VOLT:CH2,2.048;MEAS:VOLT:CH3,1.337;MEAS:VOLT:CH4,0;:MEAS:CURR:CH1,0.42
reply (default): 0.123;2.048;1.337;0;0.42

…ONN_COPY

Fix corrupted output when using chained queries and single queries with multiple return values. NETCONN_NOCOPY can only be used in cases like *IDN? where the buffer is const, which is used in tests and is probably why it hasn't been discovered.

netconn_write() documentation calling NETCONN_COPY "inefficient" may get people to generally avoid it, even if NETCONN_NOCOPY **cannot** be used, as is the case in SCPI_Write(). There would need to be a mechanism either for freeing buffers after use without copying, or one to ensure the corresponding tcp frame has been received by the client. Considering SCPI performance only really matters when low latency is key, or transfer of large amounts of block data is required - while at the same time the target has small amounts of memory and low performance - NETCONN_COPY is the obvious safe choice for this project.

"When passed the flag NETCONN_COPY the data is copied into internal buffers which are allocated for the data. This allows the data to be modified directly after the call, but is inefficient both in terms of execution time and memory usage. If the flag is not set then the data is not copied but rather referenced, and the NETCONN_NOCOPY manifest is provided for backwards compatibility. *The data must not be modified after the call*, since the data can be put on the retransmission queue for the connection, and stay there for an indeterminate amount of time."
@j123b567
Copy link
Owner

j123b567 commented Nov 8, 2021

Please keep in mind, that the library itself was never designed with multiple sessions in mind. It can fail hardly in more complex cases.

E.g. if you allow two simultanouse clients and one sends in one TCP packet *ID and in second packet N?\r\n and the other client will send in between MEAS?\r\n, then the result in the buffer for parsing will be *IDMEAS?\r\nN?\r\n which is wrong for both.

So in my opinion, the only correct way of solving this is to introduce real multi session ability. The easiest approach would be to have multiplle scipi_t context for each session and somehow share status of the device between them. So introduce some functions to have some "master" session and for every client, derive new "slave" session, which will be discarded, after client disconnect.

@j123b567 j123b567 linked an issue Nov 8, 2021 that may be closed by this pull request
@MisterHW
Copy link
Contributor Author

MisterHW commented Nov 8, 2021

I've been wondering about possible benefits for multiple sessions. While it's again not an issue with scpi-parser itself but a defect in the example I aim to resolve, a single line* sent in a single session, like

MEAS:VOLT:CH1?;CH2?;CH3?;CH4?:MEAS:CURR:CH1?\r\n

seems to produce garbled output. When sending

MEAS:VOLT:CH1?\r\n
MEAS:VOLT:CH2?\r\n
MEAS:VOLT:CH3?\r\n
MEAS:VOLT:CH4?\r\n
MEAS:CURR:CH1?\r\n

no issue is observed, though I haven't tested sending the commands in one go (only consecutively to ensure correct syntax and results). In its current state I believe the server example implementation has no means to manage the buffers it passes to netconn_write(), and its documentation points out that the buffers need to stay valid for an indeterminate amount of time (when kept in the re-send queue).

Copying buffers via NETCONN_COPY takes more resources, but I think it's the only legitimate way to use netconn_write() in the current example implementation. Other approaches will need a handler to be called when the tcp packet has been successfully received, or output to be written directly to a TX buffer.


(*) IEEE 488.2 allows the designer some discretion on how compound headers are handled
within the rules of section 7.6.1.5. SCPI imposes additional requirements regarding how a
compound command is parsed.
Multiple <PROGRAM MESSAGE UNIT> elements may be sent in a <PROGRAM
MESSAGE>. The first command is always referenced to the root node. Subsequent
commands, however, are referenced to the same tree level as the previous command in a
message unit.
https://www.ivifoundation.org/docs/scpi-99.pdf

@j123b567
Copy link
Owner

j123b567 commented Nov 8, 2021

NETCONN_NOCOPY vs NETCONN_COPY is deffinitely a problem which sould be solved. Buffer with data is reused, while it is sending, which is wrong.

But, I don't understand the rest of the PR.

SCPI specification allows multiple PROGRAM MESSAGE UNIT in PROGRAM MESSAGE but I don't know, if it allows multiple "queries" (commands ending with ?) in single message. It is possibly this library extension (I hope it is not against the spec to support it).

@MisterHW
Copy link
Contributor Author

MisterHW commented Nov 8, 2021

rest of the PR

The other two commits probably need to be in another branch and require some more thought / a separate PR. This PR can then focus on 9afb267.

@j123b567
Copy link
Owner

j123b567 commented Nov 8, 2021

So, can you please remove the other two commits so this can be easilly merged?

@MisterHW MisterHW force-pushed the multiple-commands branch 2 times, most recently from c5c59d7 to 9afb267 Compare November 8, 2021 11:21
@MisterHW MisterHW changed the title fix corrupted compound command results and provide key-value pair formatting fix corrupted compound command results Nov 8, 2021
@MisterHW
Copy link
Contributor Author

MisterHW commented Nov 8, 2021

two commits removed.

provide key-value pair formatting

will be revisited in another PR.

@j123b567 j123b567 merged commit 57a6620 into j123b567:master Nov 9, 2021
@MisterHW MisterHW deleted the multiple-commands branch November 9, 2021 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Possible to have multiple, independent scpi session?
2 participants