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.

MSP432P401R: SPI clock very rounded at 16 MHz - why?

Part Number: MSP432P401R

Hi forum members,

I have run into a problem running the eUSCI_B0 module of the MSP432 at 16 MHz, and need your help and advice.

I am using DriverLib to configure a 3-wire SPI interface, which is connected to two devices. Each device has its own chip select, which I enable before communicating and then disable after communicating.

However, when we got new boards, I began having frequent problems reading a chip ID register from one of the devices. After digging deeper and checking the SPI clock with an oscilloscope, I was amazed that we ever were able to communicate over the SPI bus at all, with either the older or newer hardware.

As you can see from the attached oscilloscope image, the SCLK at 16 MHz is extremely rounded, and in fact does not appear to make it all the way down to ground before starting to rise again. A comparison of the same signal on the older board and the new board shows no discernible difference in shape or level of SCLK.

As an experiment, I reduced the SCLK to 12 MHz. The resulting SCLK waveform is also attached. The shape is still extremely rounded, but at least it does get down toward ground. Also, the reading of the chip ID no longer seems to fail at the lower speed. However, the signal quality still looks so bad that I am reluctant to call this fixed.

Has anyone else seen rounded SCLK's, or SCLK's that do not seem to go all the way to ground? I am wondering if I could have something misconfigured in the setup of the eUSCI_B0.

For reference, here is my initialization code. The processor has already been ramped up to 48MHz using the DC-DC converter, and SMCLK is running at 48MHz.

My module configuration is set up to select SPI_B0, with a desired clock of 8MHz initially, SMCLK as the clock source, SPI mode 0, MSB first, and 3-pin operation mode. SPISettings is just a C++ wrapper around that, with a constructor with default values. I have to communicate with one device at a lower speed initially (8 MHz), and later ramp the speed up to 16 MHz once that part has been configured via a call to MAP_SPI_changeMasterClock(), where desiredSPIFrequency is 16*1000000u (16MHz):

    SPISettings SPIsettings;    // Static instance of SPI settings (see constructor below for default values)
    
    // Constructs SPI settings to configure eUSCI_B0
    SPISettings(
        SPIInstance moduleInstance  = SPI_B0,
        uint32_t    spiClock        = 8000000u,
        SPIClkSrc   clockSrc        = SPI_CLK_SMCLK,
        SPIMode     dataMode        = SPI_MODE0,
        SPIBitOrder bitOrder        = SPI_MSB_FIRST,
        SPIPinMode  pinMode         = SPI_3PIN
        )
    {
        moduleInstance_ = moduleInstance;
        spiMasterConfig_.selectClockSource = clockSrc;

        if (SPI_CLK_SMCLK == clockSrc)
        {
            spiMasterConfig_.clockSourceFrequency = MAP_CS_getSMCLK();
        }
        else
        {
            spiMasterConfig_.clockSourceFrequency = MAP_CS_getACLK();
        }

        spiMasterConfig_.desiredSpiClock = spiClock;
        spiMasterConfig_.msbFirst = bitOrder;

        switch (dataMode)
        {
            case SPI_MODE0:
                spiMasterConfig_.clockPhase = EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT;
                spiMasterConfig_.clockPolarity = EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW;
                break;
            case SPI_MODE1:
                spiMasterConfig_.clockPhase = EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT;
                spiMasterConfig_.clockPolarity = EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW;
                break;
            case SPI_MODE2:
                spiMasterConfig_.clockPhase = EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT;
                spiMasterConfig_.clockPolarity = EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH;
                break;
            case SPI_MODE3:
                spiMasterConfig_.clockPhase = EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT;
                spiMasterConfig_.clockPolarity = EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH;
                break;
            default:
                // Bad SPI mode - error
                ErrorHandler::FatalError(ErrorHandler::ErrorNumber::INVALID_SPI_MODE_ERROR, __FILE__, __LINE__);
                break;
        }

        spiMasterConfig_.spiMode = pinMode;
    }

    // Sets up eUSCI_B0 in 3-wire SPI mode 0, MSB first, at 8MHz initially
    void InitSpiBus()
    {
        // Set up the SPI pins
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(SPI_SCLK_PORT,
            SPI_SCLK_PIN | SPI_MOSI_PIN | SPI_MISO_PIN, GPIO_PRIMARY_MODULE_FUNCTION);

        // Configure SPI in 3-wire master mode
        MAP_SPI_initMaster(SPIsettings.moduleInstance_, &SPIsettings.spiMasterConfig_);

        // Enable the SPI module
        MAP_SPI_enableModule(SPIsettings.moduleInstance_);
    }

    // To change SPI clock rate
    void ChangeClock(uint32_t desiredSPIFrequency)
    {
        SPIsettings.spiMasterConfig_.desiredSpiClock = desiredSPIFrequency;
        MAP_SPI_changeMasterClock(SPIsettings.moduleInstance_,
                                  SPIsettings.spiMasterConfig_.clockSourceFrequency,
                                  SPIsettings.spiMasterConfig_.desiredSpiClock);
    }

After initializing the SPI bus, I can see that P1SEL1 = 0x00 and P1SEL0 = 0xE0, which indicates that the Primary Module Function has been selected on P1.7 (MISO), P1.6 (MOSI), and P1.5 (SCLK). In eUSCI_B0, I can see that UCB0CTLW0 is set to 0xA980, which selects SMCLK as the clock source, synchronous mode, 3-pin SPI, master mode, 8 bit data, MSB first, inactive state low and data captured on 1st edge of clock and changed on following edge of clock. Also, UCB0BRW is set to 0x0006 initially, which makes sense for 8 MHz operation with 48MHz on SMCLK.

After the clock speed has been increased, UCB0BRW is 0x0003, which makes sense for 16 MHz from a 48 MHz SMCLK.

Do any of you know why SCLK might look so rounded, and especially why it does not appear to switch all the way to ground at 16MHz? Is there a drive strength or other configuration setting that I am missing? Do I also need to set the P1DIR register so that SCLK and MOSI are outputs and MISO is an input, or are those values overridden by the Primary Module Function selection? None of the DriverLib examples I've seen changed the P1DIR register.

Please help - lots of pressure to find a solution quickly. I sincerely appreciate your time and advice!

Scott

  • The 20-mA drive GPIO are P2.0-P2.3. Do you know how much capacitance is on P1.5 (SPICLK)? Have you/can you verify the rounded edges with other tools like the launchpad?

    Chris
  • Hi Chris,

    Good questions, and thank you for responding.  I have the capacitance for a SPI flash device that is on the bus, but am working with the vendor to get maximum values for an FT800 graphics controller from FTDI/Bridgetek.  I'll let you know when I get further information.

    I do have a LaunchPad, but the code base relies on communication with several pieces of custom hardware, and would take quite a bit of porting effort to trim down to run on the LaunchPad.  We plan to acquire some better measurements today with grounding close to the FT800 SPI clock input.

    Do you know of any method to increase the drive strength or otherwise square up the SPI clock?  I also need to look at MISO and MOSI to see if they are shaped well.

    Do you see anything in my initialization code that looks incorrect for configuring EUSCI_B0 for master operation in mode 0?  When I set the SCK, MISO, and MOSI pins up for GPIO_PRIMARY_MODULE_FUNCTION, am I correct that this overrides any GPIO direction settings?  That's what it looked like from the DriverLib examples I had seen previously.  This is done with the following call:

    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(SPI_SCLK_PORT, SPI_SCLK_PIN | SPI_MOSI_PIN | SPI_MISO_PIN, GPIO_PRIMARY_MODULE_FUNCTION);

    I believe that the MAP_GPIO_setAsPeripheralModuleFunctionOutputPIn() call would have worked equivalently.  Is this correct?

    Thanks for your help, and I will let you know when I have more info on the capacitance, or better measurements of the SPI signals.

    Best regards, Scott

  • Chris, just to confirm: the SPI clock should have a 50% duty cycle, correct? At the moment we are not seeing a symmetric clock, and it may be that data on MISO/MOSI has not settled adequately before the rising edge of SCLK. I'm operating in SPI mode 0, so the data is clocked on the rising edge, and changes on the falling edge. The current SCLK is high for longer than it is low. Still trying to instrument and get some pictures to share.

    Thanks for your help!
  • Hi Chris,

    We captured the 16 MHz SPI clock with pin 9 of the MSP432 disconnected from all downstream devices.  The duty cycle clearly is not 50%.  SMCLK at 48 MHz is being used as the clock source.  Does this imply that odd multiples of the SPI bit rate to the SMCLK will not generate a 50% duty cycle (48 / 16 = 3), while even multiples will produce a 50% duty cycle (e.g. 48 / 12 = 4)?  Or is there something I am missing about the configuration of the SPI port on the eUSCI?

    Thanks again for your time and help,

    Scott

  • By the way, the previously posted images with severely rounded clocks were due to an incorrect oscilloscope setup. Please ignore those!

    Scott
  • Scott,
    I failed to notice in an earlier post that you are using the SMCLK at 48Mhz. The maximum frequency that the peripheral can accept is 24Mhz. I will run a couple of experiments on my side to see if the duty cycle distortion of odd verses even ratios is persistent below 24Mhz. I will also try 32Mhz/16Mhz but I am not sure that I can recommend that.

    Just as a side note, if you are going to be sending a stream of SPI data you will end up with 'gaps' in the datastream unless you make the SMCLK faster than the spiclk. If you make them the same, then you will see the extra cycle it takes to move the byte from the transmit buffer into the shift register.

    Chris
  • Thanks, Chris,

    I had just noticed that in section 6.1 of slau356h - MSP432P4xx Technical Reference Manual, which states:

    "SMCLK: Low-speed subsystem master clock. SMCLK uses the HSMCLK clock resource selection for

    its clock resource. SMCLK can be divided independently from HSMCLK by 1, 2, 4, 8, 16, 32, 64, or

    128. SMCLK is limited in frequency to half of the rated maximum frequency of HSMCLK. SMCLK is

    software selectable by individual peripheral modules."

    However, in section 6.2, the manual states:

    "DCOCLK is selected for MCLK, HSMCLK, and SMCLK (SELMx = SELSx = 3) and each system clock

    is undivided (DIVMx = DIVSx = DIVHSx = 0)."

    Since my initialization code sets the DCO clock to 48MHz early, that means that all the other clocks default to 48MHz too, which will violate section 6.1 for SMCLK.  This means that I will need to divide down SMCLK by making a DriverLib call.  I'm a little amazed that things have worked so well with SMCLK set to the default of 48MHz.  Given that all of the available clock divisors are multiples of 2, how could I get to a 16MHz SPI clock?

    Also, please take a look at this post in e2e, which appears to be setting MCLK=HSCLK=SMCLK=48MHz.  How can this be valid?

    e2e.ti.com/.../603642

    Thanks very much for your help.  I appreciate anything you can do to clear up the confusion over the maximum SMCLK that can be used, and the best choice of clocks and divisors so that we can try to run at the rated 16MHz for the SPI bus.

    Best regards!

    Scott

  • Hi Chris,

    I also found this link, where you mentioned that in order to get a 16MHz SPI bus, you would need to have SMCLK set to 16MHz.

    e2e.ti.com/.../576524

    Do you have an example of configuring the DCO to run at 48MHz, and a clock/eUSCI configuration for a SPI channel to run at the rated 16MHz?  If so, is the 16MHz SPI clock running at a 50% duty cycle?

    I am also trying to confirm whether SMCLK must be limited to no more than 24MHz.  There are conflicting posts as I mentioned above which seem to have the SMCLK initialized to 48MHz.

    I sincerely appreciate the help you have provided this week.  Enjoy your weekend.

    Scott

  • Data sheet (SLAS826G) Table 5-36 claims the maximum USCI input clock is 24MHz.

    I have run SPI with SMCLK=48MHz and BRW=2, and it was "just fine". That doesn't mean it will always work (which is the business TI is in).

    I just tried SMCLK=24MHz/BRW=1 (nothing connected) and the waveforms were visually indistinguishable. They were somewhat rounded but full-swing.
  • Thanks for your reply, Bruce,

    Seems like I am running outside the TI spec of 24 MHz max, and should change this to be safe. However, what SMCLK frequency would be required for safe and 50% duty cycle SPI clocks at 16 MHz? I suspect that it would have to be 16 MHz as well, so the SMCLK would be divided by 1.

    Would this impact the timing relationships between MISO, MOSI, and SMCLK vs. running at some higher SMCLK? I wish it was safe to run the eUSCI at 32 MHz, but it does not appear to be "in spec".

    I've seen several posts from TI staff in this forum about setting SMCLK to 48 MHz, but that certainly seems to be outside the spec in the SLAS826G Technical Reference Manual, and just because it works _now_ is no guarantee that it works _always_.

    Your help and opinions are greatly appreciated! Best regards,

    Scott
  • Sorry, I don't know any trick for getting 16MHz out of a 24MHz input clock, and we only get power-of-2 dividers on the DCO.

    I also don't know what the origin of the clock limitation is. I suppose if it's e.g. temperature or voltage and you'll always be running your system in a lab with regulated Vcc you can get away with it. Before I noticed the limit, I blissfully ran at 48MHz (20C/3.3V) without evident problems. (But I'm in the Research department.)

    I'm not sure I understand what you mean by "impact the timing relationships". Since BRCLK is divided on entry to the USCI, I imagine all that happens at the resulting BITCLK rate.
  • Thanks Bruce,

    Yes, power of 2 divisors (or undivided) on the DCO certainly make sense.  Sorry to misdirect the conversation by asking about something that obviously wouldn't work!

    I've also been running at room temperature, Vcc=3.3V, with a 48MHz SMCLK at 16MHz SPI clock for quite a while, but then a new batch of boards was built, and we ran into problems reading a known chip ID from a part on the bus.  Further investigation showed that the SPI clock was staying high for about 2 SMCLKs and low for 1, so the SPI clock's duty cycle was not 50%.  This also meant that when data is changed on the falling edge of the SPI clock (in SPI mode 0), it didn't always look like the data on MISO or MOSI was fully settled before being latched on the next rising edge of SPI clock.  It appears that we got "lucky" with the earlier batch of boards.

    A quick software change to reduce the SPI clock to 12MHz got us back a 50% duty cycle SPI clock, and there was plenty of setup time for MISO/MOSI to stabilize before the next rising clock edge.  And that was still done with SMCLK at 48MHz.

    To be safe, I will need to make a change to the SMCLK to 16MHz and try running the SPI at 16MHz.  That should produce a 50% duty cycle SPI clock too.  The fallback would be to use an SMCLK of 24MHz and SPI clock of 12MHz, which would also provide a 50% duty cycle, while allowing devices on the SPI bus more time to settle MISO/MOSI before the next rising clock edge.  Not as desirable as 16MHz due to lots of data being sent to a SPI graphics controller (FT800).

    In short, due to various (bad) examples and not digesting all the fine print in the Technical Reference Manual, I did not know that I was running the SMCLK out of spec, and will need to make a change.

    Thanks again for your input and advice.  Best regards!

    Scott

  • Hi Chris,

    Can you clarify what you mean in your last paragraph: "Just as a side note, if you are going to be sending a stream of SPI data you will end up with 'gaps' in the datastream unless you make the SMCLK faster than the spiclk. If you make them the same, then you will see the extra cycle it takes to move the byte from the transmit buffer into the shift register."

    Gaps would not be good. The data is all 8-bit chunks, and I'm not sure what would need to be done to handle an extra cycle... Do you have an example waveform showing the difference between an SMCLK faster than the SPI clock, and the SMCLK equal to the SPI clock?

    Thanks!

    Scott
  • Scott,

       I have tried to highlight the move from the transmit buffer to the shift register here:

    The following settings provided the waveform below:

    MCLK = 32Mhz

    SMCLK = 16Mhz

    SPICLK = 16Mhz

    The SPI output clock is suspended for the move so that the output data is not corrupted.  Hope that helps.

    Chris

  • Hi Chris,

    Thank you for the example.  If I understand this correctly, then there isn't any impact on software, just a delay between one SPI packet and the next?

    Also, I notice that you have MCLK = 32 MHz.  If we want to run at 48 MHz, is it possible to create an SMCLK that runs at 16 MHz?  Or am I limited to factors of 2 for divisors (or no division).  I do understand that the SMCLK should not be greater than 24 MHz, and if I want SPI to run at 16 MHz, then I will need to use an SMCLK at 16 MHz to get the correct clock rate.

    A less attractive and slower option is to run MCLK at 48 MHz, SMCLK at 24 MHz, and then the SPI clock at 12 MHz, but this will slow down the data transfer to/from our FT800 graphics controller.  I'd like to run the SPI bus at 16 MHz, but do not want to do so at the expense of running the entire system slower than 48 MHz.

    Can you please clarify whether it is possible to generate a 16 MHz SMCLK while still running the system at 48 MHz?

    Many thanks for your patience and help.  There's a lot of capability to this part, along with a good amount of complexity!

    Scott

  • You are correct, it is just the delay between packets (bytes).

    The dividers are limited to factors of 2 in the Clock system, www.ti.com/.../slau356h.pdf .

    I do not think it is possible to run a 16Mhz SPI with only a 48Mhz clock source. An alternative would be to provide two separate clock sources. For example use HFXT at 48Mhz and then the DCO at 16Mhz (or vice-versa) and supply MCLK from the 48Mhz source and SMCLK from the 16Mhz source.

    Regards,
    Chris

**Attention** This is a public forum