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.

  • Resolved

SPI Slave problem

Prodigy 220 points

Replies: 7

Views: 3972

I’m using TM4C123GH6PM, Tiva Launch Pad EK-TM4C123GXL to be more specific.

I have a SPI Master sending me commands, so I should parse the command and act accordingly.

I configure my chip as SPI Slave

void Ssi0Setup(void)
{
  // The SSI0 peripheral must be enabled for use.
  SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
  // For this example SSI0 is used with PortA[5:2].
  //SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
  // Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
  GPIOPinConfigure(GPIO_PA2_SSI0CLK);
  GPIOPinConfigure(GPIO_PA3_SSI0FSS);
  GPIOPinConfigure(GPIO_PA4_SSI0RX);
  GPIOPinConfigure(GPIO_PA5_SSI0TX);
  // Configure the GPIO settings for the SSI pins.This function also gives
  GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
                   GPIO_PIN_2);
  SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
                       SSI_MODE_SLAVE, 2000000, 8);
  // Enable the SSI0 module.
  SSIEnable(SSI0_BASE);
  //enable interrupts
  SSIIntEnable(SSI0_BASE, SSI_RXFF | SSI_RXTO | SSI_RXOR );
  // Read any residual data from the SSI port.  This makes sure the receive
  // FIFOs are empty, so we don't read any unwanted junk.
  while(SSIDataGetNonBlocking(SSI0_BASE, &ssi_data_rx[0]))
    {
    }
}

int main()
{
  ClockSetup();
  GpioSetup();
  UartSetup();
  Ssi0Setup();
  //Enable processor interrupts.
  ROM_IntMasterEnable();

  //to see the chip alive
  UARTSendStr("Endat test\r");

  while(1)
  {
    if(ssi_int_flag)
    {
      ssi_int_flag = 0;
      SSIDataGet(SSI0_BASE, &ssi_data_rx[0]);
      // Since we are using 8-bit data, mask off the MSB.
      ssi_data_rx[0] &= 0x00FF;
      ssi_command = (ssi_data_rx[0] & 0x00CF);
      switch(ssi_command)
      {
        case ENC_SND_POS_VAL:
          UARTSendStr("Encoder send position values\r"); 
          Blink(1);
        break;
        case ENC_SEL_MEM_ARE:
          UARTSendStr("Selection of memory area\r"); 
          Blink(2);
        break;
        case ENC_REC_PARAM:
          UARTSendStr("Encoder receive parameter\r"); 
          Blink(3);
        break;
        case ENC_SND_PARAM:
          UARTSendStr("Encoder send parameter\r"); 
          Blink(4);
        break;
        case ENC_REC_RST:
          UARTSendStr("Encoder receive reset\r"); 
          Blink(5);
        break;
        default:
          UARTSendStr("Invalid command\r");  
        break;
        
      }
      //clear FIFO
      while(SSIDataGetNonBlocking(SSI0_BASE, &ssi_data_rx[0]))
      {  }
    }  
  }
}

//Interrupt for SSI0
void SSI0_ISR(void)
{
  UARTSendStr("SSI Int\r"); //for debug 
  uint32_t int_status;
  //Get the interrrupt status.
  int_status = ROM_SSIIntStatus(SSI0_BASE, true);
  // Clear the asserted interrupts.
  ROM_SSIIntClear(SSI0_BASE, int_status);
    if(int_status==SSI_RXFF)
    {
      ssi_int_flag = 1;
    }
}

I get no interrupt also i see valid signal on SSI0Rx and SSI0CLK lines.

  • Guru 26105 points

    Hi,

    I have attached an spi slave example for you - compare with your code. Usually it is not a good idea to use UART routines inside real time interrupts, (specially with a slave, since this cannot force the master to wait for you).

    Not sure if you declared the interrupt inside startup_xxx.c file.

    5710.spi_slave.zip

    Petrei 

  • In reply to Petrei:

    Thank you Petrei,

    I use UART routines inside interrupt only for debug purpose. I use IAR and i included startup_ewarm.c file into the project but  I'm not sure it's linked to the project - i see no entry point to the startup file.

  • In reply to Evgeny7:

    It looks like startup  file isn't linked properly to the project. Is there some settings for it in IAR?

  • In reply to Evgeny7:

    Here's how our ver 6.70 of IAR handles: (all w/in "startup_ewarm.c")

    // this entry just after, "External declarations for the interrupt handlers...

    // The entry point for the application startup code.
    //
    //*****************************************************************************
    extern void __iar_program_start(void);
    //*****************************************************************************

    And after the Vector Table comes:

    // This is the code that gets called when the processor first starts execution
    // following a reset event.  Only the absolutely necessary set is performed,
    // after which the application supplied entry() routine is called.  Any fancy
    // actions (such as making decisions based on the reset cause register, and
    // resetting the bits in that register) are left solely in the hands of the
    // application.
    //
    //*****************************************************************************
    void
    ResetISR(void)
    {
        //
        // Enable the floating-point unit.  This must be done here to handle the
        // case where main() uses floating-point and the function prologue saves
        // floating-point registers (which will fault if floating-point is not
        // enabled).  Any configuration of the floating-point unit using DriverLib
        // APIs must be done here prior to the floating-point unit being enabled.
        //
        // Note that this does not use DriverLib since it might not be included in
        // this project.
        //
        HWREG(NVIC_CPAC) = ((HWREG(NVIC_CPAC) &
                             ~(NVIC_CPAC_CP10_M | NVIC_CPAC_CP11_M)) |
                            NVIC_CPAC_CP10_FULL | NVIC_CPAC_CP11_FULL);

        //
        // Call the application's entry point.
        //
        __iar_program_start();
    }

  • In reply to cb1_mobile:

    Thank you cb1_mobile.

    I have the same code in the file.

  • In reply to Evgeny7:

    Thank you, Evgeny7.

    If you don't achieve your SPI Slave Interrupt might that indicate some "mismatch" between your Master & your "set-up" of the MCU's Slave protocol?  As I recall - the set-up for Slave mode requires close attention to detail - especially the recongition that when these MCUs are placed in Slave mode - the SPI speed is greatly reduced!  (iirc - there is a "divide by 12" factor imposed upon SPI clock rate when in Slave mode...)

  • In reply to Petrei:

    Hi Petrei,

    The code has been very helpful and I am currently trying to run it on the TM4C1294XL launchpad.

    I believe I made all the necessary changes such as Clock, GPIO and Interrupt.

    I've also changed all the unsigned long variables into unsigned int 32. To make it the same as spi_master.c

    On the uart Terminal I get:

    Sent: 's' 'p' 'i'

    But it stops there and the Console displays:

    CORTEX_M4_0: Error: Debug Port error occurred.
    CORTEX_M4_0: Trouble Halting Target CPU

    I think the problem might be the interrupt handler. I declared SSI2IntHandler and added it into the vector table in startup_ccs.c

    The warning is #2120-D static function "SSI2IntHandler" treated as extern because it was referenced but not defined.

    Any suggestions? Thanks

    Stephen

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.