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.

TMS320F28377D: 2837xD McBSP Setup for 3-Wire SPI

Part Number: TMS320F28377D

Tool/software:

I am using a TMS320F28377D and am attempting to setup one of the McBSP peripherals as a SPI master to interface with a 3-wire SPI slave which is an Infineon TLE5014 GMR. The GMR requires a command from the micro which consists of a clock signal, transmitted data and a chip select. Looking through the examples in CCS, I have been able to get this working as expected. The part that gets complicated is that after the GMR receives the command, it begins to transmit the requested data on the shared data line. I am unsure of how to get the McBSP to put it's DX line in high impedance to allow the GMR to drive the data line, or if it is even possible. 

We have the GMR CSn pin connected to MFSXa, the SCLK pin connected to MCLKXa, the DATA pin connected to MDRa and to MDXa through a 750Ohm resistor.

The desired operation is as follows: pull FSX low, output clock signal on CLKX, transmit 16bits of data on DX and read/ignore data on DR (same as DX data). Once that portion completes, FSX needs to stay low and then the clock signal starts again on CLKX, DX gets put in high impedance, and DR receives 32bits of data from the GMR. Once that completes, FSX can go high.

Is it possible to setup the McBSP the way that is needed?

  • Hello,

    The expert on this topic is currently out of office until Tuesday 9/3, so please expect a delayed response. I apologize for any inconvenience.

    Best Regards,
    Delaney

  • In anticipation of that response, here are some snippets of the code that I have been using. I copied ConfigMcBSP from one of the examples. The other snippet is my attempt to get the communication to sequence the way I described above. I am manually holding MFSXA low. This technically works, but the signals (shared MDRa and MDXa) don't look great when viewed with an oscilloscope depending on whether the micro or GMR is attempting to drive the bus.

    void configMcBSP(uint32_t base)
    {
        #define MCBSP_CYCLE_NOP0(n)  __asm(" RPT #(" #n ") || NOP")
        #define MCBSP_CYCLE_NOP(n)   MCBSP_CYCLE_NOP0(n)
    
        //
        // Reset FS generator, sample rate generator, transmitter, receiver.
        //
        McBSP_resetFrameSyncLogic(base);
        McBSP_resetSampleRateGenerator(base);
        McBSP_resetTransmitter(base);
        McBSP_resetReceiver(base);
    
        //
        // Set Rx sign-extension and justification mode.
        //
    
        McBSP_setRxSignExtension(base, MCBSP_RIGHT_JUSTIFY_FILL_ZERO);
    
        //
        // Enable DLB mode. Comment out for non-DLB mode.
        //
        //McBSP_enableLoopback(MCBSPA_BASE);
    
        //
        // Enable clock stop mode.
        //
        McBSP_setClockStopMode(base, MCBSP_CLOCK_SPI_MODE_NO_DELAY);
    
        //
        // Set Rx & Tx delay to 1 cycle.
        //
        McBSP_setRxDataDelayBits(base, MCBSP_DATA_DELAY_BIT_1);
        McBSP_setTxDataDelayBits(base, MCBSP_DATA_DELAY_BIT_1);
    
        //
        // Set CLKX & FSX source as sample rate generator.
        //
        McBSP_setTxClockSource(base, MCBSP_INTERNAL_TX_CLOCK_SOURCE);
        McBSP_setRxClockSource(base, MCBSP_INTERNAL_RX_CLOCK_SOURCE);
        McBSP_setTxFrameSyncSource(base, MCBSP_TX_INTERNAL_FRAME_SYNC_SOURCE);
        McBSP_setRxFrameSyncSource(base, MCBSP_RX_INTERNAL_FRAME_SYNC_SOURCE);
    
        //
        // Set Tx and Rx clock and frame-sync polarity.
        //
        McBSP_setTxFrameSyncPolarity(base, MCBSP_TX_FRAME_SYNC_POLARITY_LOW);
        McBSP_setTxClockPolarity(base, MCBSP_TX_POLARITY_FALLING_EDGE);
        McBSP_setRxClockPolarity(base, MCBSP_RX_POLARITY_FALLING_EDGE);
    
        //
        // Initialize McBSP data length.
        //
        McBSP_setRxDataSize(base, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_16, 0);
        McBSP_setTxDataSize(base, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_16, 0);
    
        //
        // Set frame synchronization pulse period to 1 CLKG cycle.
        //
        McBSP_setFrameSyncPulsePeriod(base, 0);
    
        //
        // Set frame-sync pulse width to 1 CLKG cycle.
        //
        McBSP_setFrameSyncPulseWidthDivider(base, 0);
    
        //
        // Set the trigger source for internally generated frame-sync pulse.
        //
        McBSP_setTxInternalFrameSyncSource(base, MCBSP_TX_INTERNAL_FRAME_SYNC_DATA);
    
        //
        // Set LSPCLK as input source for sample rate generator.
        //
        McBSP_setTxSRGClockSource(base, MCBSP_SRG_TX_CLOCK_SOURCE_LSPCLK);
    
        //
        // Set Divide down value for CLKG.
        //
        McBSP_setSRGDataClockDivider(base, 9);
    
        //
        // Set no external clock sync for CLKG.
        //
        McBSP_disableSRGSyncFSR(base);
    
        //
        // Wait for CPU cycles equivalent to 2 SRG cycles-init delay.
        // Total cycles required = 2*(SYSCLK/LSPCLK). In this example
        // LSPCLK = SYSCLK/4.
        //
        MCBSP_CYCLE_NOP(8);
    
        //
        // Enable Sample rate generator and wait for at least 2 CLKG clock cycles.
        //
        McBSP_enableSampleRateGenerator(base);
        McBSP_enableFrameSyncLogic(base);
    
        //
        // Wait for CPU cycles equivalent to 2 CLKG cycles-init delay.
        // Total cycles required = 2*(SYSCLK/(LSPCLK/(1+CLKGDV_VAL))). In this
        // example LSPCLK = SYSCLK/4 and CLKGDV_VAL = 1.
        //
        MCBSP_CYCLE_NOP(16);
    
        //
        // Release Rx, Tx and frame-sync generator from reset.
        //
    
        McBSP_enableTransmitter(base);
        McBSP_enableReceiver(base);
    
        //
        // Wait for CPU cycles equivalent to 2 SRG cycles-init delay.
        // Total cycles required = 2*(SYSCLK/LSPCLK). In this example
        // LSPCLK = SYSCLK/4.
        //
        MCBSP_CYCLE_NOP(8);
    }

    GPIO_writePin(DEVICE_GPIO_PIN_MFSXA, 0);
    
    McBSP_setRxDataSize(MCBSPA_BASE, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_16, 0);
    McBSP_setTxDataSize(MCBSPA_BASE, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_16, 0);
    
    McBSP_transmit16BitDataBlocking(MCBSPA_BASE, 0xC061);
    McBSP_receive16BitDataBlocking(MCBSPA_BASE, &spiReadDataDummy);
    
    McBSP_setRxDataSize(MCBSPA_BASE, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_32, 0);
    McBSP_setTxDataSize(MCBSPA_BASE, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_32, 0);
    
    McBSP_transmit32BitDataBlocking(MCBSPA_BASE, 0x00000000);
    McBSP_receive32BitDataBlocking(MCBSPA_BASE, &spiReadData);
    
    GPIO_writePin(DEVICE_GPIO_PIN_MFSXA, 1);

  • Matt,

    We can change the MDX and MDR pins from their McBSP mux function back to normal GPIO function.  By default, GPIO is configured as input mode, so it won't drive against the Infineon signal, which is what is happening now.

    So in your pin config after you bring the chip select back high, you could have(assuming you are using GPIO20/21, you can change this as needed)

    GPIO_setPinConfig(GPIO_20_GPIO20);

    GPIO_setPinConfig(GPIO_21_GPIO21);

    If you need to transmit again, we can just change the mux function back over to MDR/MDX later on.

    Let me know if this will work in your system.

    Best,

    Matthew

  • Thanks Matthew, this seems to have solved the issue. I had attempting something like this previously but was unable to get it to function. Something else must have been going wrong.

    Are you able to explain the 2us gaps between when I manually set the GPIO for the MFSXa pin (line 1) and when data starts transmitting on the bus (line 8)? I can't imagine the McBSP_setTx/RxDataSize and GPIO_setPinConfig take too many clock cycles to execute. This data exchange is time sensitive, so we need to figure out how to make it as fast as possible.

    GPIO_writePin(DEVICE_GPIO_PIN_MFSXA, 0);
    
    GPIO_setPinConfig(GPIO_20_MDXA);
    
    McBSP_setRxDataSize(MCBSPA_BASE, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_16, 0);
    McBSP_setTxDataSize(MCBSPA_BASE, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_16, 0);
    
    McBSP_transmit16BitDataBlocking(MCBSPA_BASE, 0x8021);
    McBSP_receive16BitDataBlocking(MCBSPA_BASE, &spiReadDataDummy);
    
    GPIO_setPinConfig(GPIO_20_GPIO20);
    
    McBSP_setRxDataSize(MCBSPA_BASE, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_32, 0);
    McBSP_setTxDataSize(MCBSPA_BASE, MCBSP_PHASE_ONE_FRAME, MCBSP_BITS_PER_WORD_32, 0);
    
    McBSP_transmit32BitDataBlocking(MCBSPA_BASE, 0x00000000);
    McBSP_receive32BitDataBlocking(MCBSPA_BASE, &spiReadData);
    
    GPIO_writePin(DEVICE_GPIO_PIN_MFSXA, 1);

  • Matt,

    Can you look in the project settings(right click on the project and click settings all the way at the bottom of the pop-up), and then expand the following: Build->C2000 Compiler->Predefined Symbols.  If you see "DEBUG" in the Pre-define NAME list, delete it, and recompile/reload/run and see if the GPIO delay improves.

    By default all of our projects have this pre-defined as a "safety-net" to catch incorrect arguments in the code.  However, this adds some measurable overhead to the code itself, especially for small functions like GPIO config, etc.

    If this already deleted, or you don't see enough improvement, let me know; we can create our own function that doesn't use our DRIVERLIB, to see if we can cut some cycles out.

    Best,

    Matthew

  • Matthew,

    There is no DEBUG listed in the predefined symbols lists. We will live with the current situation for now.