Hi I'm trying to get the FIFO to trigger an interrupt after a certain period (s) using downsampling and the watermark interrupt. I have found that I can get the interrupt to trigger very close to what I want using a specific equation. I'm only interested in the accelerometer data, and I have configured the FIFO to send only that. The equation I have found, after reading datasheet, is this: ((odr / 2^downs) * (1 + 2*3) * delay_in_s) / 4 = watermark ODR = 100 DOWNS = 4 delay_in_s = 5 (s) => watermark = 54 This seems to work, but only if I flush the FIFO after each read, even if I toggle the interrupt off/on when it's triggered - as is recommended in the "Advanced usage guide" (https://community.bosch-sensortec.com/t5/Knowledge-base/BMI160-FIFO-Advanced-Usage/ta-p/8957). So far so good, however, when I read the available data (using https://github.com/BoschSensortec/BMI160_driver) I don't get the expected number of frames. [ 65.156567] .(3)[4101:sh][Gsensor] Set new fifo downsampling to 4. [ 65.157571] .(3)[4101:sh][Gsensor] Set new fifo watermark level to 54. [ 65.158977] .(3)[4101:sh][Gsensor] Set new trigger delay to 5s. ... [ 75.495595] .(0)[185:kworker/0:1][Gsensor] bmi160_get_fifo_data [ 75.496390] .(0)[185:kworker/0:1][Gsensor] reset_fifo_data_structure [ 75.497212] .(0)[185:kworker/0:1][Gsensor] get_fifo_byte_counter [ 75.498534] .(0)[185:kworker/0:1][Gsensor] Bytes to read = 219 [ 75.506369] .(0)[185:kworker/0:1][Gsensor] Setting up sensor data buffer... for 30 frames [ 75.508203] .(0)[185:kworker/0:1][Gsensor] \x0a AVAILABLE FIFO LENGTH : 244 [ 75.509280] .(0)[185:kworker/0:1][Gsensor] \x0a REQUESTED ACC DATA FRAMES : 30\x0a [ 75.509988] [Gsensor] \x0a AVAILABLE ACC DATA FRAMES : 0\x0a [ 75.511083] .(0)[185:kworker/0:1][Gsensor] SENSOR TIME DATA : 0 [ 75.511863] .(0)[185:kworker/0:1][Gsensor] SKIPPED FRAME COUNT : 0 Sometimes the AVAILABLE ACC DATA FRAMES is 0, sometimes it's 17. Can you help me understand why I'm not getting the full 30 expected frames? I am using the code from your Github repo to read FIFO - and my interrupt handler looks like this: static void bmi_fifo_watermark_handle(struct bmi160_acc_i2c_data *client_data) { int err = 0; u8 should_enable_fifo = 0; struct bmi160_fifo_frame *fifo = fifo_frame; /* Declare memory to store the raw FIFO buffer information */ uint8_t *fifo_buff = kzalloc(sizeof(uint8_t) * fifo_watermark_level * 4 + 25, GFP_KERNEL); /* Modify the FIFO buffer instance and link to the device instance */ struct bmi160_fifo_frame new_fifo_config; new_fifo_config.data = fifo_buff; new_fifo_config.length = fifo_watermark_level * 4 + 25; new_fifo_config.fifo_time_enable = 0x02; fifo = &new_fifo_config; wake_lock(&wl_bmi160_irq); // It's recommended by Bosch to pause interrupt during read of FIFO and later re-enable it. should_enable_fifo = BMI160_ACC_ToggleFifoWatermark(bmi160_acc_i2c_client, DISABLE); if (should_enable_fifo < 0) { GSE_ERR("Failed to disable FIFO interrupt.\n"); } /* Read data from the sensor's FIFO and store it the FIFO buffer,"fifo_buff" */ printf("\n USER REQUESTED FIFO LENGTH : %d\n", fifo->length); err = bmi160_get_fifo_data(client_data, fifo); if (err < 0) { GSE_ERR("Error getting fifo data.\n"); return; } err = bmi_check_fifo(client_data, fifo); if (err < 0) { GSE_ERR("Error detecting data.\n"); return; } // TODO: This shouldn't be needed... when reading the fifo all data that was read should be removed. Or? /* Flush FIFO */ bmi160_set_command_register(0xB0); p_bmi160->write_delay(); // Pauses 2 or 450 us, depending on current power-mode if (should_enable_fifo >= 0) { // It's recommended by Bosch to pause FIFO during interrupt read of FIFO and later re-enable it. err = BMI160_ACC_ToggleFifoWatermark(bmi160_acc_i2c_client, ENABLE); } } static int bmi_check_fifo(struct bmi160_acc_i2c_data *client_data, struct bmi160_fifo_frame *fifo) { int8_t rslt = 0; struct i2c_client *client = bmi160_acc_i2c_client; /* Declare instances of the sensor data structure to store the parsed FIFO data */ // struct bmi160_sensor_data acc_data[42]; // 300 bytes / ~7bytes per frame ~ 42 data frames struct bmi160_sensor_data *acc_data = kzalloc(sizeof(struct bmi160_sensor_data) * fifo_requested_frames, GFP_KERNEL); uint8_t acc_frames_req = fifo_requested_frames; uint8_t acc_index; int ret = 0; uint16_t index = 0; // ... unrelated code GSE_LOG("\n AVAILABLE FIFO LENGTH : %d\n", fifo->length); /* Print the raw FIFO data */ for (index = 0; index < fifo->length; index++) { // GSE_LOG("\n FIFO DATA INDEX[%d] = %d\n", index, fifo->data[index]); } /* Parse the FIFO data to extract acc data from the FIFO buffer */ GSE_LOG("\n REQUESTED ACC DATA FRAMES : %d\n ", acc_frames_req); rslt = bmi160_extract_accel(acc_data, &acc_frames_req, fifo); if (rslt == BMI160_OK) { GSE_LOG("\n AVAILABLE ACC DATA FRAMES : %d\n ", acc_frames_req); /* Print the parsed acc data from the FIFO buffer */ for (acc_index = 0; acc_index < acc_frames_req; acc_index++) { GSE_LOG("FRAME[%d] ==> x: %d, y: %d, z: %d\n", acc_index, acc_data[acc_index].x, acc_data[acc_index].y, acc_data[acc_index].z); } /* Print the special FIFO frame data like sensortime */ GSE_LOG("SENSOR TIME DATA : %d \n", fifo->sensor_time); GSE_LOG("SKIPPED FRAME COUNT : %d\n", fifo->skipped_frame_count); } else { GSE_LOG("\n Accel data extraction failed\n"); } return ret; } Other than that, the code in all of the FIFO related functions are the same as your Github, with the exception of a few log messages that are less verbose (for example printing the accelerometer data for all axis...)
... View more