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.

SSI communication problems

Other Parts Discussed in Thread: TM4C123GH6PM

Hi, Im using the tm4c123gh6pm launchpad and im trying to set up a connection to my touchscreen controller via SSI.  However it seems that I cant even get the SSI to work on its own (no clock pulse or data on SSI0TX when im sending out data from the microcontroller). Since i dont have an oscilloscope at home i am using a multimeter to check the voltage level on the SSI0CLK pin but it does not change levels at all during transmission.

here is my little test code:

 

#define GPIO_PORTA_DIR_R        (*((volatile unsigned long *)0x40004400))
#define GPIO_PORTA_AFSEL_R      (*((volatile unsigned long *)0x40004420))
#define GPIO_PORTA_DEN_R        (*((volatile unsigned long *)0x4000451C))
#define GPIO_PORTA_AMSEL_R      (*((volatile unsigned long *)0x40004528))
#define GPIO_PORTA_PCTL_R       (*((volatile unsigned long *)0x4000452C))
#define SSI0_CR0_R              (*((volatile unsigned long *)0x40008000))
#define SSI0_CR1_R              (*((volatile unsigned long *)0x40008004))
#define SSI0_DR_R               (*((volatile unsigned long *)0x40008008))
#define SSI0_SR_R               (*((volatile unsigned long *)0x4000800C))
#define SSI0_CPSR_R             (*((volatile unsigned long *)0x40008010))
#define SSI0_CC_R               (*((volatile unsigned long *)0x40008FC8))
#define SSI_CR0_SCR_M           0x0000FF00  // SSI Serial Clock Rate
#define SSI_CR0_SPH             0x00000080  // SSI Serial Clock Phase
#define SSI_CR0_SPO             0x00000040  // SSI Serial Clock Polarity
#define SSI_CR0_FRF_M           0x00000030  // SSI Frame Format Select
#define SSI_CR0_FRF_MOTO        0x00000000  // Freescale SPI Frame Format
#define SSI_CR0_DSS_M           0x0000000F  // SSI Data Size Select
#define SSI_CR0_DSS_8           0x00000007  // 8-bit data
#define SSI_CR1_MS              0x00000004  // SSI Master/Slave Select
#define SSI_CR1_SSE             0x00000002  // SSI Synchronous Serial Port
                                            // Enable
#define SSI_SR_RNE              0x00000004  // SSI Receive FIFO Not Empty
#define SSI_SR_TNF              0x00000002  // SSI Transmit FIFO Not Full
#define SSI_SR_TFE              0x00000001  // SSI Transmit FIFO Empty
#define SSI_CPSR_CPSDVSR_M      0x000000FF  // SSI Clock Prescale Divisor
#define SSI_CC_CS_M             0x0000000F  // SSI Baud Clock Source
#define SSI_CC_CS_SYSPLL        0x00000000  // Either the system clock (if the
                                            // PLL bypass is in effect) or the
                                            // PLL output (default)
#define SYSCTL_RCGC1_R          (*((volatile unsigned long *)0x400FE104))
#define SYSCTL_RCGC2_R          (*((volatile unsigned long *)0x400FE108))
#define SYSCTL_RCGC1_SSI0       0x00000010  // SSI0 Clock Gating Control
#define SYSCTL_RCGC2_GPIOA      0x00000001  // port A Clock Gating Control

unsigned int testvalue;
void ssi_Init(void);
unsigned int test(void);

int main(void){
	ssi_Init();
		while(1){
			testvalue = test();
		}
}

void ssi_Init(void){
  volatile unsigned long delay;
  SYSCTL_RCGC1_R |= SYSCTL_RCGC1_SSI0;  // activate SSI0
  SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOA; // activate port A
  delay = SYSCTL_RCGC2_R;               // allow time to finish activating
  GPIO_PORTA_DIR_R |= 0xC0;             // make PA6,7 out
  GPIO_PORTA_AFSEL_R |= 0x2C;           // enable alt funct on PA2,3,5
  GPIO_PORTA_AFSEL_R &= ~0xC0;          // disable alt funct on PA6,7
  GPIO_PORTA_DEN_R |= 0xEC;             // enable digital I/O on PA2,3,5,6,7
                                        // configure PA2,3,5 as SSI
  GPIO_PORTA_PCTL_R = (GPIO_PORTA_PCTL_R&0xFF0F00FF)+0x00202200;
                                        // configure PA6,7 as GPIO
  GPIO_PORTA_PCTL_R = (GPIO_PORTA_PCTL_R&0x00FFFFFF)+0x00000000;
  GPIO_PORTA_AMSEL_R &= ~0xEC;          // disable analog functionality on PA2,3,5,6,7
  SSI0_CR1_R &= ~SSI_CR1_SSE;           // disable SSI
  SSI0_CR1_R &= ~SSI_CR1_MS;            // master mode
                                        // configure for system clock/PLL baud clock source
  SSI0_CC_R = (SSI0_CC_R&~SSI_CC_CS_M)+SSI_CC_CS_SYSPLL;
                                        // clock divider for 2 MHz SSIClk (16 MHz PIOSC/8)
  SSI0_CPSR_R = (SSI0_CPSR_R&~SSI_CPSR_CPSDVSR_M)+8;
  SSI0_CR0_R &= ~(SSI_CR0_SCR_M |       // SCR = 0 (2 Mbps data rate)
                  SSI_CR0_SPH |         // SPH = 0
                  SSI_CR0_SPO);         // SPO = 0
                                        // FRF = Freescale format
  SSI0_CR0_R = (SSI0_CR0_R&~SSI_CR0_FRF_M)+SSI_CR0_FRF_MOTO;
                                        // DSS = 8-bit data
  SSI0_CR0_R = (SSI0_CR0_R&~SSI_CR0_DSS_M)+SSI_CR0_DSS_8;
  SSI0_CR1_R |= SSI_CR1_SSE;            // enable SSI
}
	
unsigned int test(void)
{
volatile unsigned long value = 0;
	
  SSI0_DR_R = 0x90;          // data out
  while((SSI0_SR_R&10)){};   // wait until data has finished transmitting
  value = SSI0_DR_R;     
return value;
}	

 

  • Hello Wayne,

    I checked the code on my TM4C123 LaunchPad and it works fine sending the data. The issue in the code is that in while loop waiting for data to complete it does a logical operation with decimal 10 and not hex 10.

      while((SSI0_SR_R&10)){};   // wait until data has finished transmitting

    which has to be replaced by

      while((SSI0_SR_R&0x10)){};   // wait until data has finished transmitting

    Regards

    Amit

  • Hi Amit,

    Good job - this reporter "gave up" after 20th line (or so) of "direct-register" set-up/decode...

    Bet you that Wayne was sufficiently exhausted from such (needless) extra effort - practically "guaranteed" that he'd confuse decimal w/required hex...

    Driver libraries make life so much easier.  (especially for you - and your unsanctioned cohorts...)  Rarely is there a, "justificable reason" for their bypass...  (suggest that theme (USE the Driver Lib!) be continually Sounded!)

  • I connected the tx and rx pin together to see if my data was sending properly, but no matter what value i send to myself i keep receiving 0xFF.  i am debugging it using stellaris ICDI.

  • Hello Wayne,

    Can you attach the updated code as the first code had a mistake and it is not doing a read?

    Regards

    Amit

  • Hi Amit,

    i am using the same code with the fix you posted.

     For example when i call testvalue = test() in my main the value i get equals 0xFF and not 0x90;

    unsigned int test(void)
    {
    volatile unsigned long value = 0;
        
      SSI0_DR_R = 0x90;          // data out
      while((SSI0_SR_R&0x10)){};   // wait until data has finished transmitting
      value = SSI0_DR_R;     
    return value;
    } 

     

  • Hello Wayne,

    My bad. Missed that

    What you need to do is to make sure that the SSISR register bit RNE is set before you do a read call. Or alternatively set the LBE bit which will internally loopback TX to RX and can be used to find is the correct pins on external loopback have been done.

    Regards

    Amit

  • Ah I forgot to initialize the RX pin for SSI.  I appreciate all the help Amit! ^^ 

     

  • Be careful using the RNE bit.

    I had problems with reading the correct value out of the RX FIFO.  Based on what I can tell, the RNE bit is set as soon as the hardware starts clocking data in, not when it finishes and a value is ready to be read. 

    I ensured the receive FIFO was empty before I sent the dummy value to clock in the read value.   I was the waiting on the RNE bit to start reading the FIFO, and was getting incorrect values.  Turned out they were the previous values in the FIFO.  Since I was looking for only one value, I was able to wait on the busy bit instead.  When it went inactive, I could read correct values.  If you are looking for more than one value in the FIFO, you may need a different way of determining when it is safe to read.

    Mike

  • Hello Mike,

    That is a good comment regarding the SSI Mode. That is why in TM4C129 we implemented the Advanced mode where the CPU can decide at which TX it safe to sample the RX pin to the FIFO. This would eliminate the need of RXFIFO Flush.

    Appreciate the feedback always.

    Regards

    Amit