| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #include "os/mynewt.h" |
| #include "mcu/mcu.h" |
| #include "bsp/bsp.h" |
| #include "hal/hal_timer.h" |
| #include "sysview/vendor/SEGGER_SYSVIEW.h" |
| #include "sysview/vendor/SEGGER_SYSVIEW_Conf.h" |
| |
| #define STRX(x) #x |
| #define STR(x) STRX(x) |
| |
| #if MYNEWT_VAL(SYSVIEW_TIMESTAMP_USE_TIMER) |
| |
| #define SYSVIEW_TIMESTAMP_FREQ (MYNEWT_VAL(SYSVIEW_TIMESTAMP_TIMER_FREQ)) |
| |
| U32 |
| SEGGER_SYSVIEW_X_GetTimestamp(void) |
| { |
| return hal_timer_read(MYNEWT_VAL(SYSVIEW_TIMESTAMP_TIMER_NUM)); |
| } |
| |
| #elif SEGGER_SYSVIEW_CORE == SEGGER_SYSVIEW_CORE_CM3 |
| |
| #define SYSVIEW_TIMESTAMP_FREQ (SystemCoreClock) |
| |
| #else |
| |
| #define SYSVIEW_TIMESTAMP_FREQ (OS_TICKS_PER_SEC) |
| |
| U32 |
| SEGGER_SYSVIEW_X_GetTimestamp(void) |
| { |
| /* XXX Just need to return some kind of timestamp... */ |
| return os_time_get(); |
| } |
| |
| #endif |
| |
| #define SYSVIEW_CPU_FREQ (SystemCoreClock) |
| #define SYSVIEW_RAM_BASE ((uint32_t)&_ram_start) |
| |
| static U64 |
| sysview_os_api_get_time_func(void) |
| { |
| return (U64)os_get_uptime_usec(); |
| } |
| |
| static void |
| sysview_os_api_send_task_list_func(void) |
| { |
| struct os_task *t; |
| |
| STAILQ_FOREACH(t, &g_os_task_list, t_os_task_list) { |
| os_trace_task_info(t); |
| } |
| } |
| |
| static const SEGGER_SYSVIEW_OS_API sysview_os_api = { |
| sysview_os_api_get_time_func, |
| sysview_os_api_send_task_list_func, |
| }; |
| |
| static void |
| sysview_os_api_send_interrupts_desc(void) |
| { |
| #ifdef MCU_SYSVIEW_INTERRUPTS |
| static U8 pkt[32]; |
| U8 *payload; |
| const char *s; |
| const char *ptr; |
| |
| /* |
| * Interrupts description can be very long thus we cannot send it as single |
| * system description string due to length limit. Instead, we'll tokenize it |
| * into separate interrupt descriptions and send one by one manually. |
| */ |
| |
| s = MCU_SYSVIEW_INTERRUPTS; |
| |
| do { |
| ptr = s; |
| |
| while (*ptr && *ptr != ',') { |
| ptr++; |
| } |
| |
| /* Leave 4 bytes for header */ |
| payload = &pkt[4]; |
| payload = SEGGER_SYSVIEW_EncodeString(payload, s, |
| min(sizeof(pkt) - SEGGER_SYSVIEW_INFO_SIZE, ptr - s)); |
| SEGGER_SYSVIEW_SendPacket(pkt, payload, SYSVIEW_EVTID_SYSDESC); |
| |
| if (*ptr) { |
| s = ptr + 1; |
| } |
| } while (*ptr); |
| #endif |
| } |
| |
| static void |
| sysview_os_api_send_sys_desc_func(void) |
| { |
| SEGGER_SYSVIEW_SendSysDesc("O=Apache Mynewt," |
| "N=" STR(APP_NAME) "," |
| "D=" STR(BSP_NAME) "," |
| "C=" STR(ARCH_NAME)); |
| |
| sysview_os_api_send_interrupts_desc(); |
| } |
| |
| void |
| sysview_init(void) |
| { |
| #if MYNEWT_VAL(SYSVIEW_TIMESTAMP_USE_TIMER) |
| hal_timer_config(MYNEWT_VAL(SYSVIEW_TIMESTAMP_TIMER_NUM), |
| MYNEWT_VAL(SYSVIEW_TIMESTAMP_TIMER_FREQ)); |
| #elif SEGGER_SYSVIEW_CORE == SEGGER_SYSVIEW_CORE_CM3 |
| /* Enable Cycle Counter on Cortex-M3/M4 to get accurate timestamps */ |
| DWT->CTRL |= (1 << DWT_CTRL_CYCCNTENA_Pos); |
| #endif |
| |
| SEGGER_SYSVIEW_Init(SYSVIEW_TIMESTAMP_FREQ, SYSVIEW_CPU_FREQ, |
| &sysview_os_api, sysview_os_api_send_sys_desc_func); |
| SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE); |
| |
| #if MYNEWT_VAL(SYSVIEW_POST_MORTEM) |
| SEGGER_SYSVIEW_Start(); |
| #endif |
| } |