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

AD7794 long delay

Hi,

I'm trying to write a quick driver for the AD7794 on nrf51822. This works on a special SPI: the MISO line is alse the "data ready" line.
So when I want to read a value, I need first to ask to read the right channel, then to wait for a value, and at last to read value itself. This is not so easy with the spi_master library, but I dealed with it... out of the softdevice section.

this it my function:

int read_data(int address)
{
    uint8_t resp[5]={1,2,3,4,5};
    uint8_t config_data[2]={0b01001010,0x90};
    uint8_t mode_data[2]={0x30,0x11};
    uint32_t value;
    config_data[1]+=address;
    

    //configure the reading
    printf("read\r\n");
    spi_write(BSP_SPI_CS,0b10,config_data,2);

    //use manual slave select, and set it low
    nrf_gpio_pin_clear(BSP_SPI_CS);
    nrf_gpio_cfg_output(BSP_SPI_CS);
    nrf_gpio_pin_clear(BSP_SPI_CS);

    //configure the channel, and ast for single read
    spi_write(-1,0b1,mode_data,2);


    //set the MOSI line up
    nrf_gpio_pin_set(BSP_SPI_SDI);
    nrf_gpio_cfg_output(BSP_SPI_SDI);
    nrf_gpio_pin_set(BSP_SPI_SDI);

    //set the MISO line as input
    nrf_gpio_cfg_input(BSP_SPI_SD0, NRF_GPIO_PIN_NOPULL  );
    //wait fot the line to be down (! ! ! )
    while(nrf_gpio_pin_read(BSP_SPI_SD0)!=0);
    //MISO and MOSI back to norma
    nrf_gpio_cfg_default (BSP_SPI_SD0);
    nrf_gpio_cfg_default (BSP_SPI_SDI);

    //read the value
    spi_read(-1,0b11,resp,3);
    value=(uint32_t)(((uint32_t)resp[1]<<16)+((uint32_t)resp[2]<<8)+(uint32_t)resp[3]);
    //set the CS back to high
    nrf_gpio_pin_set(BSP_SPI_CS);
    return value;
}

this is what it looks like:

The problem is when I'm using the softdevice, I'm locked into the "while GPIO not 0" loop. The MISO line still works fine and go down (but so not read correctly by the app). Afer few mode ms, the MISO line get crazy, and afer a long while (1 or 2 sec), the chip reboot.

I tried many things such as add delay in the loop, add app_sched_execute() in it as I thought it might get bored waiting(stupid, I know), etc... but I don't find a solution, even a bad one.

Does someone has any idea? thanks a lot !


 

  • The scheduler is very simple, it does not provide this functionality. It's basically just for transferring execution from interrupt context to main context. You put the event handler in a queue in the ISR, and you execute the handler in main context. That's all. FreeRTOS, linux etc which you mentioned earlier are OS's. If you want similar functionality you can use freeRTOS on the nRF chip, but I think this is a bit too much just for an SPI driver.

    A clean and nice solution is to use flag in the GPIOTE interrupt handler and wait for it in the SPI function. Did you try the following?

    bool data_ready = 0;
    
    void gpiote_interrupt(){
        //got a MISO falling edge interrupt
        data_ready = 1;
    }
    
    void SPI_read_sensor(){
        spi_send_command();
        deinit_spi(); // SPI lines cannot be configured while SPI is enabled
        configure_gpiote_interrupt_on_MISO();
        while(!data_ready){
            __WFE(); //wait for event. CPU sleeps until event
        }
        data_ready = 0;
        deinit_gpiote();
        init_spi();
        spi_read_data();
    }

    Note that you cannot reconfigure the GPIO pins while SPI is enabled.

    Another thing you should be careful with is whether or not the spi_read/write calls are blocking. For example: If the "spi_read_data()" call above is non-blocking, the function will return instantly and the scheduler might continue execute the next function in the queue before the SPI data has actually been read. Or similarly, if the "spi_read_command()" call is non-blocking it will enter the waiting loop before the spi read command is sent.

  • Thank you Stian,

    I'm actually  in vacation. My turn ;)
    I'll try this WFE() function within a month.

    But atbout OS and scheduler, not every OS has a scheduler, and a scheduler might not be an OS. This is because there is no precise definition of OS. An OS a is just a toolset that can handle hardware. . So saying that the softdevice, which is an OS in my opinion, is not an OS, is not an excuse of providing a nice scheduler or a less good one.
    I'm happy to know that the scheduler cannot do what I need, the way I need, because it's a step further. I'm quite scared to use both softdevice which has a scheduler used by bluetooth runtime, and an other scheduler, as they need "to share" interupts from a timer, and they might interract.  I'll check if it's possible, when I'll come back.
    Thanks for your answer.

Related