LPC55s28 SDK USB example are not working with -O2 optimization level

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC55s28 SDK USB example are not working with -O2 optimization level

Jump to solution
3,344 Views
emblink182
Contributor III

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.

Labels (1)
0 Kudos
Reply
1 Solution
3,264 Views
emblink182
Contributor III

Hi @Harry_Zhang 

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

 

View solution in original post

0 Kudos
Reply
11 Replies
1,902 Views
Swetha123
Contributor I

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.

0 Kudos
Reply
1,898 Views
emblink182
Contributor III
Hi Swetha123, have you tried the solution code posted on this topic?
0 Kudos
Reply
1,882 Views
Swetha123
Contributor I

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.

0 Kudos
Reply
1,854 Views
emblink182
Contributor III

Hi Swetha123, I don't have a 55s16 board so I can't debug your project. But looks like there is a typo in the code, please check the screenshots attached. I tried the same modifications on my 55s28 board and they worked fine with -O2 and -O3.

0 Kudos
Reply
1,735 Views
Swetha123
Contributor I

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.

0 Kudos
Reply
1,715 Views
emblink182
Contributor III
Hi Swetha123, I think it's something related to your specific project because my 55s28 board has the same USB hardware and uses the same SDK driver as yours 5516. Try to narrow down the search by using the technique suggested in this topic. Apply these preprocessor directives to suspected files or functions.

#pragma GCC push_options

#pragma GCC optimize ("O0")

#pragma GCC pop_options
0 Kudos
Reply
3,310 Views
frank_m
Senior Contributor III

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.

0 Kudos
Reply
3,298 Views
emblink182
Contributor III

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.

0 Kudos
Reply
3,279 Views
Harry_Zhang
NXP Employee
NXP Employee

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

3,265 Views
emblink182
Contributor III

Hi @Harry_Zhang 

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

 

0 Kudos
Reply
3,283 Views
frank_m
Senior Contributor III

> 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.