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.

CC2540 SPI SLAVE WITH INT

Other Parts Discussed in Thread: CC2541, CC2540

Hi there,

I am trying to implement an SPI Slave with Interrupt with my CC2540.  I have seen the example for the CC2541 and have written one for my CC2540.

I use a PIC for my SPI Master that sends a byte every time I press a button @ 2Mbps.  I know it sends the proper value @ the baud rate needed because other SPI peripherals that I have work fine.  When I try to send the value (0xAC) to the CC2540, the CC2540 recognize that there is an SPI interrupt and enters the uart0rx_isr.  There when I try to read the U0DBUF, it always reads 0x00.  Here is the code that I am using.  If anyone has dealt with a similar problem, help will be appreciated.

/***********************************************************************************
* INCLUDES
*/

#include <hal_types.h>

#include <ioCC254x_bitdef.h>

#include "ioCC2540.h"



/***********************************************************************************
* CONSTANTS
*/

// These values will give a baud rate of approx. 2.00 Mbps at 32 MHz system clock.
#define SPI_BAUD_M  0
#define SPI_BAUD_E  16


// Define size of buffer.
#define BUFFER_SIZE 252

/***********************************************************************************
* LOCAL VARIABLES
*/

/***********************************************************************************
* LOCAL FUNCTIONS
*/
void MyTime(uint16 tdelay)
{
  for(unsigned short i=0;i<tdelay;i++)
  {
    asm("NOP");
  }
}

/***********************************************************************************
* @fn          uart0rx_isr
*
* @brief       Interrupt routine which receives data from master
*
* @param       none
*
* @return      0
*/

#pragma vector = URX0_VECTOR
__interrupt void uart0rx_isr(void)
{
  

    static uint8 bufferIndex = 0;

   
    if(U0DBUF == 0xAC || U0DBUF == 0xCA)                                        //   || U0DBUF == 0x00
    {
      P0_1 = 0;   // LED Off.
    }
    else
    {
      P0_1 = 1;   // LED On.
    }
    
asm("NOP");
 asm("NOP");
 asm("NOP");

    
    P0_1 = 1;   // LED On.
    
  
}



/***********************************************************************************
* @fn          main
*
* @brief       Receive data using SPI in master mode
*
* @param       void
*
* @return      void
*/

void main(void)
{
  #define SPIMY  0x10
    /****************************************************************************
     * Clock setup
     * See basic software example "clk_xosc_cc254x"
     */
    
    // Set system clock source to HS XOSC, with no pre-scaling.
    CLKCONCMD = (CLKCONCMD & ~(CLKCON_OSC | CLKCON_CLKSPD)) | CLKCON_CLKSPD_32M;
    // Wait until clock source has changed.
    while (CLKCONSTA & CLKCON_OSC);
    
    // Note the 32 kHz RCOSC starts calibrating, if not disabled.
    
    
    /***************************************************************************
     * Setup I/O ports
     *
     * Port and pins used USART0 operating in SPI-mode are
     * MISO (MI): P0_2
     * MOSI (MO): P0_3
     * SSN (SS) : P0_4
     * SCK (C)  : P0_5
     *
     * These pins can be set to function as peripheral I/O so that they
     * can be used by USART0 SPI. Note however, when SPI is in master mode,
     * only MOSI, MISO, and SCK should be configured as peripheral I/O's.
     * If the external slave device requires a slave select signal (SSN),
     * this can be implemented by using general-purpose I/O pin configured as
     * output.
     */


    PERCFG = 0x00;    

    P2DIR = 0x00;

    
    //// Set pins 2, 3 and 5 as peripheral I/O and pin 4 as GPIO output.
    //P0SEL = 0x2c;       // Master Mode
    //P0DIR = 0x12;       // Master Mode P0_1 LED
    
    
    //Set pins 2, 3, 4 and 5 as peripheral I/O.
    P0SEL = 0x3c;       // Slave Mode
    P0DIR = 0x02;       // Slave Mode P0_1 LED
    

    P1SEL = 0x00;      // GPIO.
    P1DIR = 0x00;      // Output.
    
    
    
    P0_1 = 1;          // LED On.

    
    
     /***************************************************************************
     * Setup interrupt
     */

    // Clear CPU interrupt flag for USART0 RX (TCON.URX0IF)
    URX0IF = 0;

    // Set individual interrupt enable bit in the peripherals SFR
    // Not any.

    // Enable interrupt from USART0 RX by setting [IEN0.URX0IE=1]
    URX0IE = 1;

    // Enable global interrupts
    EA = 1;
    
    

    /***************************************************************************
     * Configure SPI
     */

    //// Set USART to SPI mode and Master mode.
    //U0CSR = 0x00;

     // Set USART to SPI mode and Slave mode.
    U0CSR = 0x20;
    
    // Set:
    // - mantissa value
    // - exponent value
    // - clock phase to be centered on first edge of SCK period
    // - negative clock polarity (SCK low when idle)
    // - bit order for transfers to LSB first
    U0BAUD =  SPI_BAUD_M;
    U0GCR = SPIMY;

 while(1); 
    
}


/***********************************************************************************
  Copyright 2012 Texas Instruments Incorporated. All rights reserved.

  IMPORTANT: Your use of this Software is limited to those specific rights
  granted under the terms of a software license agreement between the user
  who downloaded the software, his/her employer (which must be your employer)
  and Texas Instruments Incorporated (the "License").  You may not use this
  Software unless you agree to abide by the terms of the License. The License
  limits your use, and you acknowledge, that the Software may not be modified,
  copied or distributed unless embedded on a Texas Instruments microcontroller
  or used solely and exclusively in conjunction with a Texas Instruments radio
  frequency transceiver, which is integrated into your product.  Other than for
  the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  works of, modify, distribute, perform, display or sell this Software and/or
  its documentation for any purpose.

  YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.

  Should you have any questions regarding your right to use this Software,
  contact Texas Instruments Incorporated at www.TI.com.
***********************************************************************************/
  • Hey Georgios,

    I've been trying to compare how you've configured your USART0 subsystem with the hal_uart_spi API functions. I noticed one difference. If you find the file _hal_uart_spi.c within the TI BLE stack and look at the function HalUARTOpenSPI() you'll notice that U0CSR.RE (UART Rx enable) bit is set and you are only setting the SPI slave bit.

    The user's guide is a little ambiguous on whether this UART receiver enable bit enables Rx for the USART module (meaning either SPI or UART mode), or only when configured for UART mode is selected. Thus we are left with trial and error. Try setting this rec. enable bit and see if it changes anything.

    You can also take a look through the _hal_uart_spi.c to see how the USART module is configured but the only difference that jumped out at me was that bit.

    -Matt

  • Hi Matt,

    Well I just think I am into the twilight zone.  Firstly thank you for the reply.  But it did not work out.  Secondly I tried something radical.

    I made my CC2540 a Master as shown in the example spi_master_send.c and it worked fine, it was sending the data drom P0_3 which is the MO pin In USART 0 SPI.

    I then made the CC2540 a Slave with Interrupts and at each interrupt I was sending back a specific value.  Now is the strange part.  The CC2540 was transmiting the value from P0_2, which according to the datasheet is the MI.

    Once I reversed them using two batch cables, it worked properly and received and transmitted normally.

    Is it possible to have the same registers (except P0SEL,P0DIR,U0CSR which need to be changed from Master to Slave) and the CC2540 to transmit data from MI instead of MO?

  • This actually makes a lot of sense. When your device is configured as a master it will transmit from MO and receive from MI. However these pins are fully labeled MOSI (master out slave in) and MISO (master in slave out). When you configure the device as a slave, the MISO pin is used to transmit and the MOSI pin is used to recieve. This means that the direction of data flow on these pins changes depending on its role. This is what you are seeing above. If you connect both MISO pins together and both MOSI pins together on your two devices then you should be fine for your SPI comms.

    Check out section 17.2.2 in the user's guide for a better explanation of the data flow directions on the pins. Hope that helps.

    -Matt

  • Matt,

    Thank you for the reply.  Now all makes sense.  I am used to programming using μC that you specify the SDO,SDI and they don't change regardless of master or slave mode.  But isn't this a problem when the CC2540 is a peripheral and the main μC has predefined SDO and SDI pins?

    Thank you again for all your help,

    Best regards,,

    Georgios

  • Hey Georgios,

    Even if your μC has fixed SPI channels as long as the MISO and MOSI pins for both devices are connect you should be ok. The only problem I would see would be if you needed to change roles between master/slave (which is somehwat of a corner case). In that situation if your μC didn't also change the data flow direction as the CC2540 does then it would not work.

    Glad I could help,

    Matt

  • Hello,

    It is the first time I am programming cc2540 and I am trying to interface it with a memory module through SPI.
    Can anyone helps me? I am somehow confused.

    Firstly I am trying to use simpleBLEPeripheral example. It worked for a time. I changed the broadcast name from "SimpleBLEPeripheral" to "Something" and my phone recognized the BLE. But now, when I simulate again the same example, my phone doesn't recognize anything. Do you understand what happens?

    Also, the simple BLE Bridge example results in a bug, connected to HAL_BOARD_INIT and SLEEPCMD, do you understand what happens ?

    Thank you very much.