M5222X - USB DATA from FLASH

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

M5222X - USB DATA from FLASH

2,730 Views
mjbcswitzerland
Specialist V
Hi All

Does any one know of restrictions to sending DATA over USB directly from FLASH?

I spend today completing a HID device working with the debugger from SRAM. Enumeration was working reliably and then interrupt DATA was being collected correctly. Then I compiled for FLASH and found that the enumeration would no longer get past the first DATA transfer - the data content was all zeros.

Since most of the descriptors were build up as const directly from FLASH I suspected that this may be the  problem: (example below):
    static const USB_DEVICE_DESCRIPTOR device_descriptor = {        STANDARD_DEVICE_DESCRIPTOR_LENGTH,   // standard device descriptor length (0x12)        DESCRIPTOR_TYPE_DEVICE,        {(unsigned char)USB_SPEC_VERSION,(USB_SPEC_VERSION >> 8)},        0,0,0,                               // device class, sub-class and protocol        ENDPOINT_0_SIZE,                     // size of endpoint reception buffer        {(unsigned char)USB_VENDOR_ID, (USB_VENDOR_ID >> 8)},        {(unsigned char)USB_PRODUCT_ID, (USB_PRODUCT_ID >> 8)},        {(unsigned char)USB_PRODUCT_RELEASE_NUMBER, (USB_PRODUCT_RELEASE_NUMBER >> 8)},        MANUFACTURER_STRING_INDEX, PRODUCT_STRING_INDEX, SERIAL_NUMBER_STRING_INDEX,  // fixed string table indexes        1                                    // number of configurations    };    fnPrepareOutData((unsigned char *)&device_descriptor, STANDARD_DEVICE_DESCRIPTOR_LENGTH, 0, ptrUSB_HW);

After removing the const attribute (and thus causing it to be copied from FLASH to SRAM) the DATA in this transfer was then correct again, which seemingly shows that direct transfers from FLASH don't work but from SRAM are OK.

Has anyone else experienced this or know of a method to be able to work directly from FLASH?

Regards

Mark

www.uTasker.com





Labels (1)
0 Kudos
Reply
6 Replies

1,265 Views
JimDon
Senior Contributor III
What version of CW?

I be willing to bet that some where in the code it casts away const and writes something in the table.


0 Kudos
Reply

1,265 Views
mjbcswitzerland
Specialist V
Hi Jim

CW6.3 - I have often used const without any problems. After removing all const references in the USB code the project runs from FLASH as it did from SRAM.

I did, when I first noticed the problem, very quickly step through some code and confirmed that the USB pointers were aimed at FLASH and that the FLASH (in the memory viewer) did show the expected content.

Therefore I don't think that it is a compiler issue but rather a USB memory access issue. I will be working on a USB communication device later today so will look more closely again...

Regards

Mark

0 Kudos
Reply

1,265 Views
JimDon
Senior Contributor III
Well, right now I have all my descriptors in RAM, but should move them as ram is at a premium.
I am using CW 7.0, but I don't think that makes a difference.

Tell me if you find anything. I will try them as const.

0 Kudos
Reply

1,265 Views
mjbcswitzerland
Specialist V
Hi Jim

Yes, the RAM is a bit critical (I am going to use an 8k part and it needs also fairly large buffers for its 3 UARTs) so that's why I tried working directly from FLASH. If it can be confirmed that there is no work around I think that I will keep the consts but do a copy to fixed USB tx buffers to keep RAM use to a minimum.

I am curious about your tests from FLASH...!

Regards

Mark



Message Edited by mjbcswitzerland on 2008-05-27 03:59 PM
0 Kudos
Reply

1,265 Views
mjbcswitzerland
Specialist V
Jim

I haven't tried this yet (it has only just occured to me) - but if you are trying USB transmissions directly from FLASH (before I do) you could have a go at doing the following:
Add CFM_FLASH to the FLASH address, where
#define CFM_FLASH            (IPSBAR + 0x4000000)

Since the USB controller has its own DMA controller it is possibly working like the general purpose DMA controller. This also has to use the 'back-door' FLASH address to work properly. I solved this a long time back when creating a DMA based memcpy() - it reduces a 512 byte memcpy() to about 40% of the time using the standard loop method. In this code I used the following when setting up the DMA controller:
        if ((unsigned long)ptrFrom < START_OF_SRAM) {                                 DMA_SAR3 = (BACKDOOR_FLASH + (unsigned long)ptrFrom);        // if from FLASH, set to backdoor        }        else {            DMA_SAR3  = (unsigned long)ptrFrom;                          // address of first byte to be transfered  (SARn)        }

 I suspect that the same technique will be relevant for the USB controller.

Furthermore, there may be access restrictions where the DMA controller will error when trying to access FLASH (then no transfer will take place - it aborts) if it doesn't have the rights to use FLASH. I solved this for the general purpose DMA controller by performing these two commands:
    PACR1 = 0x04;                                                        // enable DMA to access FLASH
    GPACR1 = 0x04;
These are already active in my project code but, again, they may also be required for the USB controller to be able to work directly from FLASH.

I will report back once I have tried this out (in case you don't beat me to it).

Regards

Mark


www.uTasker.com

0 Kudos
Reply

1,265 Views
mjbcswitzerland
Specialist V
Hi Jim

I finally got a chance to give it a try and can confirm that with this trick the USB controller can send tokens and data directly from FLASH.

As you know, the data pointers used by the USB controller need to be in little-endian format (although the buffer descriptor control words also have to be, these can be converted in the bit defines and so don't need such converstion at run time). This means that all USB data addresses pass through a conversion routine and by simply checking there whether the address is in FLASH - and adding the backdoor offset in this case - I could leave all fixed descriptors as consts in FLASH (saving a few hundred bytes of RAM):

// The Buffer Descriptor Tables work in Little-endian mode so we have to convert some addresses
//
extern void *fnLE_add(unsigned long long_word)
{
    unsigned long ulLE_long_word;

  if (long_word < START_OF_SRAM) {    // if the address is in FLASH we use FLASH backdoor to allow USB controller to access it
        long_word += BACKDOOR_FLASH;
    }

    ulLE_long_word = ((long_word >> 24) | ((long_word >> 8) & 0x0000ff00) | ((long_word << 8) & 0x00ff0000) | ((long_word << 24) & 0xff000000));

    return (void *)ulLE_long_word;
}

 In addition, on initialisation, I ensure that the DMA controller has rights to access FLASH by performing:
    PACR1 = 0x04;                                                        // enable DMA to access FLASH (also by USB DMA controller)
    GPACR1 = 0x04;


Regards

Mark

www.uTasker.com

0 Kudos
Reply