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.

SPI3 slave data rotated

Other Parts Discussed in Thread: RM48L952, HALCOGEN

Hello,

I have MIBSPI3 set up as a slave to receive data. I have it working, however, the data is always rotated. If I see [0,1,2,3,4,5,6,7] on the scope, I'll see [7,0,1,2,3,4,5,6] in my receive buffer after calling mibspiGetData(). Relevant code and scope outputs provided below. I think it likely has to do with the initialization of MIBSPI3, but I can't nail down where.

for(i=0;i<FSR/TGROUP_SIZE;i++) //TGROUP_SIZE = 8, FSR = 16
    {
        mibspiSetData(mibspiREG3, 0, DummyTX); //This is dummy data on slave that doesn't go anywhere
        //set group 0, length 8, charlen 16, trigger rising on GIOA6, oneshot transfer, CS_NONE, dataFormat0, buffer mode 4
        //lock transmission, enable WDELAY, chip select hold and transfer group pointer reset are ALL unchecked
        mibspiTransfer(mibspiREG3, 0);

        mibspiSetData(mibspiREG1, 1, tx); //Set Master Data
        //set group 1, length 8, charlen 16, trigger rising on GIOA7, oneshot transfer, CS_NONE, dataFormat0, buffer mode 4
        //lock transmission, enable WDELAY, chip select hold and transfer group pointer reset are ALL unchecked
        mibspiTransfer(mibspiREG1, 1);
        tx += TGROUP_SIZE;

        //trigger master and slave
        gioSetBit(gioPORTA,6,1);
        gioSetBit(gioPORTA,7,1);


        while (mibspiIsTransferComplete(mibspiREG3, 0) == 0);  // wait here until transfer is complete
        gioSetBit(gioPORTA,6,0);
        gioSetBit(gioPORTA,7,0);

        status = mibspiGetData(mibspiREG3, 0, prx);
        prx += TGROUP_SIZE;
        sClockRx += (16*8);

    }
Code generated by HalCoGen 3.06



/** bring MIBSPI out of reset */ mibspiREG3->GCR0 = 1U; /** enable MIBSPI RAM Parity */ mibspiREG3->UERRCTRL = (mibspiREG3->UERRCTRL & 0xFFFFFFF0U) | (0x00000005U); /** enable MIBSPI3 multibuffered mode and enable buffer RAM */ mibspiREG3->MIBSPIE = (mibspiREG3->MIBSPIE & 0xFFFFFFFEU) | 1U; /** MIBSPI3 master mode and clock configuration */ mibspiREG3->GCR1 = (mibspiREG3->GCR1 & 0xFFFFFFFCU) | ((0U << 1U) /* CLOKMOD */ | 0U); /* MASTER */ /** MIBSPI3 enable pin configuration */ mibspiREG3->INT0 = (mibspiREG3->INT0 & 0xFEFFFFFFU) | (0U << 24U); /* ENABLE HIGHZ */ /** - Delays */ mibspiREG3->DELAY = (0U << 24U) /* C2TDELAY */ | (0U << 16U) /* T2CDELAY */ | (0U << 8U) /* T2EDELAY */ | 0U; /* C2EDELAY */ /** - Data Format 0 */ mibspiREG3->FMT0 = (0U << 24U) /* wdelay */ | (0U << 23U) /* parity Polarity */ | (0U << 22U) /* parity enable */ | (0U << 21U) /* wait on enable */ | (0U << 20U) /* shift direction */ | (1U << 17U) /* clock polarity */ | (0U << 16U) /* clock phase */ | (7U << 8U) /* baudrate prescale */ | 16U; /* data word length */ /** - Data Format 1 */ mibspiREG3->FMT1 = (0U << 24U) /* wdelay */ | (0U << 23U) /* parity Polarity */ | (0U << 22U) /* parity enable */ | (0U << 21U) /* wait on enable */ | (0U << 20U) /* shift direction */ | (0U << 17U) /* clock polarity */ | (1U << 16U) /* clock phase */ | (7U << 8U) /* baudrate prescale */ | 8U; /* data word length */ /** - Data Format 2 */ mibspiREG3->FMT2 = (0U << 24U) /* wdelay */ | (0U << 23U) /* parity Polarity */ | (0U << 22U) /* parity enable */ | (0U << 21U) /* wait on enable */ | (0U << 20U) /* shift direction */ | (0U << 17U) /* clock polarity */ | (1U << 16U) /* clock phase */ | (7U << 8U) /* baudrate prescale */ | 16U; /* data word length */ /** - Data Format 3 */ mibspiREG3->FMT3 = (0U << 24U) /* wdelay */ | (0U << 23U) /* parity Polarity */ | (0U << 22U) /* parity enable */ | (0U << 21U) /* wait on enable */ | (0U << 20U) /* shift direction */ | (0U << 17U) /* clock polarity */ | (0U << 16U) /* clock phase */ | (99U << 8U) /* baudrate prescale */ | 16U; /* data word length */ /** - Default Chip Select */ mibspiREG3->DEF = (uint32)(0x00U); /** - wait for buffer initialization complete before accessing MibSPI registers */ /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Hardware status bit read check" */ while ((mibspiREG3->FLG & 0x01000000U) != 0U) { } /* Wait */ /** - initialize transfer groups */ mibspiREG3->TGCTRL[0U] = (1U << 30U) /* oneshot */ | (0U << 29U) /* pcurrent reset */ | (TRG_RISING << 20U) /* trigger event */ | (TRG_GIOA6 << 16U) /* trigger source */ | (0U << 8U); /* start buffer */ mibspiREG3->TGCTRL[1U] = (0U << 30U) /* oneshot */ | (0U << 29U) /* pcurrent reset */ | (TRG_ALWAYS << 20U) /* trigger event */ | (TRG_DISABLED << 16U) /* trigger source */ | (8U << 8U); /* start buffer */ mibspiREG3->TGCTRL[2U] = (1U << 30U) /* oneshot */ | (0U << 29U) /* pcurrent reset */ | (TRG_ALWAYS << 20U) /* trigger event */ | (TRG_DISABLED << 16U) /* trigger source */ | ((8U+8U) << 8U); /* start buffer */ mibspiREG3->TGCTRL[3U] = (1U << 30U) /* oneshot */ | (0U << 29U) /* pcurrent reset */ | (TRG_ALWAYS << 20U) /* trigger event */ | (TRG_DISABLED << 16U) /* trigger source */ | ((8U+8U+0U) << 8U); /* start buffer */ mibspiREG3->TGCTRL[4U] = (1U << 30U) /* oneshot */ | (0U << 29U) /* pcurrent reset */ | (TRG_ALWAYS << 20U) /* trigger event */ | (TRG_DISABLED << 16U) /* trigger source */ | ((8U+8U+0U+0U) << 8U); /* start buffer */ mibspiREG3->TGCTRL[5U] = (1U << 30U) /* oneshot */ | (0U << 29U) /* pcurrent reset */ | (TRG_ALWAYS << 20U) /* trigger event */ | (TRG_DISABLED << 16U) /* trigger source */ | ((8U+8U+0U+0U+0U) << 8U); /* start buffer */ mibspiREG3->TGCTRL[6U] = (1U << 30U) /* oneshot */ | (0U << 29U) /* pcurrent reset */ | (TRG_ALWAYS << 20U) /* trigger event */ | (TRG_DISABLED << 16U) /* trigger source */ | ((8U+8U+0U+0U+0U+0U) << 8U); /* start buffer */ mibspiREG3->TGCTRL[7U] = (1U << 30U) /* oneshot */ | (0U << 29U) /* pcurrent reset */ | (TRG_ALWAYS << 20U) /* trigger event */ | (TRG_DISABLED << 16U) /* trigger source */ | ((8U+8U+0U+0U+0U+0U+0U) << 8U); /* start buffer */ mibspiREG3->TGCTRL[8U] = (8U+8U+0U+0U+0U+0U+0U+0U) << 8U; mibspiREG3->LTGPEND = (mibspiREG3->LTGPEND & 0xFFFF00FFU) | (((8U+8U+0U+0U+0U+0U+0U+0U)-1U) << 8U); /** - initialize buffer ram */ { i = 0U; /*SAFETYMCUSW 139 S MR: 13.7 REVIEWED " If condition cannot be removed as the LHS depends on GUI configuraion " */ if (8U > 0U) { while (i < (8U-1U)) { mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold */ | (0U << 11U) /* lock transmission */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold must be zero for last buffer */ | (0U << 10U) /* enable WDELAY */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } /*SAFETYMCUSW 139 S MR: 13.7 REVIEWED " If condition cannot be removed as the LHS depends on GUI configuraion " */ if (8U > 0U) { while (i < ((8U+8U)-1U)) { mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold */ | (0U << 11U) /* lock transmission */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold must be zero for last buffer */ | (0U << 10U) /* enable WDELAY */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } /*SAFETYMCUSW 139 S MR: 13.7 REVIEWED " If condition cannot be removed as the LHS depends on GUI configuraion " */ if (0U > 0U) { while (i < ((8U+8U+0U)-1U)) { mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold */ | (0U << 11U) /* lock transmission */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold must be zero for last buffer */ | (0U << 10U) /* enable WDELAY */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } /*SAFETYMCUSW 139 S MR: 13.7 REVIEWED " If condition cannot be removed as the LHS depends on GUI configuraion " */ if (0U > 0U) { while (i < ((8U+8U+0U+0U)-1U)) { mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold */ | (0U << 11U) /* lock transmission */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold must be zero for last buffer */ | (0U << 10U) /* enable WDELAY */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } /*SAFETYMCUSW 139 S MR: 13.7 REVIEWED " If condition cannot be removed as the LHS depends on GUI configuraion " */ if (0U > 0U) { while (i < ((8U+8U+0U+0U+0U)-1U)) { mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold */ | (0U << 11U) /* lock transmission */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold must be zero for last buffer */ | (0U << 10U) /* enable WDELAY */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } /*SAFETYMCUSW 139 S MR: 13.7 REVIEWED " If condition cannot be removed as the LHS depends on GUI configuraion " */ if (0U > 0U) { while (i < ((8U+8U+0U+0U+0U+0U)-1U)) { mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold */ | (0U << 11U) /* lock transmission */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold must be zero for last buffer */ | (0U << 10U) /* enable WDELAY */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } /*SAFETYMCUSW 139 S MR: 13.7 REVIEWED " If condition cannot be removed as the LHS depends on GUI configuraion " */ if (0U > 0U) { while (i < ((8U+8U+0U+0U+0U+0U+0U)-1U)) { mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold */ | (0U << 11U) /* lock transmission */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold must be zero for last buffer */ | (0U << 10U) /* enable WDELAY */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } /*SAFETYMCUSW 139 S MR: 13.7 REVIEWED " If condition cannot be removed as the LHS depends on GUI configuraion " */ if (0U > 0U) { while (i < ((8U+8U+0U+0U+0U+0U+0U+0U)-1U)) { mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold */ | (0U << 11U) /* lock transmission */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } mibspiRAM3->tx[i].control = (4U << 13U) /* buffer mode */ | (0U << 12U) /* chip select hold must be zero for last buffer */ | (0U << 10U) /* enable WDELAY */ | (0U << 8U) /* data format */ |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU)); /* chip select */ i++; } } /** - set interrupt levels */ mibspiREG3->LVL = (0U << 9U) /* TXINT */ | (0U << 8U) /* RXINT */ | (0U << 6U) /* OVRNINT */ | (0U << 4U) /* BITERR */ | (0U << 3U) /* DESYNC */ | (0U << 2U) /* PARERR */ | (0U << 1U) /* TIMEOUT */ | (0U); /* DLENERR */ /** - clear any pending interrupts */ mibspiREG3->FLG |= 0xFFFFU; /** - enable interrupts */ mibspiREG3->INT0 = (mibspiREG3->INT0 & 0xFFFF0000U) | (0U << 9U) /* TXINT */ | (0U << 8U) /* RXINT */ | (0U << 6U) /* OVRNINT */ | (0U << 4U) /* BITERR */ | (0U << 3U) /* DESYNC */ | (0U << 2U) /* PARERR */ | (0U << 1U) /* TIMEOUT */ | (0U); /* DLENERR */ /** @b initialize @b MIBSPI3 @b Port */ /** - MIBSPI3 Port output values */ mibspiREG3->PC3 = 1U /* SCS[0] */ | (1U << 1U) /* SCS[1] */ | (1U << 2U) /* SCS[2] */ | (1U << 3U) /* SCS[3] */ | (1U << 4U) /* SCS[4] */ | (1U << 5U) /* SCS[5] */ | (0U << 8U) /* ENA */ | (0U << 9U) /* CLK */ | (0U << 10U) /* SIMO */ | (0U << 11U); /* SOMI */ /** - MIBSPI3 Port direction */ mibspiREG3->PC1 = 0U /* SCS[0] */ | (0U << 1U) /* SCS[1] */ | (1U << 2U) /* SCS[2] */ | (1U << 3U) /* SCS[3] */ | (1U << 4U) /* SCS[4] */ | (1U << 5U) /* SCS[5] */ | (0U << 8U) /* ENA */ | (1U << 9U) /* CLK */ | (0U << 10U) /* SIMO */ | (1U << 11U); /* SOMI */ /** - MIBSPI3 Port open drain enable */ mibspiREG3->PC6 = 0U /* SCS[0] */ | (0U << 1U) /* SCS[1] */ | (0U << 2U) /* SCS[2] */ | (0U << 3U) /* SCS[3] */ | (0U << 4U) /* SCS[4] */ | (0U << 5U) /* SCS[5] */ | (0U << 8U) /* ENA */ | (0U << 9U) /* CLK */ | (0U << 10U) /* SIMO */ | (0U << 11U); /* SOMI */ /** - MIBSPI3 Port pullup / pulldown selection */ mibspiREG3->PC8 = 1U /* SCS[0] */ | (1U << 1U) /* SCS[1] */ | (1U << 2U) /* SCS[2] */ | (1U << 3U) /* SCS[3] */ | (1U << 4U) /* SCS[4] */ | (1U << 5U) /* SCS[5] */ | (1U << 8U) /* ENA */ | (1U << 9U) /* CLK */ | (1U << 10U) /* SIMO */ | (1U << 11U); /* SOMI */ /** - MIBSPI3 Port pullup / pulldown enable*/ mibspiREG3->PC7 = 0U /* SCS[0] */ | (0U << 1U) /* SCS[1] */ | (0U << 2U) /* SCS[2] */ | (0U << 3U) /* SCS[3] */ | (0U << 4U) /* SCS[4] */ | (0U << 5U) /* SCS[5] */ | (0U << 8U) /* ENA */ | (0U << 9U) /* CLK */ | (0U << 10U) /* SIMO */ | (0U << 11U); /* SOMI */ /* MIBSPI3 set all pins to functional */ mibspiREG3->PC0 = 0U /* SCS[0] */ | (0U << 1U) /* SCS[1] */ | (0U << 2U) /* SCS[2] */ | (0U << 3U) /* SCS[3] */ | (0U << 4U) /* SCS[4] */ | (0U << 5U) /* SCS[5] */ | (0U << 8U) /* ENA */ | (1U << 9U) /* CLK */ | (1U << 10U) /* SIMO */ | (1U << 11U); /* SOMI */ /** - Finally start MIBSPI3 */ mibspiREG3->GCR1 = (mibspiREG3->GCR1 & 0xFEFFFFFFU) | (1U << 24U);

  • H i Andrew,

    I have forwarded your question to our expert, and he will respond to your question soon.

    Regards,

    QJ

  • Hello Andrew,

      You are setting up the SPI3 as a slave but however it is generating the SPICLK. The SPIENA is supposed to be an output and the SPICS is supposed to be an input for a slave but now they are opposite. Can you try to configure the SPI3 with CLKMOD=0 and set the SPI1 CLKMOD=1?

  • Charles 

    Sorry for my delayed response and thanks for your suggestions. 

    I did goof on line 332 above where I set the port direction for the clk as an output. However, I see that I did set CLKMOD=0 on SPI3 (line 11 above). I've not changed 332 to set the clk as an input, but no change in behavior. 

    I also have the SPIENA and CS set as a GPIO instead of a of SPI pin, lines 376-382). Do their directions matter still?

    Other suggestions?

  • Hi Andrew,

      Can you look at the MibSPI3 RXRAM directly to see if the data is stored in their intended order in the transfer group buffer? The MibSPI3 RXRAM starts at 0xFF0C0200. Does the data get stored starting at the specified PSTART pointer? The PSTART is specified in the corresponding transfer group control register (TGxCTRL). Also if you are trying to trigger the transfer group multiple times, I will suggest to first only trigger for one time for simpler debugging. At the end of the TG transfer, check for any error in the upper 8 bits of each receive buffer in the RXRAM. You might also want to put a breakpoint before calling mibspiGetData() to move the TG data to the CPU RAM while you are examing the content of the RXRAM.

  • It's a little complicated to try to do only one trigger. I'll provide some more background first, and then I'll give an update on what I have now - I've got minor improvement.

    I am trying to communicate with an external device. It's interface is close to, but not quite SPI. What I have set up is to talk to the device through the SPI1 master. This device than does some stuff, and send data back on a clock that is the same frequency but slightly shifted as the clock sent to it. So that is why I set up SPI3 to be a slave - so that it can receive the data on those lines and use the clock returned by the device. However, this means that I do not care about the MISO pin on SPI1 and I do not care about the MISO pin on SPI3. SPI1 is only to send, SPI3 is only to receive. 

    I have tried the code with an external loopback SPI1 clock to SPI3 clock and SPI1 data to SPI3 data. This loopback seems to work fine.

    I've found a couple of funnies - I do not think they're related, but just in case:

    1. Even though SPI1 and 3 have their own RAMs/groups - I have to have my SPI1 master set up to be TG1 and my SPI3 slave to be TG0. Changing them does not work.
    2. I have to use a length of 8. Ideally I'd like to use a length of 16, but that doesn't work, which is why I have the for loop to do two tx/rx of length 8. 

    With the code below, I have been able to make it work correctly every other time. I found that the TGENA bit of Tg0CTRL would not clear after SPI3 received data. I don't know why, but it may be because the data on SPI3 isn't actually going anywhere. So if I clear that bit, it works every other time. I'm not sure what's preventing it from working all the time still though.

    for(i=0;i<FSR/TGROUP_SIZE;i++) //TGROUP_SIZE = 8, FSR = 16
        {
    
            mibspiREG3->TGCTRL[0] &= ~(0x80000000U);
            mibspiSetData(mibspiREG3, 0, tx); //This is dummy data on slave that doesn't go anywhere
            mibspiTransfer(mibspiREG3, 0);
    
    
    
            //set group 1, length 8, charlen 16, trigger rising on GIOA7, oneshot transfer, CS_NONE, dataFormat0, buffer mode 4
            //lock transmission, enable WDELAY, chip select hold and transfer group pointer reset are ALL unchecked
            mibspiSetData(mibspiREG1, 1, tx); //Set Master Data
            mibspiTransfer(mibspiREG1, 1);
            tx += TGROUP_SIZE;
    
            //trigger master and slave
            gioSetBit(hetPORT1,14,1);
            gioSetBit(hetPORT1,16,1);
    
    
            while (mibspiIsTransferComplete(mibspiREG3, 0) == 0);  // wait here until transfer is complete
            while (mibspiIsTransferComplete(mibspiREG1, 1) == 0);  // wait here until transfer is complete
            gioSetBit(hetPORT1,14,0);
            gioSetBit(hetPORT1,16,0);
    
            status = mibspiGetData(mibspiREG3, 0, prx);
            ti_printf("%x | ", status);
            prx += TGROUP_SIZE;
            sClockRx += (16*8);
    
        }

    As far as your questions go, I have checked and the data was not in the correct order in the rxRAM. But PSTART was correctly pointing to 0 in TG0 and it would correctly calculate end to be 8. The errors are an interesting one. The first time through, it works fine. No errors in the upper 8 bits of the rx buffer. The second time through when it incorrectly reads the data, again there's no errors. then every time after that whenever it gets the correct data, the status returned by mibspiGetData is 0x40, which if I'm reading the datasheet/code correctly is the last chip select number?

  • Nevermind on the LCSN, looking at the variables tab in the debugger, I see the flags of the rx part of the ram is actually 0x4000 on the first rx array item, indicating an overrun, not the LCSN. 

    But it still alternates between getting the right data and the wrong data. I do see other signs of the overrun, there's the RxBUF and Emu that have data in the receive fields for some reason.

  • Hello Andrew,

      You said that if you use external loopback between SPI1 and SPI3 then it works but does not work when the SPI3 is receiving the data from the external device. You also said that the external device is generating the SPICLK to the SPI3 but with the phase shifted. Not sure what the external device's setup on the clock polarity and phase. I think you want to make sure that the SPI3's polarity and phase setup is in agreement with the external device.

  • I've tried modifying the phase and polarity with no success. You can also see in the pictures in my first post that the data is set on the falling edge of the clock (SPI3SIMO goes up on the falling edge of SPI3CLK). This means that it is definitely is latched on the rising edge, so one of either polarity or phase. I have tried both (actually all permutations) with no success. 

    I realized I left out something else that may be relevant. The device I'm communicating with needs 8 clock cycles prior to sending it everything else. unfortunately, the device also passes those 8 clock cycles back. I think that's why I'm getting the overrun. I've tried powering down the SPI3 for those 8 clock cycles with no success. 

    I send the 8 clock cycles with 


    mibspiREG1 ->DAT1 = (mibspiREG1 ->DAT1) | (1U << 24);

    but I've also noticed it seems to mess with my PC2 register. I've also noticed that PC2 register alternates between 0x01010e0f (working) and 0x0101060F (when it doesnt work).

  • Hello Andrew,

      Back to your original question about the data being rotated in the receive buffer. Is this only seen when you hookup to the external device or even when you are in external loopback mode between SPI1 and SPI3. If there is no data rotation problem when you are in external loopback test then it indicates the transfer group is properly setup for SPI3. It will be good if you could limit the trigger (a rising edge on the GIO pin) to one so it is easier for you to debug if the subsequent triggers somehow overwrite the received data for the first trigger. Do you see data rotation if you change the TG size from 8 to a smaller value? Is the external device capable to add delay between transactions, i.e. the WDELAY as capable by the MibSPI module?

  • Thanks for your continued support here.

    I have tried adjusting the TG size from everything from 16 to 1 and they all behave similarly.

    I'm confident that the issue is with having to send the 8 preload clocks to the external device. Stepping through the code I see that every time I send it 8 clocks, the external device sends 8 clocks back which puts data in my spi3 ram. However, every other time I communicate with it, when I trigger SPI3 it overwrites the 8 preload clocks. This explains the overrun buffer status that I saw earlier

    What I am trying to do now is to set up a different transfer group to receive those 8 bits and do nothing with them, just store them in a different location. I set up Data format 1 to be charlen of 8, and spi3 TG 2 to use data format 1 with a length of 1 and a rising gio pin as the trigger. However, I still see that data that comes in on those 8 preload cycles go to the tg0 spot of the spi3 ram. Am I missing something else I need to set up TG2?

    Current version of my code:

        mibspiREG3->TGCTRL[0] &= ~(0x80000000U);//Only works the first time without this. Works every other time with it
    
        //Set up TG2 to receive 8 clocks of data and don't do anything with it
        mibspiSetData(mibspiREG3,2,preloadTX); //Dummy data that doesn't go anywhere
        mibspiTransfer(mibspiREG3,2);
    
        //Trigger for spi3 slave to be able to receive
        gioSetBit(hetPORT1,16,1);
    
        //send (and receive) 8 clock cycles to external device
        mibspiREG1->DAT1 = (mibspiREG1 ->DAT1) | (1U << 24);
    
    //    while (mibspiIsTransferComplete(mibspiREG3, 2) == 0);  // hangs - does not receive data into TG2
    
        //reset TG2 trigger source
        gioSetBit(hetPORT1,16,0);
    
        //increase the counter of the # of clocks sent to external device
        sClockRx +=8;
    
    //    for(i=0;i<FSR/TGROUP_SIZE;i++) //TGROUP_SIZE = 8, FSR = 16
    //    {
        //set group 0, length 16, charlen 16, trigger rising on hetPORT1 bit 14, oneshot transfer, CS_NONE, dataFormat0, buffer mode 4
        //lock transmission, enable WDELAY, chip select hold and transfer group pointer reset are ALL unchecked
        mibspiSetData(mibspiREG3, 0, tx); //This is dummy data on slave that doesn't go anywhere
        mibspiTransfer(mibspiREG3, 0);
    
        //set group 1, length 16, charlen 16, trigger rising on hetPORT1 bit 14, oneshot transfer, CS_NONE, dataFormat0, buffer mode 4
        //lock transmission, enable WDELAY, chip select hold and transfer group pointer reset are ALL unchecked
        mibspiSetData(mibspiREG1, 1, tx);
        mibspiTransfer(mibspiREG1, 1);
    
    //    tx += TGROUP_SIZE;
    
        //trigger master and slave
        gioSetBit(hetPORT1,14,1);
    
    
        while (mibspiIsTransferComplete(mibspiREG1, 1) == 0);  // wait here until transfer is complete
        while (mibspiIsTransferComplete(mibspiREG3, 0) == 0);  // wait here until transfer is complete
    
        gioSetBit(hetPORT1,14,0);
    
        status = mibspiGetData(mibspiREG3, 0, prx);
        prx += TGROUP_SIZE;
        sClockRx += (16*8);

  • Hi Andrew,

      Now I think I understand your setup. Your SPI3 is configured with charlengh=16 but the external device needs to first send 8 dummy clock cycles that does not carry the actual data. Is this the correct understanding? Is there any way for you to suppress these 8 clock cycles in the external device? Or while these 8 clock cycles are generated make the nCS inactive so that it does not select SPI3? I have also fowarded your question to another expert who might be able to suggest other options.

  • This a correct understanding! It's a weird device...

    Unfortunately I can not suppress them. I hadn't thought about making the nCS inactive. That may be a solution - but currently I am not using the CS at all. CS0 is brought out to a via, so maybe I can blue wire something to it. 

    My solution that I'm working on now is to try to change the data format dynamically. So set up the data format and TG information to take in 8 clock cycles, send the 8 dummy clocks, then change the data format and TG back to what I would ideally want. Does the MIBSPI need to be in reset for this process? It'd be a few more clock cycles than the nCS, so I will look into that possibility as well.

    I probably have some errors in the code below (hot off the presses!) but this is basically the idea I'm trying to implement for sending the 8 cycles:

    int i = 0U;
        //Reinit TG0 data charlen
        /** - Data Format 0 */
        mibspiREG3->FMT0 = (0U << 24U)  /* wdelay */
                      | (0U << 23U)  /* parity Polarity */
                      | (0U << 22U)  /* parity enable */
                      | (0U << 21U)  /* wait on enable */
                      | (0U << 20U)  /* shift direction */
                      | (0U << 17U)  /* clock polarity */
                      | (1U << 16U)  /* clock phase */
                      | (7U << 8U) /* baudrate prescale */
                      | 8U;  /* data word length */
        /** - initialize transfer groups */
        mibspiREG3->TGCTRL[0U] = (1U << 30U)  /* oneshot */
                           | (0U << 29U)  /* pcurrent reset */
                           | (TRG_RISING << 20U)  /* trigger event */
                           | (TRG_HET1_14 << 16U)  /* trigger source */
                           | (0U << 8U);  /* start buffer */
        mibspiREG3->LTGPEND = (mibspiREG3->LTGPEND & 0xFFFF00FFU) | (((1U+1U+1U+1U+0U+0U+0U+0U)-1U) << 8U);
    
        i = 0U;
        if (1U > 0U)
        {
            while (i < (1U-1U))
            {
                mibspiRAM3->tx[i].control = (4U << 13U)  /* buffer mode */
                                         | (0U << 12U)  /* chip select hold */
                                         | (0U << 11U)  /* lock transmission */
                                         | (0U << 8U)  /* data format */
                                         |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU));  /* chip select */
                i++;
            }
            mibspiRAM3->tx[i].control = (4U << 13U)  /* buffer mode */
                                     | (0U << 12U) /* chip select hold must be zero for last buffer */
                                     | (0U << 10U)  /* enable WDELAY */
                                     | (0U << 8U)  /* data format */
                                     |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU));  /* chip select */
            i++;
        }
    
        //Send 8 clock cycles
    
        uint16_t tx[1] = {0};
        uint16_t rx[1] = {0};
        mibspiSetData(mibspiREG3, 0, tx); //This is dummy data on slave that doesn't go anywhere
        mibspiTransfer(mibspiREG3, 0);
    
        //set group 1, length 16, charlen 16, trigger rising on hetPORT1 bit 14, oneshot transfer, CS_NONE, dataFormat0, buffer mode 4
        //lock transmission, enable WDELAY, chip select hold and transfer group pointer reset are ALL unchecked
        mibspiSetData(mibspiREG1, 1, tx);
        mibspiTransfer(mibspiREG1, 1);
    
    //    tx += TGROUP_SIZE;
    
        //trigger master and slave
        gioSetBit(hetPORT1,14,1);
    
        while (mibspiIsTransferComplete(mibspiREG1, 1) == 0);  // wait here until transfer is complete
        while (mibspiIsTransferComplete(mibspiREG3, 0) == 0);  // wait here until transfer is complete
    
        gioSetBit(hetPORT1,14,0);
        mibspiGetData(mibspiREG3, 0, rx);
        ti_printf("preload got %d\r\n\r\n", rx[0]);
    
        /** - Data Format 0 */
        mibspiREG3->FMT0 = (0U << 24U)  /* wdelay */
                      | (0U << 23U)  /* parity Polarity */
                      | (0U << 22U)  /* parity enable */
                      | (0U << 21U)  /* wait on enable */
                      | (0U << 20U)  /* shift direction */
                      | (0U << 17U)  /* clock polarity */
                      | (1U << 16U)  /* clock phase */
                      | (7U << 8U) /* baudrate prescale */
                      | 16U;  /* data word length */
    
        /** - initialize transfer groups */
        mibspiREG3->TGCTRL[0U] = (1U << 30U)  /* oneshot */
                           | (0U << 29U)  /* pcurrent reset */
                           | (TRG_RISING << 20U)  /* trigger event */
                           | (TRG_HET1_14 << 16U)  /* trigger source */
                           | (0U << 8U);  /* start buffer */
        i = 0U;
                       /*SAFETYMCUSW 139 S MR: 13.7 REVIEWED " If condition cannot be removed as the LHS depends on GUI configuraion " */
        if (16U > 0U)
        {
            while (i < (16U-1U))
            {
                mibspiRAM3->tx[i].control = (4U << 13U)  /* buffer mode */
                                         | (0U << 12U)  /* chip select hold */
                                         | (0U << 11U)  /* lock transmission */
                                         | (0U << 8U)  /* data format */
                                         |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU));  /* chip select */
                i++;
            }
            mibspiRAM3->tx[i].control = (4U << 13U)  /* buffer mode */
                                     | (0U << 12U) /* chip select hold must be zero for last buffer */
                                     | (0U << 10U)  /* enable WDELAY */
                                     | (0U << 8U)  /* data format */
                                     |(uint32)((~(uint32)((0x00U) ^ CS_NONE) & 0xFFU));  /* chip select */
            i++;
        }

  • Actually, I don't think the nCS idea will work based on this paragraph in SPNU217b;

    When operating in slave mode, the MibSPI uses the chip-select pins 0 to 3 to
    generate a trigger to the corresponding Transfer Group Setting “0000” on the
    chip-select pins triggers Transfer Group 0, “0001” triggers TG1. When the
    value “1111” is set to the chip-select, the MibSPI is deselected - that is
    Transfer Group 15 is not available in slave mode.

    I think that means that if I connect something to CS0 and raise it, I will just change to TG1. 

  • Hi Andrew,

      SPNU217b is the user guide for the R1x family of devices. These are very old devices. Can you please tell me what device you are using? If you are using our Hercules family of devices then please refer to the corresponding device TRM. I do not see such statement that the chip select is used as trigger in slave mode in functional mode in the Hercules TRM.

  • I am using an RM48L952 I did not realize that information was so old. It makes me a little concerned I wasn't able to change transfer groups. 

  • Hello Andrew,

      Checking the internal design spec of MibSPI, the paragraph you referred to is still valid. Please see below snippet. Sorry for the confusion.  Will need to update TRM to clarify for future release. As you can see in slave mode the trigger event and source has no effect.  What you can also do is that for the first RX buffer of the TG0 in MibSPI3 you setup the dataformat with charlengh=8 to take care of the 8 dummy clocks from the external device and the subsequent RX buffers in TG0 with charlengh=16. The dataformat can be specific to each buffer.

  • How would I go about setting up the first RX buffer in TG0 to be charlength = 8 and following ones be 16? I'm not entirely sure that this would fix my problem anyway because while in this case I need to send 8 dummy clocks followed by 16 u16 words, in other cases I need to send 8 dummy clocks followed by 3600 u16 words. But perhaps I can just go and change my pstart location after I send the 8 dummy clocks

    What I've done for now is I generated mibspiInit for sending 1 byte (charlen = 8, TG length = 1) and copied the code generated by HalCoGen into a separate function. I then regenerated HalCoGen for my normal setup (charlen = 16, TG length = 16). So before I send the 8 dummy clocks I call the 1bytemibspiInit, send 8 clocks, and then recall mibspiInit(). This seems to mostly work but now my rx buffer is doing something weird. It seems to swapping the bytes within the word, so 0x1234 becomes 0x3412. I can probably work around this - but I'm going to investigate this a little closer.

  • Hello Andrew,

      Sorry for not being clear. Let's say you have 8 16-bit data to transfer from the external device to MibSPI3. You can setup TG0 with 9 buffers. The first buffer will use dataformat with charlengh=8 and the next 8 buffers will use dataformat with charlengh=16. You will need to specify the dataformat for each buffer in the TXRAM, not RXRAM. I understand that your TXRAM for MibSPI is only to transmit dummy data. But the dataformat you specify in the TXRAM will be used for receive as well. HalcoGen will generate code to setup your TXRAM per your specified dataformat for the entire transfer group. You will need to manually change the dataformat for only the first buffer. For example, in HalcoGen use dataformat 1 for the 9 buffers in the transfer group. Later you will manually change buffer0 to use dataformat 0 by writing to the MibSPI3 TXRAM buffer0 directly.

  • ah - great! I didn't realize that setting the information for the tx would also then set up the rx, but I guess that  makes sense. 

    I will try this out and get back to you, but it sounds promising!

  • Hi Andrew,

      For some reason your very last post can not be found in the forum but I got in email at 12.54AM. I'm wondering if you have read the flags earlier in your code as what you are showing with 0xA0 or 0x20 they currently are indicating 0 for RXOVR. The RXOR is a read-clear flag. Once it is read, it is automatically cleared. The RXOVR is supposed to be set when the data transfer has been finished and the received data is copied into the corresponding RXDATA field while RXEMPTY flag is still 0.

    For rx[0] it is indicating it has received data in the RXDATA field while other buffers have not received data yet.

    In the meantime, I'm having internal discussion with others to see why you are not receiving data. Is this what happen right now?

  • Charles,

    sorry for my slow response. We've been able to blue-wire and rev the hardware to include a mux to stop the clock from coming back and that has fixed the problem. I will likely someday look at this again. I'm confident it somehow has to do with pstart or pcurrent not being reset to the proper position when it should. I will come back to update should I find anything.

    Thanks for all the help. I will try to find a post to mark it as 'solved' as a thanks for your time.

  • Finally got it to work the way intended. My problem before was that I wasn't looking at the flags register to wait until the transfer was done. So what I was doing was disabling it, then reenabling it in the middle of the transfer and that's why I couldn't get it to work. 

    	//Disable spi3 
        mibspiREG3->GCR1 &= ~(1 << 24);
        
        //send data on spi1 using data format 1 (8 clocks)
        mibspiREG1->DAT1 = (mibspiREG1 ->DAT1) | (1U << 24);
        //must wait until this is finished before enabling spi3 again
        while((mibspiREG1->FLG & (1 << 9)) == 0);
    
        //enable spi3 again
        mibspiREG3->GCR1 |= (1 << 24);

  • Hello Amdrew,

      thanks for the update. Glad that it is working for you now.