title: Unknown BlueNRG SPI response
body: <p>I'm trying to communicate with BlueNRG chip (on <a href="http://www.st.com/web/catalog/tools/FM116/SC1075/PF260517" rel="nofollow">X-NUCLEO-IDB04A1</a> extension board) connected to STM32L1 (on <a href="http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260002" rel="nofollow">NUCLEO-L152RE</a> board) over SPI protocol.</p>
  
  <p>According to BlueNRG <a href="http://www.st.com/st-web-ui/static/active/en/resource/technical/document/user_manual/DM00114498.pdf" rel="nofollow">manual</a>, I can send an empty SPI packet of 5 bytes: <code>(0x0B, 0, 0, 0, 0)</code> to get the read/write buffer sizes as well as the device status. The status is supposed to be <code>0x02</code> (ready), or <code>0x00</code> or <code>0xFF</code> if the device was sleeping and is waking up.</p>
  
  <p>Here is the communication I'm getting:</p>
  
  <pre><code>Send (0x0B, 0, 0, 0, 0)
  Receive (0x00, 0x00)    // why 2 bytes?
  Send (0x0B, 0, 0, 0, 0) // assuming device is waking up, re-trying
  Receive (0x06, 0x00)    // what is code 6?
  </code></pre>
  
  <p>My test app is written in Rust using <a href="https://github.com/hackndev/zinc" rel="nofollow">Zinc</a>. The MCU is running the default clock (2048 MHz from MSI). Here is the code responsible for SPI initialization:</p>
  
  <pre><code>// PB.3 = CLCK
  let _spi_clock = pin::Pin::new(pin::PortB, 3,
    pin::AltFunction(pin::AfSpi1_Spi2, pin::OutPushPull, pin::Medium),
    pin::PullDown);
  
  // PA.6 = MISO
  let _spi_in = pin::Pin::new(pin::PortA, 6,
    pin::AltFunction(pin::AfSpi1_Spi2, pin::OutPushPull, pin::Medium),
    pin::PullNone);
  
  // PA.7 = MOSI
  let _spi_out = pin::Pin::new(pin::PortA, 7,
    pin::AltFunction(pin::AfSpi1_Spi2, pin::OutPushPull, pin::Medium),
    pin::PullNone);
  
  // PA.1 = CS
  let spi_csn = pin::Pin::new(pin::PortA, 1,
    pin::GpioOut(pin::OutPushPull, pin::Medium),
    pin::PullUp);
  spi_csn.set_high();
  
  let spi = spi::Spi::new(spi::Spi1, spi::DirFullDuplex, spi::RoleMaster,
    spi::Data8b, spi::DataMsbFirst, 1); // baud pre-scaler = 2
  
  let bnrg_reset = pin::Pin::new(pin::PortA, 8,
    pin::GpioOut(pin::OutPushPull, pin::VeryLow),
    pin::PullUp);
  
  bnrg_reset.set_low();
  // do something
  bnrg_reset.set_high();
  </code></pre>
  
  <p>SPI internals are slightly modified from <a href="https://github.com/hackndev/zinc/blob/master/src/zinc/hal/stm32l1/spi.rs" rel="nofollow">zinc master</a>. The send/receive code is organized as follows:</p>
  
  <pre><code>loop {
    spi_csn.set_low();
    // send a dummy read request
    spi.write(SpiRead as u8); // = 0x0B
    spi.write(0);
    spi.write(0);
    spi.write(0);
    spi.write(0);
  
    let status = spi.read();
    // debug print status
    while spi.has_more_data() {
      let data = spi.read();
      // debug print data
    }
  
    spi_csn.set_high();
  }
  </code></pre>
  
  <p>The question is - <em>how to explain or treat these BlueNRG responses</em>? I wasn't able to find any formal description of the low-level protocol it uses (not talking about HCI/ACI here, but about the status codes other than <code>0x02</code> = ready). It is very possible that I'm just initializing the hardware incorrectly, or even missing something obvious here. Would appreciate any guidance.</p>