/** * @brief Measure duration of signal send by sensor * * @param drv_data Pointer to the driver data structure * @param signal_val Value of signal being measured * * @return duration in usec of signal being measured, * -1 if duration exceeds DHT_SIGNAL_MAX_WAIT_DURATION */ static s8_t dht_measure_signal_duration(struct dht_data *drv_data, u32_t signal_val) { u32_t val; u32_t elapsed_cycles; u32_t max_wait_cycles = (u32_t)( (u64_t)DHT_SIGNAL_MAX_WAIT_DURATION * (u64_t)sys_clock_hw_cycles_per_sec / (u64_t)USEC_PER_SEC ); u32_t start_cycles = k_cycle_get_32(); do { gpio_pin_read(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, &val); elapsed_cycles = k_cycle_get_32() - start_cycles; if (elapsed_cycles >= max_wait_cycles) { return -1; } } while (val == signal_val); return (u64_t)elapsed_cycles * (u64_t)USEC_PER_SEC / (u64_t)sys_clock_hw_cycles_per_sec; }
void k_busy_wait(u32_t usec_to_wait) { #if defined(CONFIG_TICKLESS_KERNEL) && \ !defined(CONFIG_BUSY_WAIT_USES_ALTERNATE_CLOCK) int saved_always_on = k_enable_sys_clock_always_on(); #endif /* use 64-bit math to prevent overflow when multiplying */ u32_t cycles_to_wait = (u32_t)( (u64_t)usec_to_wait * (u64_t)sys_clock_hw_cycles_per_sec / (u64_t)USEC_PER_SEC ); u32_t start_cycles = k_cycle_get_32(); for (;;) { u32_t current_cycles = k_cycle_get_32(); /* this handles the rollover on an unsigned 32-bit value */ if ((current_cycles - start_cycles) >= cycles_to_wait) { break; } } #if defined(CONFIG_TICKLESS_KERNEL) && \ !defined(CONFIG_BUSY_WAIT_USES_ALTERNATE_CLOCK) _sys_clock_always_on = saved_always_on; #endif }
/** * * @brief Start tracking time spent with interrupts locked * * calls to lock interrupt can nest, so this routine can be called numerous * times before interrupt are unlocked * * @return N/A * */ void _int_latency_start(void) { /* when interrupts are not already locked, take time stamp */ if (!int_locked_timestamp && int_latency_bench_ready) { int_locked_timestamp = k_cycle_get_32(); int_lock_unlock_nest = 0; } int_lock_unlock_nest++; }
static int shell_cmd_cycles(int argc, char *argv[]) { ARG_UNUSED(argc); ARG_UNUSED(argv); printk("cycles: %u hw cycles\n", k_cycle_get_32()); return 0; }
void k_busy_wait(uint32_t usec_to_wait) { /* use 64-bit math to prevent overflow when multiplying */ uint32_t cycles_to_wait = (uint32_t)( (uint64_t)usec_to_wait * (uint64_t)sys_clock_hw_cycles_per_sec / (uint64_t)USEC_PER_SEC ); uint32_t start_cycles = k_cycle_get_32(); for (;;) { uint32_t current_cycles = k_cycle_get_32(); /* this handles the rollover on an unsigned 32-bit value */ if ((current_cycles - start_cycles) >= cycles_to_wait) { break; } } }
/** * * @brief Initialize interrupt latency benchmark * * @return N/A * */ void int_latency_init(void) { u32_t timeToReadTime; u32_t cacheWarming = NB_CACHE_WARMING_DRY_RUN; int_latency_bench_ready = 1; /* * measuring delay introduced by the interrupt latency benchmark few * times to ensure we get the best possible values. The overhead of * invoking the latency can changes runtime (i.e. cache hit or miss) * but an estimated overhead is used to adjust Max interrupt latency. * The overhead introduced by benchmark is composed of three values: * initial_start_delay, nesting_delay, stop_delay. */ while (cacheWarming) { /* measure how much time it takes to read time */ timeToReadTime = k_cycle_get_32(); timeToReadTime = k_cycle_get_32() - timeToReadTime; /* measure time to call intLatencyStart() and intLatencyStop * takes */ initial_start_delay = k_cycle_get_32(); _int_latency_start(); initial_start_delay = k_cycle_get_32() - initial_start_delay - timeToReadTime; nesting_delay = k_cycle_get_32(); _int_latency_start(); nesting_delay = k_cycle_get_32() - nesting_delay - timeToReadTime; stop_delay = k_cycle_get_32(); _int_latency_stop(); stop_delay = k_cycle_get_32() - stop_delay - timeToReadTime; /* re-initialize globals to default values */ int_locked_latency_min = ULONG_MAX; int_locked_latency_max = 0; cacheWarming--; } }
/** * * @brief Stop accumulating time spent for when interrupts are locked * * This is only call once when the interrupt are being reenabled * * @return N/A * */ void _int_latency_stop(void) { u32_t delta; u32_t delayOverhead; u32_t currentTime = k_cycle_get_32(); /* ensured intLatencyStart() was invoked first */ if (int_locked_timestamp) { /* * time spent with interrupt lock is: * (current time - time when interrupt got disabled first) - * (delay when invoking start + number nested calls to intLock * * time it takes to call intLatencyStart + intLatencyStop) */ delta = (currentTime - int_locked_timestamp); /* * Substract overhead introduce by the int latency benchmark * only if * it is bigger than delta. It can be possible sometimes for * delta to * be smaller than the estimated overhead. */ delayOverhead = (initial_start_delay + ((int_lock_unlock_nest - 1) * nesting_delay) + stop_delay); if (delta >= delayOverhead) delta -= delayOverhead; /* update max */ if (delta > int_locked_latency_max) int_locked_latency_max = delta; /* update min */ if (delta < int_locked_latency_min) int_locked_latency_min = delta; /* interrupts are now enabled, get ready for next interrupt lock */ int_locked_timestamp = 0; } }
void button_pressed(struct device *gpiob, struct gpio_callback *cb, u32_t pins) { printk("Button pressed at %d\n", k_cycle_get_32()); }