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