Hi,
creating a standard C++ project with the wizard on 11.0 build with a lot of strange errors. With SDK 2.5.0 everything is fine. "My" SDK is attached.
Simply choose new project, lpc845breakout board, the attached 2.6.0 SDK, empty board files, C++, newlibnano (semihost). Then try build it.
Solved! Go to Solution.
Now the (very, very tiny) fix works as expected, and that only 2 years later...
Hi @1234567890 and @dmarks_ls
Many thanks for your reports!
Please take a look at the LPC845 BRK SDK ver. 2.9.0. We changed the following lines:
#define CLK_MUX_DEFINE(reg, mux) (((offsetof(SYSCON_Type, reg) & 0xFFU) << 8U) | ((mux)&0xFFU))
#define CLK_DIV_DEFINE(reg) (((uint32_t)offsetof(SYSCON_Type, reg)) & 0xFFFU)
Now a CPP project should build without problems.
If somebody catches a problem in another SDK release, please let us know.
Yours ,
Diego
NXP,
Still waiting for you to acknowledge this issue in your software. Thanks.
Thank you for your feedback, we are checking this issue internally.
We will keep you informed.
Regards
Soledad
OK, this is definitely a bug, and I'm surprised that NXP QC allowed this to go out the door.
I encountered this exact same issue when I was upgrading my RT1050 project from MCUX 10.3.1 to MCUX v11.0.0. MCUX 11 uses the new version of the GCC 8 compiler, and apparently the C++ compiler is more strict about certain things that are generally OK in C code. Specifically, it is no longer a fan of dereferencing a null pointer in order to manually determine the offset of a struct member. Here are the offending macros in fsl_clock.h in your SDK:
/* clock mux register definition */
#define CLK_MUX_DEFINE(reg, mux) (((((uint32_t)(&((SYSCON_Type *)0U)->reg)) & 0xFFU) << 8U) | ((mux)&0xFFU))
[...]
/* clock divider register definition */
#define CLK_DIV_DEFINE(reg) (((uint32_t)(&((SYSCON_Type *)0U)->reg)) & 0xFFFU)
Each of those macros pretends that there is a SYSCON_Type struct located at address 0, then references the "reg" (macro parameter) field of that struct, takes the address of that field, and then converts the address to a uint32_t. Apparently this played nice in GCC 7 with C++ code, but GCC 8 flags this as an error (and correctly so):
../drivers/fsl_clock.h:173:64: note: in definition of macro 'CLK_DIV_DEFINE'
../drivers/fsl_clock.h:173:78: error: dereferencing a null pointer in '*0'
And since the value is borked, it then flags each and every enumeration value below, because now that value isn't a proper constant.
When I encountered this issue with my RT1050 project and MCUX 11, I was still using SDK 2.5.1. So I upgraded my SDK, and magically the issue went away... because NXP redefined those macros. Here's the "before":
#define CCM_TUPLE(reg, shift, mask, busyShift) \
(int)((((uint32_t)(&((CCM_Type *)0U)->reg)) & 0xFFU) | ((shift) << 8U) | \
((((mask) >> (shift)) & 0x1FFFU) << 13U) | ((busyShift) << 26U))
[...]
#define CCM_ANALOG_TUPLE(reg, shift) ((((uint32_t)(&((CCM_ANALOG_Type *)0U)->reg) & 0xFFFU) << 16U) | (shift))
And here's the "after":
#define CCM_TUPLE(reg, shift, mask, busyShift) \
(int)((reg & 0xFFU) | ((shift) << 8U) | \
((((mask) >> (shift)) & 0x1FFFU) << 13U) | ((busyShift) << 26U))
[...]
#define CCM_ANALOG_TUPLE(reg, shift) (((reg & 0xFFFU) << 16U) | (shift))
Basically, they just got rid of the "offset of" operation altogether. Now in the LPC845 code, I'm not sure if the same trick works. But, there's really no need to explicitly do a null pointer dereference... there's a standard C construct for this, offsetof() (located in stddef.h). If you look in stddef.h, you'll see that it's not defined the way it is in the Wikipedia article, but rather to call the intrinsic function of the compiler:
/* Offset of member MEMBER in a struct of type TYPE. */
#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
Replace the two offending macros in fsl_clock.h with these:
#define CLK_MUX_DEFINE(reg, mux) (((offsetof(SYSCON_Type, reg) & 0xFFU) << 8U) | ((mux)&0xFFU))
#define CLK_DIV_DEFINE(reg) (offsetof(SYSCON_Type, reg) & 0xFFFU)
I did this, and a basic C++ project for the LPC845 (using your supplied SDK) builds fine. Hope this helps.
NXP, you need to scrub all of your libraries for all of your supported parts, find every place where you explicitly dereference a null pointer to calculate the offset of a member, and use the "offsetof()" macro instead. Otherwise, that code will generate a compiler error whenever it's used in C++ code.
I'm having this same issue using MCUexpresso 11.2.0 and SDK 2.8.0 for LPC812. In my case the first patch for CLK_MUX_DEFINE fixed that problem, but with the patch for CLK_DIV_DEFINE I'm now getting a whole lot of errors like this:
../drivers/fsl_clock.h:244:27: note: in expansion of macro 'CLK_DIV_DEFINE'
244 | kCLOCK_IOCONCLKDiv0 = CLK_DIV_DEFINE(IOCONCLKDIV0),
| ^~~~~~~~~~~~~~
../drivers/fsl_clock.h:158:74: error: stray '\215' in program
Any ideas what the problem there is?
Ok, forget that, it seems there was a bad character or something in there from copy and pasting from the website. I typed it out manually and recompiled and that fixes the problem. Thanks for this post! NXP should really test their SDK with C++...
Please take a look at SDK 2.9 for LPC812. We added the changes to having a successful build after creating a CPP project.
Many thanks for your comments.
Diego.
Now the (very, very tiny) fix works as expected, and that only 2 years later...
Hi,
thanks a lot for your detailed description and the solution. Your patch solved the problem.
Glad I could help. NXP, please acknowledge the issue, thanks.
Can you provide some of the "strange errors"? I'm building a C++ project on RT1050 with SDK 2.6.0 just fine.