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

Allow non-aligned PSTR() #7275

Merged
merged 5 commits into from
May 18, 2020
Merged

Allow non-aligned PSTR() #7275

merged 5 commits into from
May 18, 2020

Conversation

s-hadinger
Copy link
Contributor

PSTR() are by default aligned to 32-bits boundaries, whereas normal string are not. I understand the speed benefit, but it consumes some additional Flash, which is around 1.7KB for Tasmota.

This change allows to override this default behavior and allow non-aligned PSTR() with #define PSTR_ALIGN 1.

There is no change if you don't explicitly set this flag as compile option -DPSTR_ALIGN=1.

Currently the only way in Tasmota to achieve the same result is to override the entire PSTR() macro with:

-DPSTR\(s\)=\(__extension__\(\{static\ const\ char\ __c\[\]\ __attribute__\(\(__aligned__\(1\)\)\)\ __attribute__\(\(section\(\ \"\\\\\".irom0.pstr.\"\ __FILE__\ \".\"\ __STRINGIZE\(__LINE__\)\ \".\"\ \ __STRINGIZE\(__COUNTER__\)\ \"\\\\\"\,\ \\\\\"aSM\\\\\"\,\ \@progbits\,\ 1\ \#\"\)\)\)\ =\ \(s\)\;\ \&__c\[0\]\;\}\)\

@earlephilhower
Copy link
Collaborator

That's one hell of an ugly command line #define! Do you really have ~1,000 separate strings in flash? Or, am I missing something with the comment in the header?

Can you also please put in the same PR to https://github.com/earlephilhower/newlib-xtensa ? The newlib-xtensa is the original source of this header, and when we update the library or compiler, if it's not in that other repo changes will get lost.

@s-hadinger
Copy link
Contributor Author

I counted 1128 PSTRs in Tasmota. And I agree this is the ugliest command line option I've ever seen. I maybe escaped too much, but I won't optimize it.

I will do the PR in newlib-xtensa too.

@mhightower83
Copy link
Contributor

mhightower83 commented May 6, 2020

Can we add a PSTR16() PSTR4() to give the old behavior? Printing from umm_info() umm_info(NULL, true) is using a (heap-less) print function that relies on 16 4-byte alignment. It will need to be updated. I also have at least one other PR that depends on 16 4-byte alignment.

Edited: changed reference to 16 to 4-byte alignment.

@earlephilhower
Copy link
Collaborator

@mhightower83 are you sure about the 16 byte alignment thing? I am pretty sure we never had a 16 byte aligned PSTR. It used to be packed, byte-wise (which is what this PR is enabling)...

@mhightower83
Copy link
Contributor

Oops, brain fog today that should have been 4 bytes. PSTR4()

@devyte
Copy link
Collaborator

devyte commented May 7, 2020

@s-hadinger as @mhightower83 said, there may be issues with changing the alignment. How much have you tested with that macro override?

@s-hadinger
Copy link
Contributor Author

I didn't think this could be an issue since regular strings are not 4-bytes aligned.

I have Tasmota devices running for a few days with this macro and didn't observe any issue or crash. There was no issue reported on Discord either, but it's still a recent change.

@mhightower83
Copy link
Contributor

I would expect a possible problem when umm_info(NULL, true) is called. The print code uses ets_strcpy() and ets_strlen() which is only safe with word-aligned strings when using PROGMEM. I don't think this would be used in production code, the printed results can only be seen on the serial port. Thus, I expect calls to umm_info(NULL, false), which does not print, would be harmless.

@earlephilhower
Copy link
Collaborator

earlephilhower commented May 7, 2020

-edit- I see we crossposted, but had the same answer. :)

@s-hadinger, it's a little more complicated than that. RAM is fine reading byte-wide, but IROM(PSTR) needs special instructions to only to 32-bit reads and extract the byte needed.

The main library routines (all printf* variants, strcpy, etc.) all work with any alignment of data in strings.

However, @mhightower83 has some routines in a special-use section that need to be 4 byte aligned because his code can't afford to do the adjustments.

@s-hadinger
Copy link
Contributor Author

Good to know. As far as I know, we don't compile with umm_info() enabled in Tasmota.

The only places where I found a use of umm_info_safe_printf_P was using the DBGLOG_FORCE which is used in umm_info.c with RAM strings only, no PSTR().

Did I miss something?

Anyways, there is no harm in adding a PSTR4() variant for 4-bytes aligned PSTR strings.

@mhightower83
Copy link
Contributor

@s-hadinger, sorry there is a bit of macro nesting going on here to make it easier to change things as a group:

#define DBGLOG_FORCE(force, format, ...) {if(force) {UMM_INFO_PRINTF(format, ## __VA_ARGS__);}}

#define UMM_INFO_PRINTF(fmt, ...) umm_info_safe_printf_P(PSTR(fmt), ##__VA_ARGS__)

and I think only that last line will need to be changed to use PSTR4()

@s-hadinger
Copy link
Contributor Author

@mhightower83 thanks, I missed that macro.

@earlephilhower I changed the PR to add PSTR4() macro and changed the UMM_INFO_PRINTF() macro accordingly.

Copy link
Collaborator

@earlephilhower earlephilhower left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thx. We should get @mhightower83 to chime in, too.

@mhightower83
Copy link
Contributor

Thanks! LGTM.

@s-hadinger
Copy link
Contributor Author

Gentle bump. Is there anything more needed for merging?

@earlephilhower
Copy link
Collaborator

@s-hadinger can you also port these final changes to newlib so they don't get lost? Thx!

@devyte devyte merged commit 3e4d7c7 into esp8266:master May 18, 2020
@s-hadinger s-hadinger deleted the patch-2 branch May 19, 2020 07:09
s-hadinger added a commit to s-hadinger/newlib-xtensa that referenced this pull request May 19, 2020
@sparkplug23
Copy link

With either 1 or 4 byte alignment I am getting crashes on my own code, which uses PSTR in the way tasmota does. To be specific "loadProhibited" and errors related to alignment when trying to use debug builds with vscode/platformio. Did you come across this and if so did you manage to clear the error. Many thanks.

@s-hadinger
Copy link
Contributor Author

@sparkplug23 Can you share the code of where it crashes?

@sparkplug23
Copy link

@s-hadinger Thanks for replying. After spending days on this, as it always happens, the second you ask for help you find the problem! It seems I was using a PSTR incorrectly with sprintf, I am amazed this worked in release mode but not debug builds. Hopefully this was my only issue, I could be back haha. Great work on the code. I have around 2000 PSTRs in my code, so I know the feeling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants