mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-25 02:47:27 +08:00
add dump_threads diagnostics function
This commit is contained in:
@@ -177,20 +177,26 @@ void vApplicationIdleHook(void) {
|
||||
if (odrv.system_stats_.fully_booted) {
|
||||
odrv.system_stats_.uptime = xTaskGetTickCount();
|
||||
odrv.system_stats_.min_heap_space = xPortGetMinimumEverFreeHeapSize();
|
||||
|
||||
uint32_t min_stack_space[AXIS_COUNT];
|
||||
std::transform(axes.begin(), axes.end(), std::begin(min_stack_space), [](auto& axis) { return uxTaskGetStackHighWaterMark(axis.thread_id_) * sizeof(StackType_t); });
|
||||
odrv.system_stats_.min_stack_space_axis = *std::min_element(std::begin(min_stack_space), std::end(min_stack_space));
|
||||
odrv.system_stats_.min_stack_space_usb = uxTaskGetStackHighWaterMark(usb_thread) * sizeof(StackType_t);
|
||||
odrv.system_stats_.min_stack_space_uart = uxTaskGetStackHighWaterMark(uart_thread) * sizeof(StackType_t);
|
||||
odrv.system_stats_.min_stack_space_startup = uxTaskGetStackHighWaterMark(defaultTaskHandle) * sizeof(StackType_t);
|
||||
odrv.system_stats_.min_stack_space_can = uxTaskGetStackHighWaterMark(odCAN->thread_id_) * sizeof(StackType_t);
|
||||
odrv.system_stats_.max_stack_usage_axis = axes[0].stack_size_ - *std::min_element(std::begin(min_stack_space), std::end(min_stack_space));
|
||||
odrv.system_stats_.max_stack_usage_usb = stack_size_usb_thread - uxTaskGetStackHighWaterMark(usb_thread) * sizeof(StackType_t);
|
||||
odrv.system_stats_.max_stack_usage_uart = stack_size_uart_thread - uxTaskGetStackHighWaterMark(uart_thread) * sizeof(StackType_t);
|
||||
odrv.system_stats_.max_stack_usage_startup = stack_size_default_task - uxTaskGetStackHighWaterMark(defaultTaskHandle) * sizeof(StackType_t);
|
||||
odrv.system_stats_.max_stack_usage_can = odCAN->stack_size_ - uxTaskGetStackHighWaterMark(odCAN->thread_id_) * sizeof(StackType_t);
|
||||
|
||||
// Actual usage, in bytes, so we don't have to math
|
||||
odrv.system_stats_.stack_usage_axis = axes[0].stack_size_ - odrv.system_stats_.min_stack_space_axis;
|
||||
odrv.system_stats_.stack_usage_usb = stack_size_usb_thread - odrv.system_stats_.min_stack_space_usb;
|
||||
odrv.system_stats_.stack_usage_uart = stack_size_uart_thread - odrv.system_stats_.min_stack_space_uart;
|
||||
odrv.system_stats_.stack_usage_startup = stack_size_default_task - odrv.system_stats_.min_stack_space_startup;
|
||||
odrv.system_stats_.stack_usage_can = odCAN->stack_size_ - odrv.system_stats_.min_stack_space_can;
|
||||
odrv.system_stats_.stack_size_axis = axes[0].stack_size_;
|
||||
odrv.system_stats_.stack_size_usb = stack_size_usb_thread;
|
||||
odrv.system_stats_.stack_size_uart = stack_size_uart_thread;
|
||||
odrv.system_stats_.stack_size_startup = stack_size_default_task;
|
||||
odrv.system_stats_.stack_size_can = odCAN->stack_size_;
|
||||
|
||||
odrv.system_stats_.prio_axis = osThreadGetPriority(axes[0].thread_id_);
|
||||
odrv.system_stats_.prio_usb = osThreadGetPriority(usb_thread);
|
||||
odrv.system_stats_.prio_uart = osThreadGetPriority(uart_thread);
|
||||
odrv.system_stats_.prio_startup = osThreadGetPriority(defaultTaskHandle);
|
||||
odrv.system_stats_.prio_can = osThreadGetPriority(odCAN->thread_id_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,17 +29,23 @@ typedef struct {
|
||||
bool fully_booted;
|
||||
uint32_t uptime; // [ms]
|
||||
uint32_t min_heap_space; // FreeRTOS heap [Bytes]
|
||||
uint32_t min_stack_space_axis; // minimum remaining space since startup [Bytes]
|
||||
uint32_t min_stack_space_usb;
|
||||
uint32_t min_stack_space_uart;
|
||||
uint32_t min_stack_space_startup;
|
||||
uint32_t min_stack_space_can;
|
||||
uint32_t max_stack_usage_axis; // minimum remaining space since startup [Bytes]
|
||||
uint32_t max_stack_usage_usb;
|
||||
uint32_t max_stack_usage_uart;
|
||||
uint32_t max_stack_usage_startup;
|
||||
uint32_t max_stack_usage_can;
|
||||
|
||||
uint32_t stack_usage_axis;
|
||||
uint32_t stack_usage_usb;
|
||||
uint32_t stack_usage_uart;
|
||||
uint32_t stack_usage_startup;
|
||||
uint32_t stack_usage_can;
|
||||
uint32_t stack_size_axis;
|
||||
uint32_t stack_size_usb;
|
||||
uint32_t stack_size_uart;
|
||||
uint32_t stack_size_startup;
|
||||
uint32_t stack_size_can;
|
||||
|
||||
int32_t prio_axis;
|
||||
int32_t prio_usb;
|
||||
int32_t prio_uart;
|
||||
int32_t prio_startup;
|
||||
int32_t prio_can;
|
||||
|
||||
USBStats_t& usb = usb_stats_;
|
||||
I2CStats_t& i2c = i2c_stats_;
|
||||
|
||||
@@ -126,16 +126,21 @@ interfaces:
|
||||
attributes:
|
||||
uptime: readonly uint32
|
||||
min_heap_space: readonly uint32
|
||||
min_stack_space_axis: readonly uint32
|
||||
min_stack_space_usb: readonly uint32
|
||||
min_stack_space_uart: readonly uint32
|
||||
min_stack_space_can: readonly uint32
|
||||
min_stack_space_startup: readonly uint32
|
||||
stack_usage_axis: readonly uint32
|
||||
stack_usage_usb: readonly uint32
|
||||
stack_usage_uart: readonly uint32
|
||||
stack_usage_startup: readonly uint32
|
||||
stack_usage_can: readonly uint32
|
||||
max_stack_usage_axis: readonly uint32
|
||||
max_stack_usage_usb: readonly uint32
|
||||
max_stack_usage_uart: readonly uint32
|
||||
max_stack_usage_can: readonly uint32
|
||||
max_stack_usage_startup: readonly uint32
|
||||
stack_size_axis: readonly uint32
|
||||
stack_size_usb: readonly uint32
|
||||
stack_size_uart: readonly uint32
|
||||
stack_size_startup: readonly uint32
|
||||
stack_size_can: readonly uint32
|
||||
prio_axis: readonly int32
|
||||
prio_usb: readonly int32
|
||||
prio_uart: readonly int32
|
||||
prio_startup: readonly int32
|
||||
prio_can: readonly int32
|
||||
usb:
|
||||
c_is_class: False
|
||||
attributes:
|
||||
|
||||
+16
-1
@@ -1,5 +1,5 @@
|
||||
|
||||
Most information in this file can be reproduced by running `dump_interrupts(odrv0)` and `dump_dma(odrv0)` in `odrivetool`.
|
||||
Most information in this file can be reproduced by running `dump_interrupts(odrv0)`, `dump_dma(odrv0)` and `dump_threads(odrv0)` in `odrivetool` (minor manual postprocessing was applied to the output of those functions).
|
||||
|
||||
Take this info with a grain of salt as we might forget to update it from time to time. When in doubt check the file history.
|
||||
|
||||
@@ -55,3 +55,18 @@ Take this info with a grain of salt as we might forget to update it from time to
|
||||
| DMA1_Stream5 | 2 | 0 (SPI3_TX) | SPI |
|
||||
| DMA2_Stream0 | 0 | 0 (ADC1) | freerunning ADC |
|
||||
|
||||
|
||||
## Threads
|
||||
|
||||
- lowest priority: -3
|
||||
- highest priority: 3
|
||||
|
||||
| Name | Stack Size [B] | Prio |
|
||||
|---------|----------------|------|
|
||||
| axis0 | 2048 | 3 |
|
||||
| axis1 | 2048 | 2 |
|
||||
| can | 1024 | 0 |
|
||||
| startup | 2048 | 0 |
|
||||
| uart | 4096 | 0 |
|
||||
| usb | 4096 | 0 |
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ def launch_shell(args, logger, app_shutdown_token):
|
||||
'dump_errors': dump_errors,
|
||||
'oscilloscope_dump': oscilloscope_dump,
|
||||
'dump_interrupts': dump_interrupts,
|
||||
'dump_threads': dump_threads,
|
||||
'dump_dma': dump_dma,
|
||||
'dump_timing': dump_timing,
|
||||
'BulkCapture': BulkCapture,
|
||||
|
||||
@@ -487,6 +487,25 @@ def dump_interrupts(odrv):
|
||||
" *" if (status & 0x80000000) else " ",
|
||||
str((status >> 8) & 0x7fffff).rjust(7)))
|
||||
|
||||
def dump_threads(odrv):
|
||||
prefixes = ["max_stack_usage_", "stack_size_", "prio_"]
|
||||
keys = [k[len(prefix):] for k in dir(odrv.system_stats) for prefix in prefixes if k.startswith(prefix)]
|
||||
good_keys = set([k for k in set(keys) if keys.count(k) == len(prefixes)])
|
||||
if len(good_keys) > len(set(keys)):
|
||||
print("Warning: incomplete thread information for threads {}".format(set(keys) - good_keys))
|
||||
|
||||
print("| Name | Stack Size [B] | Max Ever Stack Usage [B] | Prio |")
|
||||
print("|---------|----------------|--------------------------|------|")
|
||||
for k in sorted(good_keys):
|
||||
sz = getattr(odrv.system_stats, "stack_size_" + k)
|
||||
use = getattr(odrv.system_stats, "max_stack_usage_" + k)
|
||||
print("| {} | {} | {} | {} |".format(
|
||||
k.ljust(7),
|
||||
str(sz).rjust(14),
|
||||
"{} ({:.1f}%)".format(use, use / sz * 100).rjust(24),
|
||||
str(getattr(odrv.system_stats, "prio_" + k)).rjust(4)
|
||||
))
|
||||
|
||||
|
||||
def dump_dma(odrv):
|
||||
if odrv.hw_version_major == 3:
|
||||
|
||||
Reference in New Issue
Block a user