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
1,394 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
1 Solution
1,314 Views
emblink182
Contributor III

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

 

View solution in original post

0 Kudos
5 Replies
1,360 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
1,348 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
1,329 Views
HangZhang
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

1,315 Views
emblink182
Contributor III

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

 

0 Kudos
1,333 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.