Similar to other issues I have had with other SDK samples (FatFS/SDcard), it seems that caching causes problems with USB device samples.
If I switch one of the samples (such as: dev_hid_mouse_bm) to use SRAM_OC as location of global vars, then USB will fail to enumerate.
I have also tried setting the config buffer to be cacheable in usb_device_config.h, but that causes USB device initialization to fail completely.
How can I use the USB stack when running from OCRAM?
Solved! Go to Solution.
Hello guys,
In cases when a cacheable RAM region is being used as main RAM for the application it will be necessary to relocate the USB descriptors and data to a non cacheable memory. The following changes in the project will take care of this relocation:
#else
#define USB_GLOBAL USB_LINK_USB_GLOBAL_BSS
#define USB_BDT USB_LINK_USB_BDT_BSS
#define USB_DMA_DATA_NONINIT_SUB USB_LINK_NONCACHE_NONINIT_DATA
#define USB_DMA_DATA_INIT_SUB
#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA
#endif
With the above configuration, the USB descriptors and data will be placed in the SRAM_DTC region, the same changes apply if you want to use the Non cacheable SDRAM region, you just need to change the region you want to use in the configuration above.
Hope this helps.
Regards,
Carlos Mendoza
I tried defining sections to match what is in the USB macros of usb_misc.h, but it still didn't fix the issue.
Hi Jack,
In fact, not only USB, but also ENET has this phenomenon. This is because these bus masters put their control and data exchange blocks in RAM, for example, USB Periodic Frame List. Since TCM do not need cache, anything written by USB/ENET peripheral can be read by MCU directly. But if you put these blocks in OCRAM, MCU will not know if the data is changed by other master. MCU will still read data from cache but not refresh it. So, if you hope to make full use of OCRAM, you should keep these control and data exchange blocks in DTCM, or close cache function.
Regards,
Jing
Jing,
My biggest issue with the RT1050 SDK software right now is that this software has been provided in a state where much of the middleware (USB, lwIP, FatFS) does not function correctly on a platform where any memory other than (non-cacheable) SRAM_DTC is used for global data. For a chip where the official eval board has 32 MB of SDRAM, forcing all global data into 128 KB is incredibly constraining and for many use cases impossible. It is frustrating to NXP's customers to provide them this RT1050 software as-is, then only provide general advice when those customers inevitably incur multiple hours of development cost while discovering, reporting, and mitigating these issues. SDK examples need to function correctly regardless of what memory region is used for global data.
Hui_Ma / Mike has done a great job investigating these issues and fielding my concerns; it is my hope you will work closely with him and the rest of the SDK team to resolve these deficiencies in the SDK software, rather than leaving these issues as an exercise for the reader. Thanks.
David R.
Hello guys,
In cases when a cacheable RAM region is being used as main RAM for the application it will be necessary to relocate the USB descriptors and data to a non cacheable memory. The following changes in the project will take care of this relocation:
#else
#define USB_GLOBAL USB_LINK_USB_GLOBAL_BSS
#define USB_BDT USB_LINK_USB_BDT_BSS
#define USB_DMA_DATA_NONINIT_SUB USB_LINK_NONCACHE_NONINIT_DATA
#define USB_DMA_DATA_INIT_SUB
#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA
#endif
With the above configuration, the USB descriptors and data will be placed in the SRAM_DTC region, the same changes apply if you want to use the Non cacheable SDRAM region, you just need to change the region you want to use in the configuration above.
Hope this helps.
Regards,
Carlos Mendoza
Carlos - that answer was super helpful for me to get stated. I just would like another option. The NonCacheable section could also assigned to the OCRAM memory region.
/* Region 5 setting */
MPU->RBAR = ARM_MPU_RBAR(5, 0x20210000);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 0, 1, 0, ARM_MPU_REGION_SIZE_64KB);
This example kind of fragments the memory, but it should work well enough to get started running the USB demo completely in OCRAM.
were you able to run the USB code on SRAM_OC with the above changes?.
i have been trying the above changes, but the USB enumeration is failing.
this is my board.c changes
/* Region 5 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(5, 0x00000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB);
/* Region 6 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(6, 0x20000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB);
/* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(7, 0x20200000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256B-ARM_MPU_REGION_SIZE_32KB);
/*Region 11 for sram oc non cache area */
MPU->RBAR = ARM_MPU_RBAR(11, 0x20238000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 0, 1, 0, ARM_MPU_REGION_SIZE_32KB);
/* Region 8 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(8, 0x80000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_32MB);
while ((size >> i) > 0x1U)
{
i++;
}
if (i != 0)
{
/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
assert(!(nonCacheStart % size));
assert(size == (uint32_t)(1 << i));
assert(i >= 5);
/* Region 9 setting: Memory with Normal type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(9, nonCacheStart);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1);
}
/* Region 10 setting: Memory with Device type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(10, 0x40000000);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_4MB);
/* Enable MPU */
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
my usb_misc.h changes
#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA
#else
#define USB_GLOBAL USB_LINK_USB_GLOBAL_BSS
#define USB_BDT USB_LINK_USB_BDT_BSS
#define USB_DMA_DATA_NONINIT_SUB USB_LINK_NONCACHE_NONINIT_DATA
#define USB_DMA_DATA_INIT_SUB
#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA
#endif
my linker setttings
my mcu settings
am I missing anything?
carlosmendoza It looks like this change only works for the USB device examples. Do you know the corresponding change that is necessary for the USB host examples?
Thanks, Carlos. I appreciate the clarification regarding .bss and .data for non-cacheable data (I was missing the .init section definition).
Will these source code modifications and linker script changes be incorporated into future SDK revisions and example projects, for USB and all other peripherals and middleware that are affected by RT1050 cache issues?
EDIT: I missed Jing's reply above. I'm glad that NXP acknowledges that there is considerable work to be done, and I look forward to seeing this platform working at its full potential.
David R.
Jing,
Is there documentation on how to do this? I don't know what the control and data exchange blocks are. Is the developer expected to make changes to the MCUXpresso SDK code directly?
In the dev_hid_mouse_bm example, the buffer is already defined to use non-cached memory:
mouse.c
/*******************************************************************************
* Variables
******************************************************************************/
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t s_MouseBuffer[USB_HID_MOUSE_REPORT_LENGTH];
In the thread: MCUX on RT1050 - MMC stack won't initialize drodgers had a similar issue with ENET which seems to require a change to the SDK code, although the USB stack config and comments seem to suggest that caching should be taken care of automatically when configured correctly.
There is already cache handling code around the USB config buffer in usb_device_dci.c, are you suggesting that this is not sufficient to allow using cached memory for USB?
usb_device_dci.c:
#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
if (length)
{
DCACHE_CleanByRange((uint32_t)buffer, length);
}
#endif
/* Call the controller send interface, the callbackFn is initialized in
USB_DeviceGetControllerInterface */
error = deviceHandle->controllerInterface->deviceSend(deviceHandle->controllerHandle, endpointAddress,
buffer, length);
}
else
{
#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
if (length)
{
DCACHE_CleanInvalidateByRange((uint32_t)buffer, length);
}
#endif