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 Transmit Interrupt Flag doesn't go up

Part Number: MSP432P401R

I will give down below the code I use for sending over the SPI.
I need to send very quickly bytes to the CC1200 chip. And because of that, I work without interrupts and I only watch the flag. As soon as it goes up, I send the next byte over the SPI.
First I pull STE low, then I wait for the CC1200 to be ready(wait for the SOMI to go high) and then I send bytes over the SPI. At the end, I wait for the sending to be finished and I pull STE high.

There are two problems:
1. Using the SPI is Busy function doesn't seem to work so I look at the Busy bit manually.
2. Sometimes the SPI doesn't want to set the Interrupt flag for the transmit buffer. After some transmit the flag goes down and doesn't come back up.
This error occurs rarely and I can't find why it happens.

#define CC1200 EUSCI_B0_BASE

uint8_t	CC1200_Burst_Write(uint8_t* inputBuffer, uint8_t startingAddress, uint8_t length)
{
	int32_t	i;
	uint8_t statusByte;

	CC1200_Select_Module();

	/* Command byte that says burst write from starting address */
	CC1200_Transmit_Byte(startingAddress | CC1200_WRITE_BURST);
	statusByte	= CC1200_Receive_Byte();

	for(i = 0; i<length; i++)
	{
		CC1200_Transmit_Byte(inputBuffer[i]);
	}

	CC1200_Deselect_Module();

	return statusByte;
}

static void	CC1200_Select_Module()
{
	/* Clear receive interrupt status */
    EUSCI_B_SPI_clearInterruptFlag(CC1200_SPI, CC1200_SPI_RECEIVE_INTERRUPT);

	/* Pull chip select down and wait until SOMI goes down */
	MAP_GPIO_setOutputLowOnPin(CC1200_SPI_PORT, CC1200_SPI_STE);
	while (MAP_GPIO_getInputPinValue(CC1200_SPI_PORT, CC1200_SPI_MISO));
}

static void	CC1200_Deselect_Module()
{
	/* Wait for the SPI to finish transfer to deselect the module */
	while (UCB0STATW & 1);

	/* After ending transfer, pull chip select up */
	MAP_GPIO_setOutputHighOnPin(CC1200_SPI_PORT, CC1200_SPI_STE);
}

static void	CC1200_Transmit_Byte(uint8_t byte)
{
	/* Wait for transmit buffer to be empty and transmit byte */
	while (!(EUSCI_B_SPI_getInterruptStatus(CC1200_SPI, CC1200_SPI_TRANSMIT_INTERRUPT)));
	EUSCI_B_SPI_transmitData(CC1200_SPI, byte);
}

static uint8_t	CC1200_Receive_Byte()
{
    /* Wait for receive flag to read receive register */
	while (!(EUSCI_B_SPI_getInterruptStatus(CC1200_SPI, CC1200_SPI_RECEIVE_INTERRUPT)));
	return	EUSCI_B_SPI_receiveData(CC1200_SPI);
}

  • Jasaleja,

    I will look into this for you. A few preliminary questions to help me first. Can you tell me what revision of silicon you are using? Rev C and above is what is recommended.

    What clock source are you using for your SPI? Please make sure it is synchronous in this case. This slightly reminds me of USCI43 Errata. Can you please read the description and assess if this is also what you see with SPI?
    www.ti.com/.../slaz610
  • Well,

    We are using REV C, and SMCLK 6 MHz. It is synchronous.

    I don't know how much you are able to look into this, but here is some info. I looked at the errata but I am currently home, so I will look into it tomorrow.
    Currently the only way to achieve this is to manually clear the interrupt bit. If it is cleared this way it won't reassert itself. We are never clearing this bit so it can't be it.
    The worst thing is I can't recreate it. It happened to me like 2-3 times in the last six months. Now I gave my code to me partner who is testing my code together with his, and it occurs a few times a day.
    We checked, and he doesn't even have any interaction with EUSCIB0.
    The only workaround now we can think of is watchdog timer because our systems can recover quickly with it.


  • Jasaleja,

    Can you share with me your SPI init code? Please let me know where your investigation takes you. I would also be curious to know if using interrupts actually eliminates this anomaly.
  • Here is the part of the code that has to do with the SPI.

    /* SPI Master Configuration Parameter for CC1200 */
    static const eUSCI_SPI_MasterConfig spiCC1200Config =
    {
            EUSCI_B_SPI_CLOCKSOURCE_SMCLK,                              // SMCLK Clock Source
            6000000,                                                    // SMCLK = HFXT/8 = 6MHz
            6000000,                                                    // SPICLK = 6MHz
            EUSCI_B_SPI_MSB_FIRST,                                      // MSB First
            EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT,    // Phase
            EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW,                   // Low polarity
            EUSCI_B_SPI_3PIN                                            // 3Wire SPI Mode
    };
    
    void CC1200_Init()
    {
        /* Initialize all SPI related GPIOs and start the SPI module */
        MAP_GPIO_setAsOutputPin(CC1200_SPI_PORT, CC1200_SPI_STE);
    
        MAP_GPIO_setOutputHighOnPin(CC1200_SPI_PORT, CC1200_SPI_STE);
    
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(CC1200_SPI_PORT,
                CC1200_SPI_CLK | CC1200_SPI_MOSI | CC1200_SPI_MISO, GPIO_PRIMARY_MODULE_FUNCTION);
    
        /* Configure SPI in 3 wire master mode for CC1200 */
        SPI_initMaster(CC1200_SPI, &spiCC1200Config);
        SPI_enableModule(CC1200_SPI);
        EUSCI_B_SPI_disableInterrupt(CC1200_SPI, CC1200_SPI_TRANSMIT_INTERRUPT);
        EUSCI_B_SPI_disableInterrupt(CC1200_SPI, CC1200_SPI_RECEIVE_INTERRUPT);
    }
    

  • Jasaleja,

    How's your investigation coming?

    Also, in your comments, you note that SMCLK = HFXT/8. Is HFXT the source of your SMCLK? If so, can you try sourcing the DCO for an experiment and see if the anomaly you are seeing is replicated?
  • Hi Evan,

    Well, the reason I have not made any post is that the problem didn't occur.

    There are a few problems with your recommendations. I can't use interrupts because they would slow me down a little and I would have to redesign my current system. I only gave a fraction of the whole code we have.

    For the DCO suggestion, I would slow me very much. I Send data at 1 MHz and my SPI needs to be as fast as possible. So using HFXT/6 is 6 MHz. I could lower that but not to 32 KHz.
    If the problem occurs, I will report and I will try to recreate it.

    Have you done any investigation?

    jasaleja
  • Jasaleja,

    What are your NVIC priorities set to if you were to use the EUSCIBx interrupt? Are there other interrupts with a higher priority above it that would potentially block it from executing causing you to slow down?

    In the meantime, I will start trying to recreate this issue yes. Can you tell me what your MCLK settings are as well?

    Is there a stripped down version of your program that you could share that you can see the anomaly you speak of? This would greatly assist/accelerate the debug.
  • Jasaleja,

    Can you explain why setting it to DCO would slow you to 32KHz? It should be no problem to use the DCO as a source to run above that. Please help me understand if I'm missing something.
  • Jasaleja,

    In the effort of making sure we control this as much as possible and find the root problem, can you also use MAP_ functions for all functions. While the majority of DriverLib APIs are available in ROM, due to architectural limitations some APIs are omitted from being included in ROM. In addition, if any bug fixes were added to the API after the device ROM was programmed, it is desirable to use the flash version of the API. An "intelligence" has been created to account for this problem. If the user includes the rom_map.h
    header file and uses the MAP_ prefix in front of the API, the header file will automatically use preprocessor macros to decide whether to use a ROM or flash version of the API.

    This will help ensure that we aren't running into any bugs that have already been addressed.
  • Evan,

    I was wrong. For some reason I thought that DCO is limited like LFXT to 32 KHz but was wrong. I will try using this source but the problem didn't occur today neither.

    Also, as you can see, in my codes above I use all MAP_ functions except for SPI functions. In a thread I made some months ago I was told not to use MAP_ with SPI functions for some reason. I understand how the MAP_ intelligence works(I saw he code). Even in the examples, they don't use MAP_ with SPI, but with other stuff they use it.

    I will try selecting DCO for source and I understand we need to corner this problem, but I currently can't do anything as it is not occuring at all.

    As soon as I get any new information, I will inform you here but until then, I can't do anything.
  • Jasaleja,

    Sounds good. In the meantime, I will try my best to recreate it but as you said it sounds a bit difficult to recreate reliably. I am going to potentially chase this in the background and talk to the people who investigated that Errata USCI43 we talked on and get more information from them.

    On the MAP_ stuff, I did not realize this. I'm going to ask around and see why that is. Learned something new today :)
  • Jasaleja,

    Thought I would quickly update you, it took some time, but I was able to confirm that theoretically, the SPI module of eUSCI could be impacted by the same issue that causes USCI43. We will be publishing a new errata soon to address SPI, but I can say that the workaround will be very similar to that suggested in USCI43. We suggest using interrupts to avoid this issue.

    With regards to your concern around using interrupts, you should make sure you are setting the priorities of the interrupts appropriately for your application, making sure that the SPI interrupts are of higher priority in the NVIC than other peripherals. You may also look at using the DMA if it fits in with regards to your application, but I do not think that using interrupts will slow your communication down than when compared to polling.
  • Hi Evan,

    Thank you very much for the answer. It was very helpful. In the mean time, the error kept occurring and we solved it with a simple trick.

    After a lot of testing we found a problem in the application. We used the eUSCIB0 SPI in our main and sometimes we used it with DMA at the same time.

    This caused the error to occur more frequently but we very quick and solved the problem. Now the problem still occurred from time to time and with additional testing we managed to narrow it down to a problem in the hardware. 

    To not bother what I was thinking I solved the problem with a little trick. After polling for CC1200_SPI_TRANSMIT_INTERRUPT in this function:

    static void CC1200_Transmit_Byte(uint8_t byte)
    {
        /* Wait for transmit buffer to be empty and transmit byte */
        while (!(EUSCI_B_SPI_getInterruptStatus(CC1200_SPI, CC1200_SPI_TRANSMIT_INTERRUPT)));
        EUSCI_B_SPI_transmitData(CC1200_SPI, byte);
    }
    
    

    I added one line of code:

    static void CC1200_Transmit_Byte(uint8_t byte)
    {
        /* Wait for transmit buffer to be empty and transmit byte */
        while (!(EUSCI_B_SPI_getInterruptStatus(CC1200_SPI, CC1200_SPI_TRANSMIT_INTERRUPT)));
        EUSCI_B_SPI_clearInterruptFlag(CC1200_SPI, CC1200_SPI_TRANSMIT_INTERRUPT);
    
        EUSCI_B_SPI_transmitData(CC1200_SPI, byte);
    }


    Now the error never occurs.

    Thanks for the help, and thanks for adding it to the errata.

  • Jasaleja,

    Glad you could find a resolution to your issue and that we could help in the process!

**Attention** This is a public forum