Post Go back to editing

Problems with CM408F on SPI protocol

I'm working with CM408F on SPI 0 but I have problem to read the answer of the connected slave, see timings below:

CH1: Is ChipSelect 
CH2: MISO
CH3: MOSI
CH4: SCLK
I send a command (0x38) on SPI to my slave and I must receive from it 0x2E88.
Scope dump confirm that sent and received data is correct.
But in my program I receive instead 012E88, and after this all rxed data is out of phase of one byte.
I can't find where my program is wrong or a patch to sync again data.
This is my init code (is a fragment):
unsigned baud;
bool cpha, cpol, msb;
volatile uint32_t * reg, wl;
reg = pREG_SPI0_CTL;
*pREG_PORTA_DATA_CLR = SPIENA;
*pREG_PORTA_DATA_CLR = PAD0 | PAD1 | PAD2 | PAD3; // Clear address
// Default values
REG_SPI_CTL = 0x00000010u;
REG_SPI_RXCTL = 0x00000000u;
REG_SPI_TXCTL = 0x00000000u;
REG_SPI_CLK = 0x00000000u;
REG_SPI_DLY = 0x00000301u;
REG_SPI_SLVSEL = 0x0000FE02u;
REG_SPI_RWC = 0x00000000u;
REG_SPI_RWCR = 0x00000000u;
REG_SPI_TWC = 0x00000000u;
REG_SPI_TWCR = 0x00000000u;

cpol = true;
cpha = false;
msb = true;
*pREG_PORTA_DATA_SET = PAD0 | PAD1 | PAD2; // Address = 7
baud = 1; // 2 MHz
wl = 8; // 8 bit

wl = wl / 8 - 1;
REG_SPI_CLK = PERIPHERALS_FREQUENCY / (baud + 1);
if(cpha) REG_SPI_CTL |= ENUM_SPI_CTL_SCKBEG;
if(cpol) REG_SPI_CTL |= ENUM_SPI_CTL_SCKLO;
if(!msb) REG_SPI_CTL |= ENUM_SPI_CTL_LSB_FIRST;
REG_SPI_CTL |= ((wl << BITP_SPI_CTL_SIZE) | ENUM_SPI_CTL_MASTER);
REG_SPI_RXCTL |= ENUM_SPI_RXCTL_RX_EN;
REG_SPI_TXCTL |= ENUM_SPI_TXCTL_TX_EN;
REG_SPI_CTL |= ENUM_SPI_CTL_EN;
*pREG_PORTA_DATA_SET = SPIENA;
REG_SPI_ICLR = BITM_SPI_ILAT_CLR_TF | BITM_SPI_ILAT_CLR_RF | BITM_SPI_ILAT_CLR_TS | BITM_SPI_ILAT_CLR_RS;

To send and receive data I use:

unsigned SpiSend(int spiNum, unsigned data)
{
volatile uint32_t * reg, d;
switch(spiNum)
{
case 0: reg = pREG_SPI0_CTL;
break;
case 1: reg = pREG_SPI1_CTL;
break;
case 2: reg = pREG_SPI2_CTL;
break;
}
REG_SPI_TX = data;
REG_SPI_RXCTL |= ENUM_SPI_RXCTL_RTI_EN;
REG_SPI_TXCTL |= ENUM_SPI_TXCTL_TTI_EN;
while(!(REG_SPI_STS & BITM_SPI_STAT_SPIF));
REG_SPI_TXCTL &= (~ENUM_SPI_TXCTL_TTI_EN);
REG_SPI_RXCTL &= (~ENUM_SPI_RXCTL_RTI_EN);
return REG_SPI_RX;
}

I hope someone can help me because I do not know what fish to catch!
Regards
Manuele

  • I found the error, I hope to be useful for all developers of this micro that they don't want to use ADI's API and with GCC as compiler.
    The init must be changed in this mode:
    wl = wl / 8 - 1;
    REG_SPI_CLK = PERIPHERALS_FREQUENCY / (baud + 1);
    if(cpha) REG_SPI_CTL |= ENUM_SPI_CTL_SCKBEG;
    if(cpol) REG_SPI_CTL |= ENUM_SPI_CTL_SCKLO;
    if(!msb) REG_SPI_CTL |= ENUM_SPI_CTL_LSB_FIRST;
    REG_SPI_CTL |= ((wl << BITP_SPI_CTL_SIZE) | ENUM_SPI_CTL_MASTER);
    REG_SPI_RXCTL |= ENUM_SPI_RXCTL_RX_EN | ENUM_SPI_RXCTL_RWC_EN;
    REG_SPI_TXCTL |= ENUM_SPI_TXCTL_TX_EN;
    REG_SPI_CTL |= ENUM_SPI_CTL_EN;
    *pREG_PORTA_DATA_SET = SPIENA;
    // Clear flags
    REG_SPI_STS |= ENUM_SPI_STAT_TF_HI;
    REG_SPI_STS |= ENUM_SPI_STAT_RF_HI;

    And send/receive procedure now is:
    unsigned SpiSend(int spiNum, unsigned data)
    {
    volatile uint32_t * reg, d;
    switch(spiNum)
    {
    case 0: reg = pREG_SPI0_CTL;
    break;
    case 1: reg = pREG_SPI1_CTL;
    break;
    case 2: reg = pREG_SPI2_CTL;
    break;
    }
    REG_SPI_RWC = 1; // To be received
    REG_SPI_TWC = 1; // To be transmitted
    REG_SPI_TX = data;
    REG_SPI_RXCTL |= ENUM_SPI_RXCTL_RTI_EN;
    REG_SPI_TXCTL |= ENUM_SPI_TXCTL_TTI_EN;
    // If receive is complete also transmit is done
    while(!(REG_SPI_STS & ENUM_SPI_STAT_RF_HI));
    REG_SPI_TXCTL &= (~ENUM_SPI_TXCTL_TTI_EN);
    REG_SPI_RXCTL &= (~ENUM_SPI_RXCTL_RTI_EN);
    // Clear flags
    REG_SPI_STS |= ENUM_SPI_STAT_TF_HI;
    REG_SPI_STS |= ENUM_SPI_STAT_RF_HI;
    return REG_SPI_RX;
    }

    Regards
    Manuele