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

Whether the SPI using Easydma will occupy the CPU when transfer data?

Hello everyone 

       I have an question when I used the 52832.

       First of all,I configed "nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL);"  and the file (nrf_drv_spi.h) described the information as follow:

/**
* @param handler Event handler provided by the user. If NULL, transfers will be performed in blocking mode.
*/
       Note:spi_event_handler is not NULL.So the function should be Non-blocking mode

       Now I want to use the SPI +Easydma to achieve the non_Block mode ,Start the SPI and EasyDMA,the code needs to free the CPU(52832),

       My code have two functopns.Fuction one is that a sensor will generate an interrupt every 1ms.and I must use the 'nrf_drv_spi_transfer' to communicate to the sensor until the flag spi_xfer_done is True. and The other Function is  that the 52832 used SPIS which had enabled the EasyDma to transfer 240 Bytes Data to MOSI pin anytime. The SPIS clock is 2M.The time tansfers the 240 Bytes is :(240*8*0.5)us=960us.

       As description above ,CPU just need start the SPI ,it will not speed the time we calculated.But we found Two functions have mutual influence.

       In my understanding,the time that started the SPI using EasyDma is just taking a few 'us'.The EasyDma will do the remaining work. But actually it seems to have failed. The effection is the interrupt missed sometimes when start the second Fuction.

       What I want to know is that : when I use ‘while (!spi_xfer_done) __WFE();’,will the CPU Free?  IF the SPI with EasyDma is non-block mode,the core can achieve the two fuction .

        I can confirm that the dma is working.Beacause the clock is continuously。

        At the same time I want to know _WFE().It allows the cpu to enter the sleep mode, dose it mean that the cpu can do other works before spi_xfer_done=True? 

Parents
  • Hi Zhang,

         Now I want to use the SPI +Easydma to achieve the non_Block mode ,Start the SPI and EasyDMA,the code needs to free the CPU(52832),

    The MCU is only needed to configure the SPI and the EasyDMA RX and TX PTR register, then trigger the transaction. The actual transfer done by EasyDMA after the task start is triggered done not involve the MCU.

     

       In my understanding,the time that started the SPI using EasyDma is just taking a few 'us'.The EasyDma will do the remaining work. But actually it seems to have failed. The effection is the interrupt missed sometimes when start the second Fuction.

     We have tested the SPI and EasyDMA a lot and this is being used in many products already. So I am guessing that this most likely is not a hardware issue but something in the usage of the API.

     

    What I want to know is that : when I use ‘while (!spi_xfer_done) __WFE();’,will the CPU Free?  IF the SPI with EasyDma is non-block mode,the core can achieve the two fuction .

     We normally recommend ‘while (!spi_xfer_done) { __SEV(); __WFE();  __WFE();}’. Yes that should make the MCU go to sleep and will wakeit up when any other interrupt needs servicing. But since this is a while loop, it will go back to sleep until the spi_xfer_done is set to true. If you are using BLE and the softdevice, i would recommend you to use sd_app_evt_wait instead of the __WFE

  • Thanks a lot,Susheel. 

    the simple code I test is in below::

    /**code**/

    int main(void){

    ……

    ……

    while{

    while(DRDY_READY){

    0:APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, 5, m_rx_buf, 5));

    1:nrf_gpio_pin_clear(18);
    2:while (!spi_xfer_done)
    3:{
    4:NRF_LOG_INFO("spi_xfer_done ¡­¡­");
    5:__WFE();
    6:}
    7:nrf_gpio_pin_set(18);

     8:memcpy(m_rx_buf,Quene_buf,5);

         }

       }

    Sometimes I need a few code below the Statement 7“nrf_gpio_pin_set(18)“ as like statement 8. I think my application is not suitable for using the while (!spi_xfer_done).Because external GPIO will Trigger an interrupt every 1ms(DRDY becomes true) and then I need to use the statement 0. If i am right,I can move the statement 8 to spi_event_handle and remove the while(!spi_xfer_done).Therefore the MCU is more efficient.

Reply
  • Thanks a lot,Susheel. 

    the simple code I test is in below::

    /**code**/

    int main(void){

    ……

    ……

    while{

    while(DRDY_READY){

    0:APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, 5, m_rx_buf, 5));

    1:nrf_gpio_pin_clear(18);
    2:while (!spi_xfer_done)
    3:{
    4:NRF_LOG_INFO("spi_xfer_done ¡­¡­");
    5:__WFE();
    6:}
    7:nrf_gpio_pin_set(18);

     8:memcpy(m_rx_buf,Quene_buf,5);

         }

       }

    Sometimes I need a few code below the Statement 7“nrf_gpio_pin_set(18)“ as like statement 8. I think my application is not suitable for using the while (!spi_xfer_done).Because external GPIO will Trigger an interrupt every 1ms(DRDY becomes true) and then I need to use the statement 0. If i am right,I can move the statement 8 to spi_event_handle and remove the while(!spi_xfer_done).Therefore the MCU is more efficient.

Children
  • zhanglt3420 said:
    If i am right,I can move the statement 8 to spi_event_handle and remove the while(!spi_xfer_done).Therefore the MCU is more efficient.

    You need to WFE under a loop which is not relysolely on DRDY_READY. So I think what you have is good enough. Try this code

     

    /**code**/
    
    int main(void){
    
    ……
    
    ……
    
    while{
    
            if(DRDY_READ && spi_xfer_done){
                 DRDY_READ = false;
                 spi_xfer_done = false;
                 APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, 5, m_rx_buf, 5));
                 memcpy(m_rx_buf,Quene_buf,5);
    
           }
           else{
                nrf_gpio_pin_clear(18);
               __SEV();
               __WFE();
               __WFE();
               nrf_gpio_pin_set(18);
           }
    
        }
    }

  • After reading the code you gave,somewhere is in doubt.After using the nrf_drv_spi_transfer(),you call the  ’memcpy(m_rx_buf,Quene_buf,5)‘ immediately.The value in the buffer ‘m_rx_bufer‘ maybe invalid.Because the MISO pin maybe no signal at the same time.

    the code in the else{……} is clearly.it can let the mcu enter the sleep mode and reduce the Power consumption.Am I right?

  • I am not sure of when to update the m_rx_buf and m_tx_buf. That logic you can decide on yourself. It is not clear to me about when to use it. In your original code why you do a memcpy into m_rx_buf and not m_tx_buf is something i do not know.

    But based on your thoughts it sounds like the code in line number 15 (memcpy) should be before the nrf_drv_spi_transfer.

Related