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 !


 

Parents
  • Hi, sorry for the late response. Vacation time.. What if you do it like this:

    • Initialize SPI
    • Do the SPI write sequence
    • De-initialize SPI
    • Set up GPIOTE on the MISO line and trigger on falling edge.

    Then in the GPIOTE event handler:

    • Initialize SPI again
    • Do the SPI read sequence

    This will also be a more power efficient solution as the CPU is running in a while loop, and is not blocking other things from running.

Reply
  • Hi, sorry for the late response. Vacation time.. What if you do it like this:

    • Initialize SPI
    • Do the SPI write sequence
    • De-initialize SPI
    • Set up GPIOTE on the MISO line and trigger on falling edge.

    Then in the GPIOTE event handler:

    • Initialize SPI again
    • Do the SPI read sequence

    This will also be a more power efficient solution as the CPU is running in a while loop, and is not blocking other things from running.

Children
  • thanks for your answer.
    I can do this but I must split my function at least into 2 parts. I don't like it.
    look this is want to be able to do:

    void my_lovely_function()
    {
      uint32_t summer_temperature[6];
      uint8_t i;
      what_a_nice_day();
      I_love_summer();
      let_s_enable_temperature_sensors();
      let_s_wait_a_delay_to_stabilise_them();
      for(i=0;i<6;i++)
        summer_temperature[i]=check_ext_adc(i);
      switch_temperature_sensor_down();
      if(do_I want_to_send_this_temperature_by_bluetooth(summer_temperature))
        send_bt_data(summer_temperature);
      this_was_my_pleasure_to_deal_with_you();
      thanks_for_reading_all_this();
      return;
    }

    If I split "check_ext_adc", I still must wait for its result, which will still break the scheduler.
    I can make some ugly stuffs, but I love code that I can understand without comment and 
    chart.
    What's the max time lengh of a function and why? How can I say in a function, "let's pause and wait quietly for something (time, event, whatever)"? what's the min time I should free the scheduler for it to be happy? (bluetooth connected).
    Kind regards,

  • If you want to wait quietly for something, the way to do it is to exit the function, return to idle, and wait for an interrupt. This interrupt could be the GPIOTE telling you SPI driver that data is ready, or an app_timer continuously polling the SPI lines. Blocking the main thread waiting in a for loop is generally not a good idea, so why it asserts is hard to say, it would require some debugging to know exactly why it fails.

    If these sensor readings are something you do continuously, I would suggest to use the app_timer to trigger the reading instead of the scheduler. Also if the time it takes for the MISO line to go low after the command has been issued is somewhat deterministic (i.e. you can say that it is always less than 12ms) maybe it's better to hard code the waiting time using the app_timer and initiate a read sequence in the app_timer timeout interrupt.

  • Hi,
    The function is called by a app_timer (from app_timer_create), depending of the state of the bluetooth state machine(if connected, timer is on fast, if off, it's on slow). So the main tread, on the main loop just check the scheduler and low power the module.

        for (;;)
        {
            app_sched_execute();
            power_manage();
        }

    For now, I use the timeout of the timer as interrupt, but the reading rate is just ok (5ms/measure so 33Hz).
    On every scheduler I ever met, there was a function "delay" and "wait_for_event", and even on linux, there is mutexs, and and non-crashing "sleep" function for threads. That's all what I want :
    -Or a way to create and wait for an event
    -Or a way to wait for some specific time, but without limit but max value of an integer.
    -Or both
    And if they don't exist:
    -whats the limit of time, for a function called on a timer, without any hulk risk, and why, and how to change it, if it's possible?

Related