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 via SerialInterface

Other Parts Discussed in Thread: CC2540

I'm trying to implement HCI over SPI on the CC2540, and as a first step, I'm trying just to get basic commands sent over SPI and interpreted by the CC2540 as a SPI Slave. 

I followed the instructions at this wiki () and have integrated the SerialInterface API into the SimpleBLEPeripheral workspace. Seems like everything builds and downloads with no issues. I think I've reverse engineered the desired packet structure from the SerialInterface.c source, but I'm still not seeing any feedback from the CC2540 that the commands are being seen. I have a bus pirate acting as SPI Master and connected the the P18 debug header on my v1.8.8 SmartRF05 board, connected as follows:

MISO - Pin 12

MOSI - Pin 18

CS - Pin 14

CLK - Pin 16

GND - Pin 20

As far as I can tell from the source, cSerialPacketParser() is registered as a callback for NPI Transport when the Serial Interface task is first initialized. From here, cSerialPacketParser steps through the incoming data, looking for a) the cmd_identifier of 0x77, b) the op_code (0x1, 0x2, or 0x3), c) the cmd_len, and d) the cmd_data. For example, if I wanted to enable advertising, I would send 0x77,0x01,0x04,[duration, interval]. Or if I wanted to print something to the RF05 LCD, I would send 0x77,0x03,0x03,0x41,0x42,0x43 (I would expect this to print 'ABC' on the display). 

However, I get no reaction (not even a failure response) from the CC2540. 

Additionally, I have no idea how the actual SPI parsing code ever gets invoked. spiParseRx() is what parses the incoming data against the desired SPI packet format: 0xFE (Start of Frame), (Data Length), (data), (frame-sequence-check). This code is called in the chain from HalUARTPoll, but I couldn't find any place inside the source that that function gets invoked!

So I have no idea if my cSerialPacketParser byte arrays need to be the data portion of a normal SPI packet or not, and I have no idea where along the lines my SPI communication is failing. 

Has anyone else used the SerialInterface patch with SPI? 

  • Hello. If you are trying to use the standard HCI interface, you shouldn't use the serial interface example. This example is for a custom interface. You should use the HostTestApp project, SPI configuration, that is included with the installer.
  • Thanks Tim.

    I actually started with the HostTestApp and used hand-assembled HCI commands along with the SPI packet format. I could see the data arrive at the part by using a bus pirate (master in this case is an external uC), but I never got any validation from the part that the command was accepted, and no indication if the command was correct.

    That's why I started with the SerialInterface stuff, in an attempt to verify that the chip is happily receiving the data I send down. I unfortunately can't tell that it is in either of my attempts.
  • If you're not getting anything back, then your packet format / handshaking must be incorrect. You can try setting breakpoints in the _hal_uart_spi.c driver to debug. It would also help if you posted a logic capture of the SPI lines.
  • Thanks Tim,

    Yesterday I managed to get all the preprocessor defines correct and had my project successfully breakpoint-ing at spiParseRx(), so I can watch bytes come across one at a time and see the <SOF><LEN><DATA><FCS> packet get parsed correctly.

    The project I'm using is a special controller-only build (host is external, controller is the only thing implemented on CC2540), and the callback after parsing the SPI data is hciSerialPacketParser. However, since I believe that callback is compiled into the stack somewhere, I can't see what the Parser is expecting in terms of HCI command structure.

    For example, to enable advertising, I send the following over SPI:

    0xFE - SPI Start of Frame
    0x05 - Total SPI Data Length
    0x01 - HCI UART Indicator
    0x0A, 0x20 - Opcode for Set Enable Advertising
    0x01 - Length of Parameter
    0x01 - Parameter (Enable Advertising)
    0x2E - SPI Frame Check Sequence

    Starting from index 0, bytes 2 - 6 all get submitted to hciSerialPacketParser, but the chip doesn't appear to start broadcasting. I've tried other commands (setting the advertising data, setting the advertising parameters), but get no physical response.
  • The packet format of HCI commands is documented in the HCI Vendor Specific API guide included with the stack.

    Note that, if you are using a special controller-only build, many of these commands will not be valid as they require the host (i.e. the standard HostTestApp network processor project). You'll need to check the BLE spec for the controller-only commands. Where did you get this build from? Did we provide it to you?

    One thing that may help you is to prototype with HCI Tester: processors.wiki.ti.com/.../LPRF_BLE_HCITester. This is a GUI which can send controller-only HCI commands. I will need to provide you with the .xml for this if you want to use it. Also, since this runs on a PC you would need to use a UART-to-SPI bridge to use SPI. The bridge is available here: processors.wiki.ti.com/.../Cc2640_Adding_a_UART_or_SPI_driver_to_a_Sample_Project
  • Hey Tim,

    Yes, this is a build provided from TI. In the BLE Spec, section 7.8 lists all of the LE Controller Commands. The ones we used to turn on advertising over UART (using this same build) are Set_Advertising_Data, Set_Advertising_Parameters, and Set_Advertising_Enable. We had another developer send these HCI commands down to the same build via UART and he was able to see the part broadcast.

    Now that we've switched to SPI, I'm sending the exact same data down we sent over UART, only this time it's wrapped in the SPI packet format as shown in the second link you provided in your last reply.

    I've come across the HCITester, and I think that would only provide confirmation that my HCI Commands are constructed properly. For development I'm using a bus pirate attached directly the SPI lines on the CC2540 to send down the commands, so adding a second CC2540 as a UART-to-SPI bridge is non-trivial for my current setup, although it may come to that.

    As I stated before, I'm getting the exact bytes I expect down and can inspect these in the debugger, but when we get to the callback function, nothing happens. I don't think the problem lies in the communication from SPI master to SPI slave (CC2540). The issue is either with the HCI command itself (odd, since the same commands worked over UART), or with the expected format of the command from the perspective of the parser built into the BLE 1.4 stack (which I don't have access to).

    I'll take a peek at the UART-to-SPI bridge project, perhaps that has some info about any packet changes made between the two transport types.
  • If you are sending the same bytes to the packet parser for SPI that you are for UART (and it worked for UART) then I don't think the error is in the command.

    Do you see any activity on the SRDY line?

    How are you switching between UART and SPI configurations? Did we provide you both projects? Also, what stack was this? I would not consider any SPI driver before 1.4.0 stable.
  • I'm waiting on my dev board to get yellow-wired so I can probe the SRDY line.

    As far as I can tell, there is only 1 project within the HCITestApp workspace. To enable SPI I just changed the preprocessor defines. Within hal_uart.c there are several different Init/Open functions (SPI, DMA, ISR, USB), and the one called depends on what defines are enabled. Tracing the boot sequence of the code, we are initializing, opening and polling using all SPI functions.


    The following are the preprocessor defines I'm using for the project:

    INT_HEAP_LEN=2700

    HALNODEBUG

    OSAL_CBTIMER_NUM_TASK=1

    xPOWER_SAVING

    HAL_AES_DMA=TRUE

    HAL_DMA=TRUE

    HAL_UART=TRUE

    HAL_UART_DMA=TRUE

    HAL_UART_ISR=0

    HAL_UART_SPI=1

    HAL_SPI_QUEUED_TX=TRUE

    HAL_KEY=FALSE

    HAL_LCD=FALSE

    HAL_LED=FALSE

    If I'm recalling correctly, I believe I used the HostTestRelease workspace (CC2540SPI configuration) as the basis for the preprocessor defines to get SPI working.

    This is using BLE Stack 1.4.0

  • Here are the defines for a working controller-only CC2540 SPI project that I just tested:

    xPOWER_SAVING

    xBLE_BADDR_FROM_FLASH

    HAL_FLASH=FALSE

    HAL_UART=TRUE

    HAL_UART_DMA=0

    HAL_UART_ISR=0

    HAL_UART_SPI=2

    HAL_LED=FALSE

    HAL_KEY=FALSE

    HAL_LCD=FALSE

    HAL_DMA=TRUE

    HAL_AES_DMA=TRUE

    Here is the hex. If this doesn't work for you, then something in your SPI handshaking / packet format is off:

    /cfs-file/__key/communityserver-discussions-components-files/538/cc2540_5F00_controller_5F00_SPI.hex

  • Actually I see you are using the HAL_UART_SPI = 1 configuration so you'll want to change that from my defines.

  • Awesome, thanks Tim, I'll give this a try today. Any chance you have the hex for the HAL_UART_SPI=1 configuration? Just for an apples-to-apples comparison. 

  • Also - if you tested your .hex over SPI and had it broadcasting, would you care to share the bytes you sent over the wire? I have no reason to believe mine are incorrect, but if we do the exact same thing and mine doesn't work when your's does, I may have a HW issue that needs addressing. 

  • Hey again Tim,

    I've captured 2 GIFs of me stepping through the code while reviewing incoming SPI data.

    http://imgur.com/a/ELiqr

    The "Incoming SPI Data" gif shows me send a byte sequence over SPI, and then watch the debugger as the data comes in. You can see the SOF, LEN, DATA, FCS sequence clearly, and all bytes are accounted for.

    The "hciSerialPacketParser Callback" gif shows just the first and last frame as the bytes are incoming, and then shows the callback for the parser trigger. 

    Even though all the bytes show up correctly, there is still no BLE behavior from the chip. When we run this same project on UART using the OEM CC2540 module, I can get broadcasting to work. So, at this point, I think one of the following is true:

    A) hciSerialPacketParser somehow expects something different than what I'm sending it

    B) The CC2540SPI version of the project handles interfacing with the stack differently than the UART version

    C) We have something wrong with our HW, such that the chip can receive the data perfectly, but somehow doesn't broadcast (not sure if this is even possible, but I'll look into it). 

    I'm running HostTestRelease (straight from the 1.4 stack), CC2540SPI project.

    I tried using your defines and got linking errors. One of them had to do with the OSAL_CBTIMER, and after adding that in, I got some other linking error. So I'm using my original preprocessor setup, replicated below:

    INT_HEAP_LEN=2700

    HALNODEBUG

    OSAL_CBTIMER_NUM_TASK=1

    xPOWER_SAVING

    HAL_AES_DMA=TRUE

    HAL_DMA=TRUE

    HAL_UART=TRUE

    HAL_UART_DMA=TRUE

    HAL_UART_ISR=0

    HAL_UART_SPI=1

    HAL_SPI_QUEUED_TX=TRUE

    HAL_KEY=FALSE

    HAL_LCD=FALSE

    HAL_LED=FALSE

  • And for the sake of testing, I am using the CC2540EM module we have, configured for SPI, using the same SPI master and the same commands by interfacing the P18/P20 EM debug connectors.

    I can watch the traffic get to the part in the same way as I did above, but still no reaction.
    All else equal, I can load up the UART version of this and send over non-packetized bytes (just the raw HCI commands), and it starts advertising fine.
  • Wait. You're running host test release? From the beginning of the thread you said you were using the controller-only project?
  • I've only been playing with HostTestRelease recently, after I realized I could get a sign-of-life out of the part using UART. Up until that point I had been using the controller-only release you guys provided (HCITestApp). Sorry for the confusion, I'm bouncing back and forth between them trying to document what does and doesn't work under each project.
  • So which hex file do you want? I can provide working hex files with SPI logic captures for HCITest or HostTestApp. Or do you just want both?
  • Let's do both, gives me more to test :)
  • Ok hopefully this should pinpoint the problem : /cfs-file/__key/communityserver-discussions-components-files/538/SPI-stuff.zip

    This includes for CC2540 1.4.0 SPI HostTestApp and HCITestApp:

    - logic captures (open with salae: https://www.saleae.com/downloads)

    - HCITesterScripts used to perform test

    - HCITester logs of test

    - hex files used

    I verified that the device was advertising in both cases. Note that you may see the HCI commands/ events split into multiple SPI packets on the logic capture because I was using a UART-to-SPI bridge which polls.

  • Hey Tim,

    Thanks for the zip, lots of helpful information in there. I've gone through the script, log and SPI capture for the HCITestApp (Controller-Only) build and had a couple questions:

    1) I notice repeated occurrences of [0xFE, 0x01, 0x01, 0x00] in the SPI capture, but not in the script/log. I'm guessing this is some kind of "wake-up" byte? Additionally, there is one occurrence of [0xFE, 0x01, 0x00, 0x01] - not sure if there's any meaning to the 0x00 vs 0x01...

    2) In the Set Advertising Params command, the script and the log both indicate the following last two bytes of the sequence - 0x07, 0x00. However, in the SPI capture, with the packet split up, the last two bytes come across as 0x07, 0x05. That last octet is the "Advertising Filter Policy", where 0x05 is currently "Reserved for Future Use". Something to be worried about? 

    I'll load up the .hex's next and test them out. Just checking - these were compiled with HAL_UART_SPI=1? I guess I'll find out soon enough. 

  • Oops, jumped the fun on question #1, looks like the [0xFE, 0x01, 0x01, 0x00] transaction is used to kick off a "read" and the 0x00 transaction was actually the last byte of a transaction that was chunked into two. 

  • Hey Tim - 

    Made some good progress Friday and this weekend. I'm compiling and loading the HCITestApp source and am getting responses back from the chip over SPI. Still no broadcast, but I like this progress. Here's a snippet of my SPI Capture. The format may look confusing, but it is showing activity on MOSI and MISO. Brackets ('[ and ]') represent packet start and end. Parenthesis '()' represent MISO packets coming from the CC2540. In comparing my capture with yours, I only see 2 differences. 

    1) I have an extra byte at the end of my CC2540 response packets, but it's almost just noise since it isn't included in the length of the SPI packet...

    2) I do not get a response after sending down Set Advertising Enable. 

    Otherwise - our commands and responses match perfectly. 

    Read Command (MOSI) - [0xFE,0x01,0x01,0x00]
    HCI Reset Command (MOSI) - [0xFE,0x03,0x03,0x0C,0x00,0x0C]
    Read (MOSI) with HCI Reset Response (MISO) - [0xFE(0x00)0x01(0xFE)0x01(0x07)0x00(0x04)0x00(0x0E)0x00(0x04)0x00(0x00)0x00(0x03)0x00(0x0C)0x00(0x00)0x00(0x06)0x00(0xF7)0x00(0x00)0x00(0x00)0x00(0x00)] - extra 0xF7
    Map PM to IO Port Command (MOSI) - [0xFE,0x05,0x12,0xFC,0x02,0x00,0x00,0xE9]
    Read (MOSI) with Map PM Response (MISO) - [0xFE(0x00)0x01(0xFE)0x01(0x08)0x00(0x04)0x00(0xFF)0x00(0x05)0x00(0x12)0x00(0x04)0x00(0x00)0x00(0x12)0x00(0xFC)0x00(0x0E)0x00(0x8F)0x00(0x00)0x00(0x00)] - extra 0x8F
    Set BADDR Command (MOSI) - [0xFE,0x09,0x0C,0xFC,0x06,0x22,0x22,0x22,0x22,0x22,0x22,0xFF]
    Read (MOSI) and BADDR Command Response (MISO) - [0xFE(0x00)0x01(0xFE)0x01(0x08)0x00(0x04)0x00(0xFF)0x00(0x05)0x00(0x0C)0x00(0x04)0x00(0x00)0x00(0x0C)0x00(0xFC)0x00(0x0E)0x00(0x8F)0x00(0x00)0x00(0x00)] - extra 0x8F
    Set Advertising Data Command (MOSI) - [0xFE,0x08,0x08,0x20,0x05,0x04,0x00,0x01,0x02,0x03,0x21]
    Read (MOSI) and Set Adv Data Response (MISO) - [0xFE(0x00)0x01(0xFE)0x01(0x07)0x00(0x04)0x00(0x0E)0x00(0x04)0x00(0x00)0x00(0x08)0x00(0x20)0x00(0x00)0x00(0x21)0x00(0x0E)0x00(0x00)0x00(0x00)0x00(0x00)] - extra 0x0E
    Set Adv Params (MOSI) - [0xFE,0x12,0x06,0x20,0x0F,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x3C]
    Read (MOSI) and Set Adv Params Response (MISO) - [0xFE(0x00)0x01(0xFE)0x01(0x07)0x00(0x04)0x00(0x0E)0x00(0x04)0x00(0x00)0x00(0x06)0x00(0x20)0x00(0x00)0x00(0x2F)0x00(0x0E)0x00(0x00)0x00(0x00)0x00(0x00)] - extra 0x0E
    Set Adv Enable (MOSI) - [0xFE,0x04,0x0A,0x20,0x01,0x01,0x2E] - No Response?


  • After poking at the issue a bit further, I got the following:

    [0xFE,0x04,0x0A,0x20,0x01,0x01,0x2E]
    [0xFE(0x00)0x01(0xFE)0x01(0x07)0x00(0x04)0x00(0x0E)0x00(0x04)0x00(0x00)0x00(0x0A)0x00(0x20)0x00(0x21)0x00(0x02)0x00(0x0E)0x00(0x00)0x00(0x00)0x00(0x00)]

    Again, ignoring the extra 0x0E byte at the end of the sniff, that response breaks down to:

    0xFE - SOF
    0x07 - SPI packet Len
    0x04 - HCI Event Protocol ID
    0x0E - HCI Command Complete
    0x04 - Parameter Len
    0x00 - # commands allowed
    0x0A - OpCode
    0x20 - Opcode
    0x21 - Error Code: Role Change Not Allowed.

    So the part is getting the command, but not enabling advertising due to some other parameter? I'll investigate how roles work within BLE....
  • OK, sorry for the flurry of responses, just trying to keep things updated as I go.

    I reworked my app and got the exact same command/response sequences using the HCITestApp that you are seeing, all the way down to a "Successful" response to the Set Advertising Enable Command. But I'm still not seeing anything broadcast using my Android phone and several different BLE apps (one of which is a BLE Device Monitor from TI). I will work with my HW team to see if there is some issue keeping it from transmitting, but in the mean time - do you have a recommended method to look for advertising devices?
  • Doesn't look like it's any HW issue for us. I can put the exact same dongle we're using into an interfacer board plugged into the SmartRF board, load up simpleBLEPeripheral, and watch the dongle start broadcasting.

    I've been trying variations of the commands, along with trying to transcribe the commands sent over during initialization of the simpleBLEPeripheral source (which is difficult due to the presence the Host-stack API). Chip is definitely responding appropriately, but I'm just not getting advertising up and running with the same conversation you posted.
  • So there is no problem using the hex I sent you with and the same SPI communication from the logs? But when you use your source code and send the same SPI commands there is an issue?

    If this is the case, then I guess I'll need to send you my HCITestApp project.
  • Hey Tim,

    I just tried using your HCITestApp .hex again (HCITestApp_Controller_CC2540.hex) and got some interesting behavior. I've changed what commands I'm sending down to match the procedure outlined in Vol 6, Part D, Section 3 of the BT Core V4 Spec. This involves the following:

    Set Advertising Parameters (my payload is 6,20,f,20,0,40,0,0,0,0,0,0,0,0,0,0,7,0)

    Read Advertising Channel TX Power (CC2540 response was 0e 05 00 07 20 00 00 - Indicating TX power of 0 dB?)

    Set Advertising Data (8,20,12,8,9,53,63,68,6d,69,64,74,2,1,1,5,12,20,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0) - this *should* set the complete name to 'Schmidt'

    Set Scan Response Data (9,20,f,8,9,53,63,68,6d,69,64,74,5,12,20,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) - again, should set complete name to 'Schmidt'

    Set Advertising Enable (a,20,1)

    With your hex, I do see the part advertising, but with the name 'SimpleBLEPeripheral'. I can use the READ BADDR command over SPI to get the mac addr and it matches the part I see broadcasting. 

    So, that's progress at least. Your HCITestApp project might highlight some differences though if you can send me that.  

    6,20,f,20,0,40,0,0,0,0,0,0,0,0,0,0,7,0

  • I just reran my script and the advertising data I see is: 00:01:02:03 which is expected.
    There is no scan response so There is no possible way for it to be displaying "SimpleBLEPeripheral." What are you using for scanning? If it is a phone, it is probably caching something that once advertised with the same address as "SimpleBLEPeripheral." I would recommend using the CC2540 dongle with BTool for scanning as phones (especially iPhones) will do very strange things. I'll try to get you my project today.
  • Hey Tim,


    Using your pre-compiled HCITestApp hex, my script for sending commands over SPI, and a separate CC2540 to act as a packet sniffer using the TI Packet Sniffer utility, I'm seeing scan response data in the packet, and the device is still showing up as SimpleBLEPeripheral on my Android phone. The MAC address shown on the sniff and on my phone match. Below are the HCI Commands I'm sending over SPI:

    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 1 - READ
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 3,c,0 - HCI Reset
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 1 - READ
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 6,20,f,20,0,40,0,0,0,0,0,0,0,0,0,0,7,0 - Set Advertising Params
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 1 - READ
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 7,20,0 - Read TX Power
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 1
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 8,20,9,8,9,53,63,68,6d,69,64,74,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - Set Advertising Data (NAME = Schmidt)
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 1 - READ
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 9,20,9,8,9,53,63,68,6d,69,64,74,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - Set Scan Response Data (NAME = Schmidt)
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 1 - READ
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b c,fc,6,22,22,22,22,22,22 - Set Addr
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 1 - READ
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b a,20,1 - Enable Advertising
    sleep 2
    spiHCITest -d /dev/spidev1.5 -s 1000000 -b 1 - READ


    Attached is the packet capture. The MAC we care about is 5C:31:3E:5B:09:15. You can see the Scan Response Data has the correct data (Schmidt). I don't see any entries in any of the packets for Advertising Data. I would have also expected the device address to have been changed to 22:22:22:22:22:22, but that command, although accepted, doesn't appear to do what I think it should do. We are definitely sending data down over SPI, and the part is definitely responding to some of that data, but it seems like not all the commands have the correct effect.

    simplebleperipheral_sniff.psd

  • The BD ADDR can not be set unless the controller is idle. I would try doing this right after HCI Reset.

    Other than that, I don't see any issues here since you are sniffing the correct advertising and scan response data. The fact that the phone is seeing it as a SimpleBLEPeripheral appears to be a phone issue.
  • Thanks Tim, moving the change address command up in my sequence got it working. I'll poke on my end with the Advertising name, changing the address made it come up as "UNKNOWN DEVICE" in my scanning app, so it looks like my phone was caching it.

    Still not sure what the difference between your pre-compiled hex and my compiled hex is. If you could share your workspace with me, that would (hopefully) let me build working code for myself.

    Michael

  • Hey Tim,

    Any chance you can share your HCITestApp project source with me? There are some changes I'd like to test and I'll need a functioning workspace for a recompile. 

  • This is not a straight forward process since we do not have a release version of this for CC2540 SPI. Who is your local FAE? I think we need to begin working through them.
  • Hello Tim,

    I follow the preprocessor settings you propose for the HostTest - CC2540SPI BUT I get the following error:Could you please help me ?

  • Hello,

    Some of the threads you are posting to are very old. In order for TI to provide the best support, can you consolidate your questions and your steps to reproduce into a single thread so that TI may support you from there. You can leave these threads active for the community to comment on, but I would recommend that you create a single new post for us to support you on. Thank you for your understanding!