Sunday, October 14, 2012

CSR's USB programmer protocol analysis

In this post I will give you some info about protocol used between BlueSuite tools and USB programmer. With this info you will be able to create partially compatible programmer or make a program which can use CSR's programmer.

If you want to learn the protocol, please read on.


Architecture


Protocol is adapted to BlueCore3-MM processor features and limitations:
  • Basic data type is unsigned 16-bit word in big endian format
  • The maximum size of request or response can be 1024 bytes.
  • Protocol uses bulk USB transfer mode.

General request and response packet structure


Request packet generaly consist of sequence of commands. First command must be predecessed with null byte, any other with 2 bytes of any value. This is a little bit confusing, but I think it has something to do with switching from 24 bit to 16 bit data mode. Remember, this device and accompanied libraries were designed with audio standards in mind. So, to be more clear, here is the basic structure:

Size in bytesField
1Null byte
2*NCommand
2Don't care
2*MCommand
......

The overall packet length should not be bigger than 1024 bytes. Also it shouldn't generate a response packet bigger than 1024 bytes.

Response packet is somewhat simpler:

Size in bytesField
2*NCommand
2*XResult
2*MCommand
2*YResult
......

In response packet there is no padding bytes. Some command don't have response at all and some can have command code increased by one, which indicates an error. If this is the case, result is the same length as if the command executed succesfuly, however, it should be ignored.

Detailed commands descriptions


There is 18 different commands:

Command codeCommand description
0x0100Read data
0x0200Write data
0x0300Set speed
0x0400Is processor stopped?
0x0500Get speed
0x0600Go to programmer's firmware update mode
0x0700Get programmer's serial number
0x0800Get firmware version
0x0900Set mode (SPI or JTAG)
0x0A00???
0x0B00???
0x0C00???
0x0D00???
0x0E00Set multiple devices (unused)
0x0F00Set additional read/write command bits
0x4000Init BCCMD protocol
0x4100Send BCCMD command
0x5000???

Read data


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x0100
11Read start address
21Number of words to read

Response format:
Offset in wordsSize in wordsField description
01Command code - 0x0100
11Read start address
21Number of words to read
3Req. numberReaded data

Comment: This is one of those commands which can fail.

Write data


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x0200
11Write start address
21Number of words to write
3Req. numberData to write

Response format:
There is no response.

Comment: None

Set speed


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x0300
11Delay value

Response format:
There is no response.

Comment: This command sets communication speed of SPI or JTAG interface, whichever is currently set. For SPI mode, 4 should represent approximately 1 MHz and 393 should represent 20 kHz, which are upper and lower limits. I found this formula in code: speed in kHz = 1000000 / (126 * value + 434). However, I didn't do any actual measurements to check correctness of the formula.

Is processor stopped?


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x0400

Response format:
Offset in wordsSize in wordsField description
01Command code - 0x0400
11Status

Comment: 1 means that processor is stopped and 0 means that processor is running.

Get speed


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x0500

Response format:
Offset in wordsSize in wordsField description
01Command code - 0x0500
11Delay value

Comment: Look at "Set speed" command for details.

Go to programmer firmware update mode


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x0600

Response format:
There is no response.

Comment: This command resets programmer and boots to bootloader, so you can update firmware on it.

Get programmer's serial number


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x0700

Response format:
Offset in wordsSize in wordsField description
01Command code - 0x0700
13Serial number

Comment: This command is used for differentiating between programmers, when there is more than one plugged in. It returns a value of PSKEY_MODULE_ID. This command can fail.

Get firmware version


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x0800

Response format:
Offset in wordsSize in wordsField description
01Command code - 0x0800
11Version

Comment: BlueSuite tools check version to see which commands are supported. Latest version is 0x119.

Set mode


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x0900
11Mode

Response format:
There is no response.

Comment: Value of 0xFFFF means JTAG, any other, usually 0, means SPI.

Set multiple devices


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x0E00
11Unused

Response format:
There is no response.

Comment: Not used, probably only for compatibility with older versions of protocol.

Set additional read/write command bits


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x0F00
11Which bits
21Value

Response format:
There is no response.

Comment: If "Which bits" is 0, read command bits will be set, write bits otherwise. For BlueCore4, these values should always be 0.

Init BCCMD protocol


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x4100
11Unknown1
21Unknown2

Response format:
There is no response.

Comment: Actually I didn't figured out meanings of these values yet. This command must be called before first BCCMD packet is sent.

Send BCCMD packet


Request format:
Offset in wordsSize in wordsField description
01Command code - 0x4100
11Size of BCCMD packet
21BCCMD packet

Response format:
Offset in wordsSize in wordsField description
01Command code - 0x4100
11Size of BCCMD packet
2?Response

Comment: I didn't figure out full format of this command yet, but it is very useful. It can be used to set PS keys, for example. Full BCCMD protocol description can be found on csrsupport.com.

If you want to see a few examples how to implement this protocol, you can take a look at csrprogrammer's source code.

5 comments:

  1. Hey Jernej,

    Great work on reverse engineering this on the PC side, and great work on finding out how to repurpose a BlueCore 3 as a CSR USB<>SPI device :)
    It's a shame finding one of those BC3 chips is pretty much impossible :(
    I've been trying to emulate the CSR SPI protocol with a TI Stellaris Launchpad, and I got it to recognize it as the CSR SPI protocol, but it doesn't actually receive any information in the bulk interface, so I'm afraid there's some initialization bits I should mimic too.
    Any chance you could attach an USB sniffer and get a log from plug-in to reading out some info ?

    On another subject, if you need any more info on the SPI protocol the CSR chips are using, feel free to take a look at my reverse engineering effort on the LPT drivers:
    https://github.com/Frans-Willem/CsrSpiDrivers

    And finally, is there any way to reach you directly so we can help eachother ?

    ReplyDelete
  2. Hi Jernej,

    Great work! Thank you very much.

    Do you know some datasheet or other source of information about this processor used by CSR? Broadcom uses ARM for theses BCM43xx, but I don't know why CSR didn't the same.

    ReplyDelete
    Replies
    1. They're using their own architecture known as XAP. Specifically, BC4 uses XAP2, but AFAIK the newest iteration is XAP5.

      I couldn't find any detailed datasheet, but you can find assembler and disassembler on the internet if that helps you somehow.

      Delete
  3. Have you saw this piece of code???
    https://github.com/lorf/csr-spi-ftdi

    ReplyDelete
  4. Project Description
    We are currently using a CSR8670 to bring in audio through the A/D converters at 24KHz. The audio is then routed through the Kalimba and then to the I2S port in. The I2S is in slave mode. We have all the source C code for the above part of the project.

    We now wish to add Blue Tooth capability to the system. The above system is hooked to a long-range radio thru the I2S bus. We want to be able to use Blue Tooth headsets instead of wired headsets.
    This means that our CSR8670 will need to be in source mode for Bluetooth applications. Also since Bluetooth only works in 8KHz or 16KHZ modes, we need to use a “sample_rate_converter”. Since most noise canceling algorithms are also based on 8KHz or 16KHz, we wish to switch to a system that is 8KHz based.
    Project:
    1. Put our CSR8670 system into source Bluetooth mode so that it will be the master which will add in other Blue Tooth headsets. The whole Bluetooth system will have to be added.
    2. Set up all sampling rates to work at 8KHz for the A/D converters and the Bluetooth Headsets.
    3. Use a “sample_rate_converter” to change the 8KHz to 24KHz sampling rate which goes to the I2S bus. The I2S has to work at 24KHz. The ADK4.3.1.5 and ADK4.3.0 has a sample_rate_converter.asm in the C:\ADK_CSR867x.WIN4.3.1.5\apps\source file area. You may have to come up with the filter coefficients for the upsampling and downsampling.
    4. Integrate this with our current C program that does volume control and side tone control.
    5. Add additional controls to switch between A/D inputs for the audio or Bluetooth.

    Can you help or know someone that can help. Thanks Dean

    ReplyDelete