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.
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