This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to use DMA in NRF52 while writing on SD card, while BLE is also operating?

Hi,

In my application of interfacing SD card with nrf52, I am using SAADC to sample the input signal at 1000 samples per seconds. These samples I am combining in 84 packets each consisting 12 samples and 20 bytes. In one second I am sending 84 packets over BLE to remote tablet device.

So, I want to write these packets in SD card. Writing one packet at a time is not a good practice. So I want to write 40 packets at a time in SD card. For this I need DMA. As I am never used DMA before, I want to understand what is the correct steps to use DMA for my application.

Does any one has any idea about this?

SDC+BLE.c

Parents
  • FATFS port present in SDK 12 is using the asynchronous SD card driver (which uses SPI master driver in EasyDMA mode on nRF52). Unfortunately FATFS API is synchronous, so if it's not modiffied and used without preemptive OS, CPU has to wait for SD card operations to complete on every synchronous API call. However, when there is a serial data transfer in the background (card read/write operation), higher priority interrupts should not affect SD communication (except the possible delay), as far as SPI driver interrupts are being handled.

    I'd suggest the following scenario:

    • allocate 2 buffers,
    • set current buffer to #1,
    • start ADC sampling (N=12 samples appended into the current buffer)
    • send the samples over BLE and trigger the next sampling,
    • if current buffer is ful then switch current buffer to #2, start the ADC sampling into #2 and trigger the write of #1 into SD; while writing the data, you can still send the packets over BLE and trigger ADC sampling in interrupts
    • ...and so on...

    Note that the worst case scenario for SD write operation (according to SD specifications) is 250 or 500ms, depending on card type.

  • I'll start from #3: 3) SD card library uses SPI in DMA mode if SPIn_USE_EASY_DMA is enabled in sdk_config.h (where n is the SPI instance number used by app_sdcard, defined by APP_SDCARD_SPI_INSTANCE; by default (in fatfs example): instance 0, dma enabled).

    1. Call FATFS API functions from the main context (not an interrupt handler) and BLE functions from interrupts (which will preempt the fatfs call). BLE communication is time sensitive, so it's a good idea to keep the SPI priority lower than the priority from which wireless transmission is triggered (eg. SAADC, timer). By default SPI priority is set to lowest (SPI_DEFAULT_CONFIG_IRQ_PRIORITY (sdk_config.h) equal to APP_IRQ_PRIORITY_LOWEST (app_util_platform.h) = 7 on nRF52/Cortex M4).

    I'd also recomment using app_scheduler. If you will be able to implement ADC sampling / BLE transmission in interrupt driven way then all you need to do is schedule the SD write in one of the interrupts (then it will be executed from main cotext) and make sure that there is enough time to write the data on SD (in the worst case scenario) between filling the buffers.

    1. Take a look at nrf_drv_saadc_buffer_convert(). It takes a pointer to the buffer and buffer size as an argument. My concept is something like this: uint16_t buf[2][12N]; call _convert() with: &buf[0][0], size 12; then [0][12], then [0][24], [0][36], and so on until it's filled. When it's full (last conversion to buf[0][] finished) call _convert with( &buf[1][0]. trigger SD write of buffer 0, then convert to [1][12]. [1][24]... nrf_drv_saadc_buffer_convert() will result in interrupt and calling the handler, so you can trigger the next sampling / wireless data transmission there.
Reply
  • I'll start from #3: 3) SD card library uses SPI in DMA mode if SPIn_USE_EASY_DMA is enabled in sdk_config.h (where n is the SPI instance number used by app_sdcard, defined by APP_SDCARD_SPI_INSTANCE; by default (in fatfs example): instance 0, dma enabled).

    1. Call FATFS API functions from the main context (not an interrupt handler) and BLE functions from interrupts (which will preempt the fatfs call). BLE communication is time sensitive, so it's a good idea to keep the SPI priority lower than the priority from which wireless transmission is triggered (eg. SAADC, timer). By default SPI priority is set to lowest (SPI_DEFAULT_CONFIG_IRQ_PRIORITY (sdk_config.h) equal to APP_IRQ_PRIORITY_LOWEST (app_util_platform.h) = 7 on nRF52/Cortex M4).

    I'd also recomment using app_scheduler. If you will be able to implement ADC sampling / BLE transmission in interrupt driven way then all you need to do is schedule the SD write in one of the interrupts (then it will be executed from main cotext) and make sure that there is enough time to write the data on SD (in the worst case scenario) between filling the buffers.

    1. Take a look at nrf_drv_saadc_buffer_convert(). It takes a pointer to the buffer and buffer size as an argument. My concept is something like this: uint16_t buf[2][12N]; call _convert() with: &buf[0][0], size 12; then [0][12], then [0][24], [0][36], and so on until it's filled. When it's full (last conversion to buf[0][] finished) call _convert with( &buf[1][0]. trigger SD write of buffer 0, then convert to [1][12]. [1][24]... nrf_drv_saadc_buffer_convert() will result in interrupt and calling the handler, so you can trigger the next sampling / wireless data transmission there.
Children
No Data
Related