]>
Commit | Line | Data |
---|---|---|
1f865ee0 SR |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * A general-purpose cyclic execution infrastructure, to allow "small" | |
4 | * (run-time wise) functions to be executed at a specified frequency. | |
5 | * Things like LED blinking or watchdog triggering are examples for such | |
6 | * tasks. | |
7 | * | |
8 | * Copyright (C) 2022 Stefan Roese <[email protected]> | |
9 | */ | |
10 | ||
1f865ee0 SR |
11 | #include <command.h> |
12 | #include <cyclic.h> | |
13 | #include <div64.h> | |
14 | #include <malloc.h> | |
03de305e TR |
15 | #include <time.h> |
16 | #include <vsprintf.h> | |
1f865ee0 | 17 | #include <linux/delay.h> |
008c4b3c | 18 | #include <linux/kernel.h> |
1f865ee0 SR |
19 | |
20 | struct cyclic_demo_info { | |
008c4b3c | 21 | struct cyclic_info cyclic; |
1f865ee0 SR |
22 | uint delay_us; |
23 | }; | |
24 | ||
008c4b3c | 25 | static void cyclic_demo(struct cyclic_info *c) |
1f865ee0 | 26 | { |
008c4b3c | 27 | struct cyclic_demo_info *info = container_of(c, struct cyclic_demo_info, cyclic); |
1f865ee0 SR |
28 | |
29 | /* Just a small dummy delay here */ | |
30 | udelay(info->delay_us); | |
31 | } | |
32 | ||
33 | static int do_cyclic_demo(struct cmd_tbl *cmdtp, int flag, int argc, | |
34 | char *const argv[]) | |
35 | { | |
36 | struct cyclic_demo_info *info; | |
1f865ee0 SR |
37 | uint time_ms; |
38 | ||
39 | if (argc < 3) | |
40 | return CMD_RET_USAGE; | |
41 | ||
42 | info = malloc(sizeof(struct cyclic_demo_info)); | |
43 | if (!info) { | |
44 | printf("out of memory\n"); | |
45 | return CMD_RET_FAILURE; | |
46 | } | |
47 | ||
48 | time_ms = simple_strtoul(argv[1], NULL, 0); | |
49 | info->delay_us = simple_strtoul(argv[2], NULL, 0); | |
50 | ||
51 | /* Register demo cyclic function */ | |
008c4b3c | 52 | cyclic_register(&info->cyclic, cyclic_demo, time_ms * 1000, "cyclic_demo"); |
1f865ee0 SR |
53 | |
54 | printf("Registered function \"%s\" to be executed all %dms\n", | |
55 | "cyclic_demo", time_ms); | |
56 | ||
57 | return 0; | |
58 | } | |
59 | ||
60 | static int do_cyclic_list(struct cmd_tbl *cmdtp, int flag, int argc, | |
61 | char *const argv[]) | |
62 | { | |
28968394 RV |
63 | struct cyclic_info *cyclic; |
64 | struct hlist_node *tmp; | |
1f865ee0 SR |
65 | u64 cnt, freq; |
66 | ||
28968394 | 67 | hlist_for_each_entry_safe(cyclic, tmp, cyclic_get_list(), list) { |
1f865ee0 SR |
68 | cnt = cyclic->run_cnt * 1000000ULL * 100ULL; |
69 | freq = lldiv(cnt, timer_get_us() - cyclic->start_time_us); | |
70 | printf("function: %s, cpu-time: %lld us, frequency: %lld.%02d times/s\n", | |
71 | cyclic->name, cyclic->cpu_time_us, | |
72 | lldiv(freq, 100), do_div(freq, 100)); | |
73 | } | |
74 | ||
75 | return 0; | |
76 | } | |
77 | ||
3616218b | 78 | U_BOOT_LONGHELP(cyclic, |
8ba4eae0 | 79 | "demo <cycletime_ms> <delay_us> - register cyclic demo function\n" |
3616218b | 80 | "cyclic list - list cyclic functions\n"); |
1f865ee0 SR |
81 | |
82 | U_BOOT_CMD_WITH_SUBCMDS(cyclic, "Cyclic", cyclic_help_text, | |
83 | U_BOOT_SUBCMD_MKENT(demo, 3, 1, do_cyclic_demo), | |
84 | U_BOOT_SUBCMD_MKENT(list, 1, 1, do_cyclic_list)); |