This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430F5529 USB CDC timing problem

Other Parts Discussed in Thread: MSP430F5529

Hello,
I am using an MSP430F5529 to measure a current using an external ADC (BOOST-LMP92064EVM) at 50 kHz. I would like to transfer each measurement (4 bytes) via USB CDC.
Unfortunately, it seems that when using a 10 us timer to start an SPI measurement, at every transfer the timer gets blocked for 60 us (up to 64 bytes, this delay is constant, independently on the size of the measurement).

I am using the USB API provided by TI and checked the behaviour with an oscilloscope. When changing the CPU speed from 20 to 25 MHz this 60 us delay remained constant.

According to the example provided by TI in BOOST-LMP92064EVM (binary available only), it should be possible to reach a 50 kHz sampling frequency. Does anybody have a similar problem or an example of the serial protocol used to start the measurement in the binary example (as well as which pin is used for the external trigger)?

Thanks,
Markus

  • How many bytes to you transfer in each USB packet? Have you implemented pipelining?
  • Hi Markus and Clements,

    Markus Schuss32 said:
    I am using an MSP430F5529 to measure a current using an external ADC (BOOST-LMP92064EVM) at 50 kHz. I would like to transfer each measurement (4 bytes) via USB CDC.

    It means USB transfer of 200 kbytes/sec is required, at least.
    Roughly speaking, bulk transfer speed is proportional to transfer size, until bus-bandwidth is saturated. To ensure this speed always, transfer size of twice the speed, ie. 400 bytes transfer, is recommended.

    You may pass large buffer, greater than 64 bytes, to USBCDC_sendDataInBackground(). The API splits the large buffer into 64 bytes packets internally, when it sends the buffer over the bulk IN endpoint.

    As Clemens suggested, the buffer should be pipelined - while the first (portion of) buffer is sent over USB, your SPI ISR fills the second (portion of) buffer, vise versa.

    Markus Schuss32 said:
    at every transfer the timer gets blocked for 60 us (up to 64 bytes, this delay is constant, independently on the size of the measurement).



    USBCDC_sendDataInBackground() waits for the completion of the last transfer with timeout. As your SPI ISR is timing-critical to keep steady A/D sampling, this API should be called in the main loop. Your SPI ISR sets a flag when it fills up a (portion of) buffer. Main loop polls this flag, and it calls USBCDC_sendDataInBackground()


    If you would see sampling fluctuation, even after you've applied above suggestions, it should be caused by the lengthy endpoint ISR, which blocks SPI interrupt. In this case, you may move the endpoint ISR into the main loop, so that it doesn't disturb SPI interrupt.

    The USB CDC examples in MSP430USBDevelopersPackage_5_00_00 has this ISR for bulk IN endpoint.

    UsbIsr.c
    
        case USBVECINT_INPUT_ENDPOINT2:
            //send saved bytes from buffer...
            bWakeUp = CdcToHostFromBuffer(CDC0_INTFNUM);
             break;

    In the modified version, the endpoint ISR just sets a flag and return immediately.

    volatile uint8_t bCDC_TX_Complete = FALSE;
    
        case USBVECINT_INPUT_ENDPOINT2:
            bWakeUp = TRUE;
            bCDC_TX_Complete = TRUE;
             break;
    

    In the main loop, this flag is polled to service the IN endpoint.

    extern volatile uint8_t bCDC_TX_Complete;
    
    void main (void)
    {
        ...
        while (1)
        {
            ...
            // Check the USB state and directly main loop accordingly
            switch (USB_getConnectionState())
            {
                // This case is executed while your device is enumerated on the
                // USB host
                case ST_ENUM_ACTIVE:
    
                    if ( bCDC_TX_Complete ) {
                        bCDC_TX_Complete = FALSE;
                        CdcToHostFromBuffer(CDC0_INTFNUM);
                    }
                    ...
    

    Lastly, this flag drops at every enumeration.

    usbEventHandling.c
    
    uint8_t USB_handleEnumerationCompleteEvent()
    {
        bCDC_TX_Complete = FALSE;
        return TRUE;
    }
    

    Tsuneo



**Attention** This is a public forum