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

ncs1.5.0 and nrf5340 board ,GPIOE interrupt every 4ms ECG data ready, but 30ms can read one time

I use nordic5340 SPI read ADS1298R ecg data, using nrf5340 p0.13 to connect ADS1298R data ready pin . when ADS1298R data ready pin  high to low mean ADS1298R data ready .i config GPIOE interrupt ,and in interrupt give a semophere to ecg thread to read data :

K_SEM_DEFINE(ADS129xdataRdy_sem, 0,10);
void ADS129XdataRdy(const struct device *dev, struct gpio_callback *cb,uint32_t pins)
{
   LOG_INF("dataRdy at %" PRIu32 "\n", k_cycle_get_32());
   k_sem_give(&ADS129xdataRdy_sem);
}

interrupt setting like below:

ADS129xDRDY_dev = device_get_binding("GPIO_0");
if (ADS129xDRDY_dev == NULL) {
  LOG_INF("ads129xR data ready didn't find GPIO_0\n" );
  return 1;
}
ret = gpio_pin_configure(ADS129xDRDY_dev, 13, GPIO_INPUT|GPIO_PULL_UP );
if (ret != 0) {
   LOG_INF("Error %d: failed to configure GPIO_0 13 pin \n",ret);
  return 1;
}
ret = gpio_pin_interrupt_configure(ADS129xDRDY_dev,13,GPIO_INT_EDGE_TO_INACTIVE );
if (ret != 0) {
  LOG_INF("Error %d: failed to configure interrupt on GPIO_0 13 pin \n",ret );
   return 1;
}
gpio_init_callback(&ADS129xDRDY_cb_data, ADS129XdataRdy, BIT(13));
gpio_add_callback(ADS129xDRDY_dev, &ADS129xDRDY_cb_data);

in ecg thread take the semophere and read data:

for (;;) {

  if(k_sem_take(&ADS129xdataRdy_sem, K_MSEC(5))==0 )
 {
    ADS129x_Read_Data( ) ;
   LOG_INF("read at %" PRIu32 "\n", k_cycle_get_32());
}

but every 4ms can enter interrupt,but need 30ms read a time data:

the debug log out information :always 4ms enter interupt a time ,but 30ms read data a time ,so most of ecg data are not read and  lost.

   time interval but each "dataRdy at "almost 131 ,every 32768 mean one second, so  131/32768=0.004s . but enter many time interrupt,in ecg thread take one time semophere and only read one time . "read at %" and "dataRdy at " log out not same step mean enter many times interrupt and read a few time data.

   i want every semophere from interrupt ecg thread can take  ,and ecg thread can read every interrupt data,so  ECG data will not  lost.

  I try to  place function ADS129x_Read_Data( ) directly in interrupt to improve read speed , but system reset . even make ADS129x_Read_Data( ) become interrupt cb ,,there is SPI tranceive function in ADS129x_Read_Data( ), system also reset . zephyr OS seem not can place function in interrupt .set SPI tranceive function (child function in ADS129x_Read_Data( ) )become static inline function also reset . zephyr os reset if place ADS129x_Read_Data( ) in interrupt or make ADS129x_Read_Data( ) become GPIOE interrupt cb.

   I try to use k_sem_count_get (&ADS129xdataRdy_sem) in ecg thread,  and use k_sem_take(&ADS129xdataRdy_sem) till  k_sem_count_get (&ADS129xdataRdy_sem) ==0  ,but not effect.

  try to make ecg thread priority  higher than other thread to improve read speed .but i chang ecg thread priority high ,there is no effect.

  is nrf5340 CPU slow? these project use nrf52840 can read data from every GPIOE interrupt .these project have only a few thread and not much work need CPU to deal with

 I try to delete all other work in ecg thread only one work of take GPIOE semophere and ADS129x_Read_Data( ),this time can read fast ,but alway continuous enter interrupt sereral times and give several semoheres . while continuous take semohere and ADS129x_Read_Data( ) several time . give semophere and take semophere  did not synchronize 。maybe is broken by other thread. not synchronize mean error data read . try to lock thread switch in interrupt and unlock thread switch after read data in loop of ecg thread .but system reset.

why a little code or function placed in a k_timer cb(2ms period) interrupt or placed in GPIOE interrupt   can lead zephyr os reset? zephyr os reset in below shortcut imagine happen is i place function 

ADS129x_Read_Data( )  in void timer_readInterruptHandler(struct k_timer *timer_id) 

  • It's a little hard to know exactly what's causing this without being able debug your application and without having access to the ADS129 sensor. I assume there are some other threads running in the background causing the delay. The thread aware debugging feature that comes with Ozone may help you figure out the cause: Thread aware debugging with nRF Connect SDK

    I created a simple sample where I triggered a timer every 4ms and woke up a custom thread using a semaphore. I then toggled a GPIO (as well as using LOG_INF()) in the custom thread to see if ran every 4ms, and it did indeed:

    Can you test out the same sample in NCS v1.6.0 using nrf5340dk_nrf5340_cpuapp? First with the timer, and then you swap it out the timer with the sensor interrupt.

    semaphore_timing.zip

    Is there a reason you're logging all the data? Logging every 4ms corresponds to 250 logs each second. By the way, I don't think it should affect the timing since it has a very low priority.

Related