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: When using McBSP for burst-communication, how to avoid first clock being short-duration?

Part Number: TMS320F28377D

I am using the McBSP to communicate with an external BISS-encoder, so a clock-burst must be transmitted, which causes an encoder measurement and encoder data to be transmitted. I use one DMA to force the transmit of dummy data (no actually connected to the encoder), and another DMA to receive the data based on the McBSP-data-ready. Prior to starting I reset/release the McBSP transmit/receive registers (RRST and XRST) and I reset/release the sample-rate generator. This all works very well, except occasionally the first clock generated is a partial clock-pulse, which causes the encoder to error. My theory is either the GRST=1 or XRST=1 sometimes occurs in the middle of an LSPCLK, and there is nothing to prevent the 1/2 clock pulse from being generated. 

I don't have anything connected to MCLKR or MCLKX, so I need to use the internal LSPCLK. Is there any way to assure that the clock-burst only contains complete clock cycles?

Thanks,

Jim

  • Hi Jim, Our expert will get back on this today.

  • Any update on this question?

    Thanks,

    Jim

  • Jim,

    Sorry for the delay on our side.  Can you comment on the clock frequency you have set up to come out on the clock pin?  I want to make sure we are below the LSPCLK/2 ceiling mentioned in the TRM.

    Can you also provide the settings you are using; I assume we are in clock stop mode since you are bursting, but also what is CLKGDV?

    Best,

    Matthew

  • The clock-out frequency is 4Mhz, SYSCLK is 200Mhz, and LSPCLK = 50Mhz.

    Here are (I think) the relevant McBSP settings:
    FSXM = 1
    CLKXM = 1
    CLKRM = 1

    SCLKME = 0
    CLKSM = 1

    FPER = (16-1)
    FWID = (1-1)
    CLKGDV = (6-1)

    Thanks,

    Jim

  • Jim,

    Can you also send the setup procedure and/or code so I can try to reproduce on my end?  We're wondering if there is some order of operations effect here, that is not documented.

    Best,

    Matthew

  • I can't send our entire code base, so let me know which of these constants or macros you cannot resolve: here is the McBSP and DMA setup, and the per-loop triggering is at the bottom.

    // McBSP-A register settings

    McbspaRegs.SPCR2.all=0x0000; // Reset FS generator, sample rate generator & transmitter
    McbspaRegs.SPCR1.all=0x0000; // Reset Receiver, Right justify word
    //Loopback mode does not apply here
    //McbspaRegs.SPCR1.bit.DLB = 1; // Enable loopback mode for test. Comment out for normal McBSP transfer mode.


    McbspaRegs.MFFINT.all=0x0; // Disable all interrupts

    McbspaRegs.RCR1.all=0x0;
    McbspaRegs.RCR2.all=0x0; // Single-phase frame, No companding (Receive)
    McbspaRegs.RCR1.bit.RFRLEN1 = MCBSP_RECEIVE_FRAME_LENGTH(McBSPNumRxWords);
    McbspaRegs.RCR2.bit.RDATDLY = MCBSP_0_BIT_DELAY;
    //McbspaRegs.RCR2.bit.RFIG = 1; //Ignore incoming frame-sync pulses (the FPGA only sends one for the whole packet)

    McbspaRegs.XCR1.all=0x0;
    McbspaRegs.XCR2.all=0x0; // Single-phase frame, No companding (Transmit)
    McbspaRegs.XCR1.bit.XFRLEN1 = MCBSP_TRANSMIT_FRAME_LENGTH(McBSPNumTxWords);
    McbspaRegs.XCR2.bit.XDATDLY = MCBSP_0_BIT_DELAY;

    InitMcbspa16bit(); //Sets RCR1.bit.RWDLEN1 and XCR1.bit.XWDLEN1

    McbspaRegs.PCR.bit.FSXM = MCBSP_INTERNAL_TX_FRAME_SYNC; // FSX generated internally, FSR derived from an external source
    McbspaRegs.PCR.bit.CLKXM = MCBSP_INTERNAL_TX_CLK; // CLK-TX is driven by the sample rate generator clock
    McbspaRegs.PCR.bit.CLKRM = MCBSP_INTERNAL_RX_CLK; // CLK-RX is driven by the sample rate generator clock
    McbspaRegs.PCR.bit.CLKXP = MCBSP_TX_DATA_UPDATE_ON_FALLING; // TX data clocked on falling edges (should be sampled on rising)
    McbspaRegs.PCR.bit.CLKRP = MCBSP_RX_SAMPLED_ON_FALLING; // RX data sampled on falling edges

    //CLKSM=1 and SCLKME=0 defines the sample-rate-generator based on the internal sample rate generator
    McbspaRegs.PCR.bit.SCLKME = 0;
    McbspaRegs.SRGR2.bit.CLKSM = MCBSP_SAMPLE_RATE_GENERATOR_LSPCLK;

    McbspaRegs.SRGR2.bit.FPER = MCBSP_FRAME_SYNC_PERIOD(16); // FPER = 16 bits plus 1 FS bit
    McbspaRegs.SRGR1.bit.FWID = MCBSP_FRAME_SYNC_PULSE_WIDTH(1); // Frame Width = 1 CLKG period
    McbspaRegs.SRGR1.bit.CLKGDV = MCBSP_CLOCK_DIVIDE(McBSPClockDivider);// CLKG frequency = LSPCLK/(x) (or SYSCLKOUT/{x*4})

    //For debug: stop the McBSP clock on emulator halt:
    McbspaRegs.SPCR2.bit.FREE = 0; //Stop the clock on breakpoint halt
    McbspaRegs.SPCR2.bit.SOFT = 0; //And don't finish the word

    delay_loop(); // Wait at least 2 SRG clock cycles
    McbspaRegs.SPCR2.bit.GRST=1; // Enable the sample rate generator
    clkg_delay_loop(); // Wait at least 2 CLKG cycles
    McbspaRegs.SPCR2.bit.XRST=1; // Release TX from Reset
    McbspaRegs.SPCR1.bit.RRST=1; // Release RX from Reset
    McbspaRegs.SPCR2.bit.FRST=1; // Frame Sync Generator reset

    //Connect DMA channel 5 to McBSPA receive:
    DMACH5AddrConfig((volatile U16 *)&McBSPRxDataUInt[0], (U16*)&McbspaRegs.DRR1.all);

    EALLOW;
    DMA5_WRITE_BURST_SIZE(1); //One word at a time (by definition for McBSP)
    DMA5_WRITE_SRC_BURST_STEP(0); //The transfer-loop will increment
    DMA5_WRITE_DST_BURST_STEP(0); //All transmissions written to a single address (no increment)

    DMA5_WRITE_TRANSFER_SIZE(McBSPNumRxWords); //Number of transfers of 1 word(burst) at a time
    DMA5_WRITE_SRC_TRANSFER_STEP(0); //The destination is a single McBSP register
    DMA5_WRITE_DST_TRANSFER_STEP(1); //1 word increment after each 1-word received

    DMA5_WRITE_SOURCE_WRAP_SIZE(0xFFFF); // Wrap disabled
    DMA5_WRITE_SOURCE_WRAP_STEP(0xFFFF); // Wrap disabled
    DMA5_WRITE_DST_WRAP_SIZE(0xFFFF); // Wrap disabled
    DMA5_WRITE_DST_WRAP_STEP(0xFFFF); // Wrap disabled

    // Set up MODE Register:
    DmaRegs.CH5.MODE.bit.CHINTE = CHINT_DISABLE; // No Transfer-complete interrupt
    DmaRegs.CH5.MODE.bit.DATASIZE = SIXTEEN_BIT; // 16-bit data size transfers
    DmaRegs.CH5.MODE.bit.CONTINUOUS = CONT_DISABLE; // Continuous is disabled; on transfer completion, DMA stops (RUNSTS=0)
    DmaRegs.CH5.MODE.bit.ONESHOT = ONESHOT_ENABLE; // Oneshot enabled (One burst/word per event) -- to prevent overrun
    DmaRegs.CH5.MODE.bit.CHINTMODE = CHINT_END; // Generate interrupt to CPU at beginning/end of transfer
    DmaRegs.CH5.MODE.bit.PERINTE = PERINT_ENABLE; // Peripheral interrupt enable
    DmaRegs.CH5.MODE.bit.OVRINTE = OVRFLOW_DISABLE; // Enable/disable the overflow interrupt
    // McBSP-A receive as peripheral interrupt source
    DmaRegs.CH5.MODE.bit.PERINTSEL = 5;
    DmaClaSrcSelRegs.DMACHSRCSEL2.bit.CH5 = DMA_MREVTA;

    // Clear any spurious flags:
    DmaRegs.CH5.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
    DmaRegs.CH5.CONTROL.bit.ERRCLR = 1; // Clear any spurious sync error flags

    EDIS;
    StartDMACH5(); //The transfer starts when the event/interrupt occurs:
    //When the McBSP receives a word, it generates the REVT events to the DMA-engine, which reads the word.
    //It is assumed the transfer is complete by the end of the HSL.

    //Connect DMA channel 6 to McBSPA transmit:
    DMACH6AddrConfig((U16*)&McbspaRegs.DXR1.all, (volatile U16 *)&McBSPTxDataUInt[0]);

    EALLOW;
    DMA6_WRITE_BURST_SIZE(1); //One word at a time (by definition for McBSP)
    DMA6_WRITE_SRC_BURST_STEP(0); //The transfer-loop will increment
    DMA6_WRITE_DST_BURST_STEP(0); //All transmissions written to a single address (no increment)

    DMA6_WRITE_TRANSFER_SIZE(McBSPNumTxWords); //Number of transfers of 1 word(burst) at a time
    DMA6_WRITE_SRC_TRANSFER_STEP(1); //1 word increment after each 1-word transmitted
    DMA6_WRITE_DST_TRANSFER_STEP(0); //The destination is a single McBSP register

    DMA6_WRITE_SOURCE_WRAP_SIZE(0xFFFF); // Wrap disabled
    DMA6_WRITE_SOURCE_WRAP_STEP(0xFFFF); // Wrap disabled
    DMA6_WRITE_DST_WRAP_SIZE(0xFFFF); // Wrap disabled
    DMA6_WRITE_DST_WRAP_STEP(0xFFFF); // Wrap disabled

    // Set up MODE Register:
    DmaRegs.CH6.MODE.bit.CHINTE = CHINT_DISABLE; // No Transfer-complete interrupt
    DmaRegs.CH6.MODE.bit.DATASIZE = SIXTEEN_BIT; // 16-bit data size transfers
    DmaRegs.CH6.MODE.bit.CONTINUOUS = CONT_DISABLE; // Continuous is disabled; on transfer completion, DMA stops (RUNSTS=0)
    DmaRegs.CH6.MODE.bit.ONESHOT = ONESHOT_ENABLE; // Oneshot enabled (One burst/word per event) -- to prevent overrun
    DmaRegs.CH6.MODE.bit.CHINTMODE = CHINT_END; // Generate interrupt to CPU at end of transfer
    DmaRegs.CH6.MODE.bit.PERINTE = PERINT_ENABLE; // Peripheral interrupt enable
    DmaRegs.CH6.MODE.bit.OVRINTE = OVRFLOW_DISABLE; // Disable the overflow interrupt
    // McBSP-A XEVT as interrupt source (McBSP ready for new data)
    DmaRegs.CH6.MODE.bit.PERINTSEL = 6;
    DmaClaSrcSelRegs.DMACHSRCSEL2.bit.CH6 = DMA_MXEVTA;

    // Clear any spurious flags:
    DmaRegs.CH6.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
    DmaRegs.CH6.CONTROL.bit.ERRCLR = 1; // Clear any spurious sync error flags

    EDIS;
    StartDMACH6(); //The transfer starts when the event/interrupt occurs:
    //Force an event (trigger) onto the DMA engine by calling DMA6_FORCE_TRIGGER(), which inserts an event into DMA6. Then
    //the McBSP transmit-register is written with the first array element. The McBSP produces an XEVT when XRDY is true,
    //which kicks off the next word-write. It is assumed the transfer is complete by the end of the HSL.

    Then to start the McBSP clock-burst and start the DMA:

    MCBSPA_DISABLE_SR_GEN(); //GRST=0
    MCBSPA_ENABLE_SR_GEN(); //GRST=1


    //We need about 20us + 48bits of clocking to receive all the data we need (44us worst case):
    MCBSPA_RECEIVER_RESET(); //this toggles RRST
    MCBSPA_TRANSMIT_RESET(); //this toggles XRST

    //I suspect the HSL is synchronized to the system-clock, so these lines of code are also
    //synchronized plus/minus system jitter. The clock-enable on the next will enable whatever
    //the system-clock state is at, which may produce a clock-sliver, that messes up some encoders.
    //Adding NOPs here would change the sliver-pulse-width.

    MCBSPA_SET_XCLK_INTERNAL(); //CLKXM=1
    DMA5_RUN(); //RUN=1
    DMA6_RUN(); //RUN = 1
    DMA6_FORCE_TRIGGER(); //PERINTFRC=1

  • Jim,

    Thanks much for the code snippet that's what I needed.  I believe the issue is the order of the below instructions

    MCBSPA_DISABLE_SR_GEN(); //GRST=0
    MCBSPA_ENABLE_SR_GEN(); //GRST=1
    
    
    //We need about 20us + 48bits of clocking to receive all the data we need (44us worst case):
    MCBSPA_RECEIVER_RESET(); //this toggles RRST
    MCBSPA_TRANSMIT_RESET(); //this toggles XRST
    
    //I suspect the HSL is synchronized to the system-clock, so these lines of code are also
    //synchronized plus/minus system jitter. The clock-enable on the next will enable whatever
    //the system-clock state is at, which may produce a clock-sliver, that messes up some encoders.
    //Adding NOPs here would change the sliver-pulse-width.
    
    MCBSPA_SET_XCLK_INTERNAL(); //CLKXM=1

    As soon as we write GRST = 1 the internal McBSP clock will be generated.  I've confirmed that 0->1 will always give a correct length clock.  As you have noted, when we set CLKXM = 1, we are just allowing the internal clock to the pin, but since we are async to the clock this will change what we see on the pin based on when the bit is set relative to the McBSP clock.

    If you move the  MCBSPA_ENABLE_SR_GEN(); //GRST=1 to the line right before the DMA5_RUN() this should guarantee that we get a proper 1st clock each time.

    Let me know if this works for you application.

    Best,

    Matthew