nrf5340 is unable to trigger rpmsg(ipc) transfer

Hi,

I have quite demanding SPI device which should send its data over BLE.
Thanks to throughput example i was able to achieve maximum transfer speeds for synthetic tests (without SPI).
Sadly after adding real data input, I noticed that no transfer is executed until I finish my commands. 

Thanks to SystemView I was able to narrow this problem to one part of configuration -> rpmsg.

flow

Colors:

Green -> spi thread
Yellow -> bt_hci thread
Orange -> ble host TX
Red (small squere in top) - IRQ 58 from probably ipc, but i wasnt able to find it in manual (not listed)
Blue - probably openAmp mailing work queue thread
purple - systemwork queue

SystemView Data Log
4010.BleProblem.dat

Here is repo with configs etc.
https://github.com/DuMaM/bitly_nrf5x

Parents Reply Children
  • Perhaps I was a bit short, but I suspect that you expect to be able to create some sort of stream to send one byte at the time. That is not the case, according to the Bluetooth specification. You need to construct complete packets, and send them to the receiving device.

    BR,
    Edvin

  •   Thanks for response, and sorry to not be clear enough. 

    This is what i'm doing here:
    -> I have ads129x communication over SPI. It's set to work in continuous mode, so every n seconds it sends data packet (24bytes). To notify that we should get them it pulls up DATA_READY pin. I detect this in ISR callback and via semaphore i'm notifying SPI thread to read data. (GREEN part in picture)
    -> after SPI read this it send that data via pipe to other thread which is packing up data for BLE transfer, every time i get 251 bytes in this thread I'm sending this with `bt_gatt_write_without_response`. (YELLOW part in picture)

    The question is:
    why it takes so long rpmsg to start transmit data and why there are so big delays between each frame. (BLUE part in picture)

  • A Bluetooth Low Energy device can only communicate with the connected device every connection interval.

    In fact, it is a bit more complicated than that. A BLE connection has something called a connection interval. Every connection interval there is a connection event. This event is not initializing a connection, but the connection event is the event that occurs every connection interval, where the two devices are able to communicate.

    In the start of a connection event, the devices can start sending messages. When both devices are done, and don't have any more data, they will turn off their radios and go to sleep (hence Bluetooth Low Power). So even if you wanted to send data immediately after that, the receiving device would not have the radio turned on, and it wouldn't hear it. Therefore they must wait up to one connection intrval, until the next connection event occurs before they can send any more data. 

    Best regards,

    Edvin

  • It makes sense to me but this happens also for longer data transfers. I can accept some delay while i start communication, but for me it looks like there is some interference between components.

    For example If I would like to sent 3MB. Instead of stable stream of data, it looks like my app is buffering them in HCI driver and then after some time, it starts to send them in every connection event (like in picture). To set some reference, time spent on buffering is 30-100ms, and when transfer starts time between each frame is around 3-10ms.

    At the end my throughput is around 60kbps.

    My connection interval is set to 28units now. 
    https://github.com/DuMaM/bitly_nrf5x/blob/496ad8dfe21107d0d8ec1a2fd75c939aa89076fb/include/app/cmd.h#L11

    What makes it more interesting is that I observe such behavior only when SPI is enabled.
    For testing purposes I prepared artificial data set which I sent in exactly the same way. With this approach I'm able to get throughput around 1100kbps. 
    With exactly the same devices, with the same connection setups, and parameters, programs.
    https://github.com/DuMaM/bitly_nrf5x/blob/496ad8dfe21107d0d8ec1a2fd75c939aa89076fb/src/app/cmd_run_sim.c

    I think the issue here is that `cmd_sim` function is sending everything in one thread, by locking itself on `bt_gatt_write_without_response`. This way it dont have to switch thread context.
    Where case with SPI needs to use mutexes and ISR to switch into different thread and protect shared resources.

  •  I think it's more a problem of how communication between threads is set up.

    I checked this with Particle Xenon board and I observed exactly the same behavior.
    I also switched from pipe to ring_buffers to save copy operations. This also didn't helped.

    Here is BLE thread:
    https://github.com/DuMaM/bitly_nrf5x/blob/e6cf66e1655bf3da2c65d58fedb561893194ba80/src/app/cmd_run_adc.c

    Here is SPI thread:
    github.com/.../spi_adc.c

Related