sysview_heap_log.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /* Application Trace to Host Example
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. Unless required by applicable law or agreed to in writing, this
  4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5. CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. #include "esp_sysview_trace.h"
  8. #include "esp_heap_trace.h"
  9. #include "esp_log.h"
  10. #include "freertos/FreeRTOS.h"
  11. #include "freertos/task.h"
  12. #include "freertos/queue.h"
  13. static const char *TAG = "example";
  14. // waits on queue for memory addresses and frees memory allocated by 'alloc_task'
  15. static void free_task(void *p)
  16. {
  17. QueueHandle_t queue = (QueueHandle_t)p;
  18. while (1) {
  19. void *p = NULL;
  20. if (xQueueReceive(queue, ( void * )&p, portMAX_DELAY) != pdPASS) {
  21. ESP_LOGE(TAG, "Failed to send to queue!");
  22. } else {
  23. ESP_LOGI(TAG, "Task[%p]: free memory @ %p", xTaskGetCurrentTaskHandle(), p);
  24. free(p);
  25. }
  26. }
  27. }
  28. struct alloc_args {
  29. int idx;
  30. TaskHandle_t waiter;
  31. };
  32. // allocates memory and puts addresses to the queue
  33. static void alloc_task(void *p)
  34. {
  35. struct alloc_args *task_args = (struct alloc_args *)p;
  36. char task_name[20];
  37. QueueHandle_t queue = xQueueCreate(10, sizeof(void *));
  38. if(queue == 0) {
  39. ESP_LOGE(TAG, "Failed to create queue!");
  40. return;
  41. }
  42. snprintf(task_name, sizeof(task_name), "free%d", task_args->idx);
  43. xTaskCreatePinnedToCore(free_task, task_name, 2500, queue, 5, NULL, portNUM_PROCESSORS-1);
  44. // here GDB will stop at brekpoint and execute OpenOCD command to start tracing
  45. for(int i = 1; i < 100; i++) {
  46. uint32_t sz = 2*i*(task_args->idx + 1);
  47. void *p = malloc(sz/2);
  48. // WARNING: the previous allocated memory is intentionally not deallocated in order to cause memory leak!
  49. p = malloc(sz);
  50. ESP_LOGI(TAG, "Task[%p]: allocated %d bytes @ %p", xTaskGetCurrentTaskHandle(), sz, p);
  51. if (xQueueSend(queue, ( void * )&p, portMAX_DELAY) != pdPASS) {
  52. ESP_LOGE(TAG, "Failed to send to queue!");
  53. }
  54. vTaskDelay(30/portTICK_PERIOD_MS);
  55. }
  56. xTaskNotifyGive(task_args->waiter);
  57. while(1){
  58. vTaskDelay(100/portTICK_PERIOD_MS);
  59. }
  60. }
  61. void app_main(void)
  62. {
  63. const int num_allocers = 3;
  64. char task_name[20];
  65. // redirect log messages to the host using SystemView tracing module
  66. esp_log_set_vprintf(&esp_sysview_vprintf);
  67. // init host-based heap tracing
  68. if(heap_trace_init_tohost() != ESP_OK) {
  69. ESP_LOGE(TAG, "Failed to init heap trace!");
  70. return;
  71. }
  72. heap_trace_start(HEAP_TRACE_ALL);
  73. for (int i = 0; i < num_allocers; i++) {
  74. struct alloc_args *task_args = malloc(sizeof(struct alloc_args));
  75. if (task_args == NULL) {
  76. ESP_LOGE(TAG, "Failed to alloc task args!");
  77. heap_trace_stop();
  78. return;
  79. }
  80. task_args->idx = i;
  81. task_args->waiter = xTaskGetCurrentTaskHandle();
  82. snprintf(task_name, sizeof(task_name), "alloc%d", i);
  83. xTaskCreatePinnedToCore(alloc_task, task_name, 2500, task_args, 5, NULL, 0);
  84. }
  85. for (int i = 0; i < num_allocers; i++) {
  86. ESP_LOGI(TAG, "Wait notify %d", i);
  87. uint32_t val = ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
  88. ESP_LOGI(TAG, "Got notify val %d", val);
  89. }
  90. // here GDB will stop at brekpoint and execute OpenOCD command to stop tracing
  91. heap_trace_stop();
  92. }