sysview_tracing.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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 <stdio.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include "esp_log.h"
  11. #include "freertos/FreeRTOS.h"
  12. #include "freertos/task.h"
  13. #include "driver/timer.h"
  14. static const char *TAG = "example";
  15. typedef struct {
  16. int group;
  17. int timer;
  18. int count;
  19. TaskHandle_t thnd;
  20. } example_event_data_t;
  21. #if CONFIG_APPTRACE_SV_ENABLE
  22. #if !CONFIG_USE_CUSTOM_EVENT_ID
  23. #define SYSVIEW_EXAMPLE_SEND_EVENT_ID 0
  24. #define SYSVIEW_EXAMPLE_WAIT_EVENT_ID 1
  25. #define SYSVIEW_EXAMPLE_SEND_EVENT_START() SEGGER_SYSVIEW_OnUserStart(SYSVIEW_EXAMPLE_SEND_EVENT_ID)
  26. #define SYSVIEW_EXAMPLE_SEND_EVENT_END(_val_) SEGGER_SYSVIEW_OnUserStop(SYSVIEW_EXAMPLE_SEND_EVENT_ID)
  27. #define SYSVIEW_EXAMPLE_WAIT_EVENT_START() SEGGER_SYSVIEW_OnUserStart(SYSVIEW_EXAMPLE_WAIT_EVENT_ID)
  28. #define SYSVIEW_EXAMPLE_WAIT_EVENT_END(_val_) SEGGER_SYSVIEW_OnUserStop(SYSVIEW_EXAMPLE_WAIT_EVENT_ID)
  29. #else
  30. #define SYSVIEW_EXAMPLE_SEND_EVENT_START_ID 0
  31. #define SYSVIEW_EXAMPLE_SEND_EVENT_END_ID 1
  32. #define SYSVIEW_EXAMPLE_WAIT_EVENT_START_ID 2
  33. #define SYSVIEW_EXAMPLE_WAIT_EVENT_END_ID 3
  34. #define SYSVIEW_EXAMPLE_EVENT_MAX 4
  35. #define SYSVIEW_EXAMPLE_SEND_EVENT_START() example_sysview_event_send(SYSVIEW_EXAMPLE_SEND_EVENT_START_ID, 0)
  36. #define SYSVIEW_EXAMPLE_SEND_EVENT_END(_val_) example_sysview_event_send(SYSVIEW_EXAMPLE_SEND_EVENT_END_ID, _val_)
  37. #define SYSVIEW_EXAMPLE_WAIT_EVENT_START() example_sysview_event_send(SYSVIEW_EXAMPLE_WAIT_EVENT_START_ID, 0)
  38. #define SYSVIEW_EXAMPLE_WAIT_EVENT_END(_val_) example_sysview_event_send(SYSVIEW_EXAMPLE_WAIT_EVENT_END_ID, _val_)
  39. static void example_sysview_module_send_desc(void);
  40. static SEGGER_SYSVIEW_MODULE s_example_sysview_module = {
  41. .sModule = "example_sysview_module",
  42. .NumEvents = SYSVIEW_EXAMPLE_EVENT_MAX,
  43. .pfSendModuleDesc = example_sysview_module_send_desc,
  44. };
  45. static void example_sysview_module_send_desc(void)
  46. {
  47. SEGGER_SYSVIEW_RecordModuleDescription(&s_example_sysview_module, "Example SystemView User Module");
  48. }
  49. static void example_sysview_event_send(uint32_t id, uint32_t val)
  50. {
  51. U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32];
  52. U8 *pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
  53. pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, val); // Add the parameter to the packet
  54. SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_example_sysview_module.EventOffset + id);
  55. }
  56. #endif
  57. #else
  58. #define SYSVIEW_EXAMPLE_SEND_EVENT_START()
  59. #define SYSVIEW_EXAMPLE_SEND_EVENT_END(_val_)
  60. #define SYSVIEW_EXAMPLE_WAIT_EVENT_START()
  61. #define SYSVIEW_EXAMPLE_WAIT_EVENT_END(_val_)
  62. #endif
  63. static void example_timer_init(int timer_group, int timer_idx, uint32_t period)
  64. {
  65. timer_config_t config;
  66. uint64_t alarm_val = (period * (TIMER_BASE_CLK / 1000000UL)) / 2;
  67. config.alarm_en = 1;
  68. config.auto_reload = 1;
  69. config.counter_dir = TIMER_COUNT_UP;
  70. config.divider = 2; //Range is 2 to 65536
  71. config.intr_type = TIMER_INTR_LEVEL;
  72. config.counter_en = TIMER_PAUSE;
  73. /*Configure timer*/
  74. timer_init(timer_group, timer_idx, &config);
  75. /*Stop timer counter*/
  76. timer_pause(timer_group, timer_idx);
  77. /*Load counter value */
  78. timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL);
  79. /*Set alarm value*/
  80. timer_set_alarm_value(timer_group, timer_idx, alarm_val);
  81. /*Enable timer interrupt*/
  82. timer_enable_intr(timer_group, timer_idx);
  83. }
  84. static void example_timer_isr(void *arg)
  85. {
  86. example_event_data_t *tim_arg = (example_event_data_t *)arg;
  87. if (tim_arg->thnd != NULL) {
  88. if (tim_arg->count++ < 10) {
  89. BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  90. SYSVIEW_EXAMPLE_SEND_EVENT_START();
  91. if (xTaskNotifyFromISR(tim_arg->thnd, tim_arg->count, eSetValueWithOverwrite, &xHigherPriorityTaskWoken) != pdPASS) {
  92. ESP_EARLY_LOGE(TAG, "Failed to notify task %p", tim_arg->thnd);
  93. } else {
  94. SYSVIEW_EXAMPLE_SEND_EVENT_END(tim_arg->count);
  95. if (xHigherPriorityTaskWoken == pdTRUE) {
  96. portYIELD_FROM_ISR();
  97. }
  98. }
  99. }
  100. }
  101. // re-start timer
  102. timer_group_clr_intr_status_in_isr(tim_arg->group, tim_arg->timer);
  103. timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->timer);
  104. }
  105. static void example_task(void *p)
  106. {
  107. example_event_data_t *arg = (example_event_data_t *) p;
  108. timer_isr_handle_t inth;
  109. ESP_LOGI(TAG, "%p: run task", xTaskGetCurrentTaskHandle());
  110. esp_err_t res = timer_isr_register(arg->group, arg->timer, example_timer_isr, arg, 0, &inth);
  111. if (res != ESP_OK) {
  112. ESP_LOGE(TAG, "%p: failed to register timer ISR", xTaskGetCurrentTaskHandle());
  113. } else {
  114. res = timer_start(arg->group, arg->timer);
  115. if (res != ESP_OK) {
  116. ESP_LOGE(TAG, "%p: failed to start timer", xTaskGetCurrentTaskHandle());
  117. }
  118. }
  119. while (1) {
  120. uint32_t event_val;
  121. SYSVIEW_EXAMPLE_WAIT_EVENT_START();
  122. xTaskNotifyWait(0, 0, &event_val, portMAX_DELAY);
  123. SYSVIEW_EXAMPLE_WAIT_EVENT_END(event_val);
  124. ESP_LOGI(TAG, "Task[%p]: received event %d", xTaskGetCurrentTaskHandle(), event_val);
  125. }
  126. }
  127. void app_main(void)
  128. {
  129. static example_event_data_t event_data[portNUM_PROCESSORS] = {
  130. {
  131. .group = TIMER_GROUP_1,
  132. .timer = TIMER_0,
  133. },
  134. #if CONFIG_FREERTOS_UNICORE == 0
  135. {
  136. .group = TIMER_GROUP_0,
  137. .timer = TIMER_0,
  138. },
  139. #endif
  140. };
  141. #if CONFIG_APPTRACE_SV_ENABLE && CONFIG_USE_CUSTOM_EVENT_ID
  142. // Currently OpenOCD does not support requesting module info from target. So do the following...
  143. // Wait untill SystemView module receives START command from host,
  144. // after that data can be sent to the host using onboard API,
  145. // so user module description does not need to be requested by OpenOCD itself.
  146. while (!SEGGER_SYSVIEW_Started()) {
  147. vTaskDelay(1);
  148. }
  149. SEGGER_SYSVIEW_RegisterModule(&s_example_sysview_module);
  150. #endif
  151. #if !CONFIG_APPTRACE_SV_TS_SOURCE_TIMER_10
  152. example_timer_init(TIMER_GROUP_1, TIMER_0, 2000);
  153. #else
  154. #warning "Timer (Group 1, Timer 0) is used by sysview module itself!"
  155. #endif
  156. #if !CONFIG_APPTRACE_SV_TS_SOURCE_TIMER_00
  157. example_timer_init(TIMER_GROUP_0, TIMER_0, 4000);
  158. #else
  159. #warning "Timer (Group 0, Timer 0) is used by sysview module itself!"
  160. #endif
  161. xTaskCreatePinnedToCore(example_task, "svtrace0", 2048, &event_data[0], 3, &event_data[0].thnd, 0);
  162. ESP_LOGI(TAG, "Created task %p", event_data[0].thnd);
  163. #if CONFIG_FREERTOS_UNICORE == 0
  164. xTaskCreatePinnedToCore(example_task, "svtrace1", 2048, &event_data[1], 3, &event_data[1].thnd, 1);
  165. ESP_LOGI(TAG, "Created task %p", event_data[1].thnd);
  166. #endif
  167. }