Closed matthijskooijman closed 1 year ago
Looking at this a bit more, I suspect that the problem might be caused by gcc reordering asm blocks, which it is apparantly allowed to do: https://gcc.gnu.org/legacy-ml/gcc-help/2017-10/msg00061.html
That thread also has some suggestions to prevent reordering by adding memory barriers (which I'm afraid would kill performance by forcing reloads of all memory across them), or by adding dependencies (which I think would keep the asm blocks in order, but not prevent inserting another one in between, which is probably the problem here), so just using unique labels seems to be a better approach.
I created a PR with this fix here: #91.
Ok I think the accepted PR fixed this, yes?
It has been a while, but yeah, I think so, I just forget to reference this issue in the commit. Closing.
TL;DR: While writing this issue, I found the cause of the issue, see the end of this post. I'll submit a PR next.
I just came back to a project using arduinounit, uploading a test suite I made earlier and then saw that the serial output was confusing: All messages about assertions said "passed" even though they seem failed.
The default
basic.ino
example gives me this output (on a custom ATmega2560 board, with both the 1.8.2 and 1.8.3 AVR core and arduinounit master):Adding some debug output shows that the test state variable is actually correct, and the right string is being printed, so I suspect that the string merging is somehow messing up, as done in https://github.com/mmurdoch/arduinounit/blob/b687ea4e797654c8270c751c9fb22352028a6a15/src/ArduinoUnitUtility/Flash.h#L11
This is confirmed by redefining
ARDUINO_UNIT_PSTR
to just use avr-libc standard (non-merging)PSTR
or removing theARDUINO_UNIT_STRING
macro from the print, i.e.:With either of those changes the output becomes correct again:
Looking at the preprocessed output (i.e. adding
-E
to the gcc commandline), I see this is being generated:So it actually seems that
__COUNTER__
is not being replaced. This also explains why not all strings are messed up, just the ones within the same function sinceptr__COUNTER__
probably ends up as a local variable in functions.I suspect that some additional machinery is needed to make sure that
__COUNTER__
is actually expanded. Normally, I think, macros within macros are not expanded, except when they contain a macro argument (at least when concatenation is involved), this is why concatenation macros are always use multiple levels). It seems that__COUNTER__
needs the same treatment: https://stackoverflow.com/a/27611869/740048I do wonder why this worked before (I also saw the problem with an older version of arduinounit which I'm pretty sure worked properly before, but maybe I rebased without checking...). Maybe older versions used different scopes for each
__extension__
block or so?However, I tried fixing this with additional macros and then got more errors because each invocation of
__COUNTER__
actually gives a separate number, so the definition and references to the variable will be different and thus break.It seems that the
__COUNTER__
approach was introduced in 60840b85adbedb40bce08b3fce836c8d2186c6cf to pretty much solve exactly this issue. However, for the test status (rather than assertion status) is actually fixed by no longer usingARDUINO_UNIT_STRING
making me believe that maybe the__COUNTER__
approach did not work and another approach was taken to fix the test status.So, I added some additiona macros to expand
__COUNTER__
only once, so all parts refer the sameptr
variable, and the problem still exists. So it turns out that theptr
variable was actualy local to theextension
block and was resolved properly, but somehow the string reference that's loaded into the variable is not.I see that the string address uses a fixed label
0:
to be loaded from. This looks like it should work, since numerical labels do not need to be unique and the0b
reference means "get the nearest label 0, going backwards", so that should get the right value. But somehow it ends up using the wrong label, but I'm not sure.However, since I just got the
__COUNTER__
stuff working, we can just use that to make the labels unique. I tried that and it seems to work, so maybe that's a good fix? I'll submit a PR in a minute.