Part Number: TM4C129XNCZAD
After discovering the problem with the CS being enabled while changing SSI modes in the related post, I was sure I knew how to fix the problem. Imagine my surprise when even after not activating the chip select until after the call to SSIConfigSetExpClk(), the problem with the corrupted transmission persisted! I found something interesting, and wanted to share my discovery in case it may help someone else later on.
The following code will result in the second communications session with Device A having the 0xB0 be corrupted to a 0x58, 0x00 transaction:
uint32_t dummy = 0;
// ***** Device A Write
SSIDisable(SSI3_BASE);
SSIConfigSetExpClk( SSI3_BASE, getSystemClockFreqHz(),
SSI_FRF_MOTO_MODE_3,
SSI_MODE_MASTER,
2000000L,
8 );
GPIOPinWrite(LCD_CSn_PORT, LCD_CSn_PIN, 0); // chip select low
SSIEnable(SSI3_BASE);
SSIDataPutNonBlocking(SSI3_BASE, 0xB0);
SSIDataGet(SSI3_BASE, &dummy);
// make sure the rx fifo is empty
while ( 0 != SSIDataGetNonBlocking (SSI3_BASE, &dummy) )
{
}
GPIOPinWrite(LCD_CSn_PORT, LCD_CSn_PIN, LCD_CSn_PIN); // chip select high
// ***** Device B Write
SSIDisable(SSI3_BASE);
SSIConfigSetExpClk( SSI3_BASE, getSystemClockFreqHz(),
SSI_FRF_MOTO_MODE_0,
SSI_MODE_MASTER,
500000L,
16 );
GPIOPinWrite(AM_CSn_PORT, AM_CSn_PIN, 0); // chip select low
SSIEnable(SSI3_BASE);
SSIDataPutNonBlocking(SSI3_BASE, 0x1234);
SSIDataGet(SSI3_BASE, &dummy);
// make sure the rx fifo is empty
while ( 0 != SSIDataGetNonBlocking (SSI3_BASE, &dummy) )
{
}
GPIOPinWrite(AM_CSn_PORT, AM_CSn_PIN, AM_CSn_PIN); // chip select high
// ***** Device A Write
SSIDisable(SSI3_BASE);
SSIConfigSetExpClk( SSI3_BASE, getSystemClockFreqHz(),
SSI_FRF_MOTO_MODE_3,
SSI_MODE_MASTER,
2000000L,
8 );
GPIOPinWrite(LCD_CSn_PORT, LCD_CSn_PIN, 0); // chip select low
SSIEnable(SSI3_BASE);
SSIDataPutNonBlocking(SSI3_BASE, 0xB0);
SSIDataGet(SSI3_BASE, &dummy);
// make sure the rx fifo is empty
while ( 0 != SSIDataGetNonBlocking (SSI3_BASE, &dummy) )
{
}
GPIOPinWrite(LCD_CSn_PORT, LCD_CSn_PIN, LCD_CSn_PIN); // chip select high}
The reason is, as you can see from the logic analyzer screenshot below, that when SSIConfigSetExpClk() is called to change the mode from 0 to 3, the clock signal polarity does not actually change until SSIEnable() is called, which is my example is after the CS is asserted.
However, if I change the code slightly by enabling the SSI before asserting the CS, the clock polarity toggles before the chip select goes low, and the transaction looks fine:
In retrospect, it makes perfect sense that the changes to the SSI configuration would not become active until the peripheral is re-enabled. But when deep in the process of trying to get code working, it was not immediately obvious -- at least to me!
Regards,
Dave