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

13 Replies

  • 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
  • In reply to Chris Sterzik:

    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

  • In reply to Chris Sterzik:

    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!
  • In reply to Scott Whitney80914:

    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

  • In reply to Scott Whitney80914:

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

    Scott
  • In reply to Scott Whitney80914:

    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
  • In reply to Chris Sterzik:

    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

  • In reply to Chris Sterzik:

    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

  • In reply to Scott Whitney80914:

    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.
  • In reply to Bruce McKenney47378:

    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