Hello, I have an issue with the SDK USB examples code on the LPC55S28 dev board.
The default optimization level on Release builds is set to -Os, and with it, the examples are working fine.
However, when I change the optimization level to -O2 examples stop working. USB FS/HS device can't enumerate.
For demonstration, I took lpcxpresso55s28_dev_hid_generic_freertos, because I have to use RTOS in my application, but I believe this issue applies to bare metal and other USB examples also.
No code changes were made to the example.
All manipulations were done on the latest SDK and MCUXpresso IDE version, all of my board and project settings are attached.
Please help to solve this issue.
解決済! 解決策の投稿を見る。
Hi @HangZhang
Thanks for the search direction, I found the solution. It turned out that this bug was reported previously back in 2021, by @cgarcia in this post
But his fix wasn't added in the SDK for some reason.
Please add it, cause all of the USB examples have the same issue for HS and FS.
#if (defined USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS)
CLOCK_EnableClock(kCLOCK_Usbh1);
/* Put PHY powerdown under software control */
volatile uint32_t registerAddress = USBHSH_BASE + 0x50; // TODO: Add
*((uint32_t *)(registerAddress)) = USBHSH_PORTMODE_SW_PDCOM_MASK; // TODO: Add
//TODO: REMOVE *((uint32_t *)(USBHSH_BASE + 0x50)) = USBHSH_PORTMODE_SW_PDCOM_MASK;
/* According to reference mannual, device mode setting has to be set by access usb host register */
*((uint32_t *)(registerAddress)) |= USBHSH_PORTMODE_DEV_ENABLE_MASK; // TODO: Add
//TODO: REMOVE *((uint32_t *)(USBHSH_BASE + 0x50)) |= USBHSH_PORTMODE_DEV_ENABLE_MASK;
/* enable usb1 host clock */
CLOCK_DisableClock(kCLOCK_Usbh1);
#endif
#if (defined USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS)
POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*< Turn on USB Phy */
CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false);
CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
/* enable usb0 host clock */
CLOCK_EnableClock(kCLOCK_Usbhsl0);
/*According to reference mannual, device mode setting has to be set by access usb host register */
//TODO: REMOVE*((uint32_t *)(USBFSH_BASE + 0x5C)) |= USBFSH_PORTMODE_DEV_ENABLE_MASK;
volatile uint32_t registerAddress = USBFSH_BASE + 0x5C; // TODO: Add
*((uint32_t *)(registerAddress)) |= USBFSH_PORTMODE_DEV_ENABLE_MASK; // TODO: Add
/* disable usb0 host clock */
CLOCK_DisableClock(kCLOCK_Usbhsl0);
#endif
Hello, Greetings.
I need to optimize my project at the O3 level for LPC5516 board, which uses HS-USB.
The fact that USB is not identified in the device manager after O3 and O2 optimization indicates that USB is not working.
Please assist with helping me resolve this issue.
Hello, emblink182. I appreciate your speedy response.
We tried the recommended solution but saw no progress.
Even using the SDK "lpcxpresso55s16_dev_cdc_vcom_freertos" with O3 and O2 optimization did not work.
SDK Version: 2.14.0.
Manifest version: 3.13.0.
IDE version: MCUXpresso IDE 11.8.0 [Build 1165] [2023-07-26]
I've attached the source file for reference.
Hello, emblink182
Apologies for the delayed response. After correcting the typo once more, we were able to run the USB SDK at the O2 level, but the O3 level is still not functioning.
The same piece of solution was patched to the project where HS-USB operates, however it still fails in O2 and O3.
However, in the project, we discovered that USB began to function at the O2 level when the usb initialization function was called from the main accessible in the USB source file "virtual_com.c", but failed when the usb initialization function was called from the main produced in our project.
To be honest, IMHO this is a common occurence.
Most vendor-supplied free libraries are not fit for aggressive optimisations, and robust commercial deployment. These libraries are churned out in far too much variants and too short timeframe to allow for proper (and costly) testing.
And in my experience this applies to all other vendors, too.
The "-O2" optimisation is a general setting. You could try to disable certain specific optimisations implied by O2, and see if it works.
Or you can try to debug the code, which could be quite surprising and confusing with high optimisation.
One common mistake is for instance the neglect of declaring all variables written to in interrupts as "volatile".
In rare cases high optimisation settings expose compiler bugs, but I think this is rather unlikely in this case.
Hi frank_m
So far most of their examples worked great, which means they tested them. But if all SDK USB examples simply do not work with the -O2, it means they didn't test this case at all, and should look at this problem.
-O2 is not something rare it's a common optimization for production code. My code requires it.
LPC MCUs aren't the cheapest on the market, and many devices are built on these platforms, so decent testing, support, and bug fixing are expected in this case.
Hi @emblink182
I tested lpcxpresso55s28_dev_hid_generic_freertos, the project with optimization level ' -O2' can not work.
I have work around, you can try. I change the hig_generit.c optimization level to -O0, it can work.
Another way, in hig_generit.c, you can
#pragma GCC push_options
#pragma GCC optimize ("O2")
main{}
#pragma GCC pop_options
It also can work.
And I will report this issue to our SDK team.
Best regards,
Hang
Hi @HangZhang
Thanks for the search direction, I found the solution. It turned out that this bug was reported previously back in 2021, by @cgarcia in this post
But his fix wasn't added in the SDK for some reason.
Please add it, cause all of the USB examples have the same issue for HS and FS.
#if (defined USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS)
CLOCK_EnableClock(kCLOCK_Usbh1);
/* Put PHY powerdown under software control */
volatile uint32_t registerAddress = USBHSH_BASE + 0x50; // TODO: Add
*((uint32_t *)(registerAddress)) = USBHSH_PORTMODE_SW_PDCOM_MASK; // TODO: Add
//TODO: REMOVE *((uint32_t *)(USBHSH_BASE + 0x50)) = USBHSH_PORTMODE_SW_PDCOM_MASK;
/* According to reference mannual, device mode setting has to be set by access usb host register */
*((uint32_t *)(registerAddress)) |= USBHSH_PORTMODE_DEV_ENABLE_MASK; // TODO: Add
//TODO: REMOVE *((uint32_t *)(USBHSH_BASE + 0x50)) |= USBHSH_PORTMODE_DEV_ENABLE_MASK;
/* enable usb1 host clock */
CLOCK_DisableClock(kCLOCK_Usbh1);
#endif
#if (defined USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS)
POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*< Turn on USB Phy */
CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false);
CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
/* enable usb0 host clock */
CLOCK_EnableClock(kCLOCK_Usbhsl0);
/*According to reference mannual, device mode setting has to be set by access usb host register */
//TODO: REMOVE*((uint32_t *)(USBFSH_BASE + 0x5C)) |= USBFSH_PORTMODE_DEV_ENABLE_MASK;
volatile uint32_t registerAddress = USBFSH_BASE + 0x5C; // TODO: Add
*((uint32_t *)(registerAddress)) |= USBFSH_PORTMODE_DEV_ENABLE_MASK; // TODO: Add
/* disable usb0 host clock */
CLOCK_DisableClock(kCLOCK_Usbhsl0);
#endif
> So far most of their examples worked great, which means they tested them. But if all SDK USB examples simply do not work with the -O2, it means they didn't test this case at all, and should look at this problem.
> LPC MCUs aren't the cheapest on the market, and many devices are built on these platforms, so decent testing, support, and bug fixing are expected in this case.
The problem is, what effort can you expect for free ?
Take the large number different MCUs and variants into account that require support.
Being involved with safety-related applications and code, efforts for testing, validating and documenting is a multiple of the time required for coding. A few years ago, my company purchased licenses for a safety-certified RT-OS for a six-figure sum - assessing this to be cheaper than developing it ourselves.
> -O2 is not something rare it's a common optimization for production code. My code requires it.
You have two options, I would say.
The first one is to locate the bug, and try to fix it. This might take some time, effort and experience.
The second option is to lower the bar. You could reduce the optimisation level to e.g. "-O1". This can be done on file level, and with some effort even on function level.
Or, you can get into optimisation details.
As said, "-O1" and "-O2" are just overall settings, that switch a number of individual optimisations on or off. Here the meaning for the GCC : https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
You can try to leave O2 active and explicitly disable individual optimisations until the code works fine.