From 77466742c7661be63b4fc7049ffe1f2df7516945 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Thu, 5 Jan 2023 18:15:06 +0800 Subject: [PATCH] drivers/segger: register sysview to note drivers list Signed-off-by: yinshengkai --- drivers/note/Make.defs | 6 +- drivers/note/note_driver.c | 21 ++ drivers/segger/sysview.c | 492 ++++++++----------------------- include/nuttx/note/note_driver.h | 6 + 4 files changed, 144 insertions(+), 381 deletions(-) diff --git a/drivers/note/Make.defs b/drivers/note/Make.defs index fe6879e56e..4aef73cf1e 100644 --- a/drivers/note/Make.defs +++ b/drivers/note/Make.defs @@ -19,11 +19,9 @@ ############################################################################ ifeq ($(CONFIG_DRIVER_NOTE),y) - ifeq ($(CONFIG_SEGGER_SYSVIEW),) - CSRCS += note_driver.c - CFLAGS += ${INCDIR_PREFIX}${TOPDIR}/sched - endif + CSRCS += note_driver.c CSRCS += note_initialize.c + CFLAGS += ${INCDIR_PREFIX}${TOPDIR}/sched endif ifeq ($(CONFIG_DRIVER_NOTERAM),y) diff --git a/drivers/note/note_driver.c b/drivers/note/note_driver.c index b209a368b5..e00e318d1f 100644 --- a/drivers/note/note_driver.c +++ b/drivers/note/note_driver.c @@ -1907,3 +1907,24 @@ int note_get_taskname(pid_t pid, FAR char *buffer) } #endif + +/**************************************************************************** + * Name: note_driver_register + ****************************************************************************/ + +int note_driver_register(FAR struct note_driver_s *driver) +{ + int i; + DEBUGASSERT(driver); + + for (i = 0; i < CONFIG_DRIVER_NOTE_MAX; i++) + { + if (g_note_drivers[i] == NULL) + { + g_note_drivers[i] = driver; + return OK; + } + } + + return -ENOMEM; +} diff --git a/drivers/segger/sysview.c b/drivers/segger/sysview.c index 54b5159818..375f506e2d 100644 --- a/drivers/segger/sysview.c +++ b/drivers/segger/sysview.c @@ -22,12 +22,13 @@ * Included Files ****************************************************************************/ -#include +#include #include #include #include #include +#include #include #include @@ -39,36 +40,84 @@ * Private Types ****************************************************************************/ -struct sysview_s +struct note_sysview_driver_s { - unsigned int irq[CONFIG_SMP_NCPUS]; -#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER - struct note_filter_mode_s mode; -#endif -#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER - struct note_filter_irq_s irq_mask; -#endif + struct note_driver_s driver; + unsigned int irq[CONFIG_SMP_NCPUS]; #ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL - struct note_filter_syscall_s syscall_mask; struct note_filter_syscall_s syscall_marker; #endif }; +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void note_sysview_start(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +static void note_sysview_stop(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH +static void note_sysview_suspend(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +static void note_sysview_resume(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER +static void note_sysview_irqhandler(FAR struct note_driver_s *drv, int irq, + FAR void *handler, bool enter); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL +static void note_sysview_syscall_enter(FAR struct note_driver_s *drv, + int nr, int argc, va_list *ap); +static void note_sysview_syscall_leave(FAR struct note_driver_s *drv, + int nr, uintptr_t result); +#endif + /**************************************************************************** * Private Data ****************************************************************************/ -static struct sysview_s g_sysview = +static const struct note_driver_ops_s g_note_sysview_ops = { -#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER - .mode = - { - .flag = CONFIG_SCHED_INSTRUMENTATION_FILTER_DEFAULT_MODE, -#ifdef CONFIG_SMP - .cpuset = CONFIG_SCHED_INSTRUMENTATION_CPUSET, + NULL, /* add */ + note_sysview_start, /* start */ + note_sysview_stop, /* stop */ +#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH + note_sysview_suspend, /* suspend */ + note_sysview_resume, /* resume */ +# ifdef CONFIG_SMP + NULL, /* cpu_start */ + NULL, /* cpu_started */ + NULL, /* cpu_pause */ + NULL, /* cpu_paused */ + NULL, /* cpu_resume */ + NULL, /* cpu_resumed */ +# endif #endif - } +#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION + NULL, /* premption */ #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION + NULL, /* csection */ +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS + NULL, /* spinlock */ +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL + note_sysview_syscall_enter, /* syscall_enter */ + note_sysview_syscall_leave, /* syscall_leave */ +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER + note_sysview_irqhandler, /* irqhandler */ +#endif +}; + +static struct note_sysview_driver_s g_note_sysview_driver = +{ + { + &g_note_sysview_ops + } }; /**************************************************************************** @@ -76,10 +125,10 @@ static struct sysview_s g_sysview = ****************************************************************************/ /**************************************************************************** - * Name: sysview_send_taskinfo + * Name: note_sysview_send_taskinfo ****************************************************************************/ -static void sysview_send_taskinfo(FAR struct tcb_s *tcb) +static void note_sysview_send_taskinfo(FAR struct tcb_s *tcb) { SEGGER_SYSVIEW_TASKINFO info; @@ -97,19 +146,19 @@ static void sysview_send_taskinfo(FAR struct tcb_s *tcb) } /**************************************************************************** - * Name: sysview_get_time + * Name: note_sysview_get_time ****************************************************************************/ -static uint64_t sysview_get_time(void) +static uint64_t note_sysview_get_time(void) { return TICK2USEC(clock_systime_ticks()); } /**************************************************************************** - * Name: sysview_send_tasklist + * Name: note_sysview_send_tasklist ****************************************************************************/ -static void sysview_send_tasklist(void) +static void note_sysview_send_tasklist(void) { int i; @@ -117,16 +166,16 @@ static void sysview_send_tasklist(void) { if (g_pidhash[i] != NULL) { - sysview_send_taskinfo(g_pidhash[i]); + note_sysview_send_taskinfo(g_pidhash[i]); } } } /**************************************************************************** - * Name: sysview_send_description + * Name: note_sysview_send_description ****************************************************************************/ -static void sysview_send_description(void) +static void note_sysview_send_description(void) { SEGGER_SYSVIEW_SendSysDesc("N="SEGGER_SYSVIEW_APP_NAME); SEGGER_SYSVIEW_SendSysDesc("D="CONFIG_LIBC_HOSTNAME); @@ -134,136 +183,7 @@ static void sysview_send_description(void) } /**************************************************************************** - * Name: sysview_isenabled - * - * Description: - * Check whether the instrumentation is enabled. - * - * Input Parameters: - * None - * - * Returned Value: - * True is returned if the instrumentation is enabled. - * - ****************************************************************************/ - -static bool sysview_isenabled(void) -{ - bool enable; - - enable = SEGGER_SYSVIEW_IsStarted(); - -#if defined(CONFIG_SCHED_INSTRUMENTATION_FILTER) && defined(CONFIG_SMP) - /* Ignore notes that are not in the set of monitored CPUs */ - - if (enable && (g_sysview.mode.cpuset & (1 << this_cpu())) == 0) - { - /* Not in the set of monitored CPUs. Do not log the note. */ - - return false; - } -#endif - -#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL - /* Use the Syscall "0" to identify whether the syscall is enabled, - * if the host tool is closed abnormally, use this bit to clear - * the active set. - */ - - if (!enable && - NOTE_FILTER_SYSCALLMASK_ISSET(0, &g_sysview.syscall_marker)) - { - NOTE_FILTER_SYSCALLMASK_ZERO(&g_sysview.syscall_marker); - } -#endif - - return enable; -} - -/**************************************************************************** - * Name: sysview_isenabled_irq - * - * Description: - * Check whether the interrupt handler instrumentation is enabled. - * - * Input Parameters: - * irq - IRQ number - * enter - interrupt enter/leave flag - * - * Returned Value: - * True is returned if the instrumentation is enabled. - * - ****************************************************************************/ - -#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER -static bool sysview_isenabled_irq(int irq, bool enter) -{ -#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER - if (!sysview_isenabled()) - { - return false; - } - - /* If the IRQ trace is disabled or the IRQ number is masked, disable - * subsequent syscall traces until leaving the interrupt handler - */ - - if ((g_sysview.mode.flag & NOTE_FILTER_MODE_FLAG_IRQ) == 0 || - NOTE_FILTER_IRQMASK_ISSET(irq, &g_sysview.irq_mask)) - { - return false; - } -#endif - - return true; -} -#endif - -/**************************************************************************** - * Name: sysview_isenabled_syscall - * - * Description: - * Check whether the syscall instrumentation is enabled. - * - * Input Parameters: - * nr - syscall number - * - * Returned Value: - * True is returned if the instrumentation is enabled. - * - ****************************************************************************/ - -#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL -static inline int sysview_isenabled_syscall(int nr) -{ -#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER - if (!sysview_isenabled()) - { - return false; - } - - /* If the syscall trace is disabled or the syscall number is masked, - * do nothing. - */ - - if ((g_sysview.mode.flag & NOTE_FILTER_MODE_FLAG_SYSCALL) == 0 || - NOTE_FILTER_SYSCALLMASK_ISSET(nr, &g_sysview.syscall_mask)) - { - return false; - } -#endif - - return true; -} -#endif - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: sched_note_start, sched_note_stop, sched_note_switch, - * sched_note_premption + * Name: note_sysview_* * * Description: * Hooks to scheduler monitor @@ -276,48 +196,32 @@ static inline int sysview_isenabled_syscall(int nr) * ****************************************************************************/ -void sched_note_start(FAR struct tcb_s *tcb) +static void note_sysview_start(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb) { - if (!sysview_isenabled()) - { - return; - } - SEGGER_SYSVIEW_OnTaskCreate(tcb->pid); - sysview_send_taskinfo(tcb); + note_sysview_send_taskinfo(tcb); } -void sched_note_stop(FAR struct tcb_s *tcb) +static void note_sysview_stop(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb) { - if (!sysview_isenabled()) - { - return; - } - SEGGER_SYSVIEW_OnTaskTerminate(tcb->pid); } #ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH -void sched_note_suspend(FAR struct tcb_s *tcb) +static void note_sysview_suspend(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb) { - if (!sysview_isenabled()) - { - return; - } - if (!up_interrupt_context()) { SEGGER_SYSVIEW_OnTaskStopExec(); } } -void sched_note_resume(FAR struct tcb_s *tcb) +static void note_sysview_resume(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb) { - if (!sysview_isenabled()) - { - return; - } - if (!up_interrupt_context()) { if (is_idle_task(tcb)) @@ -333,16 +237,15 @@ void sched_note_resume(FAR struct tcb_s *tcb) #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER -void sched_note_irqhandler(int irq, FAR void *handler, bool enter) +static void note_sysview_irqhandler(FAR struct note_driver_s *drv, int irq, + FAR void *handler, bool enter) { - if (!sysview_isenabled_irq(irq, enter)) - { - return; - } + FAR struct note_sysview_driver_s *driver = + (FAR struct note_sysview_driver_s *)drv; if (enter) { - g_sysview.irq[up_cpu_index()] = irq; + driver->irq[up_cpu_index()] = irq; SEGGER_SYSVIEW_OnTaskStopExec(); SEGGER_SYSVIEW_RecordEnterISR(); @@ -365,24 +268,22 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter) } } - g_sysview.irq[up_cpu_index()] = 0; + driver->irq[up_cpu_index()] = 0; } } #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL -void sched_note_syscall_enter(int nr, int argc, ...) +static void note_sysview_syscall_enter(FAR struct note_driver_s *drv, int nr, + int argc, va_list *ap) { + FAR struct note_sysview_driver_s *driver = + (FAR struct note_sysview_driver_s *)drv; nr -= CONFIG_SYS_RESERVED; - if (sysview_isenabled_syscall(nr) == 0) - { - return; - } - /* Set the name marker if the current syscall nr is not active */ - if (NOTE_FILTER_SYSCALLMASK_ISSET(nr, &g_sysview.syscall_marker) == 0) + if (NOTE_FILTER_SYSCALLMASK_ISSET(nr, &driver->syscall_marker) == 0) { /* Set the name marker */ @@ -390,38 +291,40 @@ void sched_note_syscall_enter(int nr, int argc, ...) /* Mark the syscall active */ - NOTE_FILTER_SYSCALLMASK_SET(nr, &g_sysview.syscall_marker); + NOTE_FILTER_SYSCALLMASK_SET(nr, &driver->syscall_marker); /* Use the Syscall "0" to identify whether the syscall is enabled, * if the host tool is closed abnormally, use this bit to clear * the active set. */ - if (NOTE_FILTER_SYSCALLMASK_ISSET(0, &g_sysview.syscall_marker) == 0) + if (NOTE_FILTER_SYSCALLMASK_ISSET(0, &driver->syscall_marker) == 0) { - NOTE_FILTER_SYSCALLMASK_SET(0, &g_sysview.syscall_marker); + NOTE_FILTER_SYSCALLMASK_SET(0, &driver->syscall_marker); } } SEGGER_SYSVIEW_MarkStart(nr); } -void sched_note_syscall_leave(int nr, uintptr_t result) +static void note_sysview_syscall_leave(FAR struct note_driver_s *drv, + int nr, uintptr_t result) { + FAR struct note_sysview_driver_s *driver = + (FAR struct note_sysview_driver_s *)drv; nr -= CONFIG_SYS_RESERVED; - if (sysview_isenabled_syscall(nr) == 0) - { - return; - } - - if (NOTE_FILTER_SYSCALLMASK_ISSET(nr, &g_sysview.syscall_marker) != 0) + if (NOTE_FILTER_SYSCALLMASK_ISSET(nr, &driver->syscall_marker) != 0) { SEGGER_SYSVIEW_MarkStop(nr); } } #endif +/**************************************************************************** + * Public Functions + ****************************************************************************/ + /**************************************************************************** * Name: sysview_get_interrupt_id * @@ -432,7 +335,7 @@ void sched_note_syscall_leave(int nr, uintptr_t result) unsigned int sysview_get_interrupt_id(void) { - return g_sysview.irq[up_cpu_index()]; + return g_note_sysview_driver.irq[up_cpu_index()]; } /**************************************************************************** @@ -468,186 +371,21 @@ int sysview_initialize(void) static const SEGGER_SYSVIEW_OS_API g_sysview_trace_api = { - sysview_get_time, - sysview_send_tasklist, + note_sysview_get_time, + note_sysview_send_tasklist, }; SEGGER_SYSVIEW_Init(freq, freq, &g_sysview_trace_api, - sysview_send_description); + note_sysview_send_description); #if CONFIG_SEGGER_SYSVIEW_RAM_BASE != 0 SEGGER_SYSVIEW_SetRAMBase(CONFIG_SEGGER_SYSVIEW_RAM_BASE); #endif -#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER - if ((g_sysview.mode.flag & NOTE_FILTER_MODE_FLAG_ENABLE) != 0) -#endif - { - SEGGER_SYSVIEW_Start(); - } - + SEGGER_SYSVIEW_Start(); + note_driver_register(&g_note_sysview_driver.driver); syslog(LOG_NOTICE, "SEGGER RTT Control Block Address: %#" PRIxPTR "\n", (uintptr_t)&_SEGGER_RTT + CONFIG_SEGGER_RTT_UNCACHED_OFF); return 0; } - -#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER - -/**************************************************************************** - * Name: sched_note_filter_mode - * - * Description: - * Set and get note filter mode. - * (Same as NOTECTL_GETMODE / NOTECTL_SETMODE ioctls) - * - * Input Parameters: - * oldm - A writable pointer to struct note_filter_mode_s to get current - * filter mode - * If 0, no data is written. - * newm - A read-only pointer to struct note_filter_mode_s which holds the - * new filter mode - * If 0, the filter mode is not updated. - * - * Returned Value: - * None - * - ****************************************************************************/ - -void sched_note_filter_mode(struct note_filter_mode_s *oldm, - struct note_filter_mode_s *newm) -{ - irqstate_t flags; - - flags = spin_lock_irqsave(NULL); - - if (oldm != NULL) - { - if (SEGGER_SYSVIEW_IsStarted()) - { - g_sysview.mode.flag |= NOTE_FILTER_MODE_FLAG_ENABLE; - } - else - { - g_sysview.mode.flag &= ~NOTE_FILTER_MODE_FLAG_ENABLE; - } - - *oldm = g_sysview.mode; - } - - if (newm != NULL) - { - g_sysview.mode = *newm; - - if ((g_sysview.mode.flag & NOTE_FILTER_MODE_FLAG_ENABLE) != 0) - { - if (!SEGGER_SYSVIEW_IsStarted()) - { - SEGGER_SYSVIEW_Start(); - } - } - else - { - if (SEGGER_SYSVIEW_IsStarted()) - { - SEGGER_SYSVIEW_Stop(); - } - } - } - - spin_unlock_irqrestore(NULL, flags); -} - -/**************************************************************************** - * Name: sched_note_filter_irq - * - * Description: - * Set and get IRQ filter setting - * (Same as NOTECTL_GETIRQFILTER / NOTECTL_SETIRQFILTER ioctls) - * - * Input Parameters: - * oldf - A writable pointer to struct note_filter_irq_s to get - * current IRQ filter setting - * If 0, no data is written. - * newf - A read-only pointer to struct note_filter_irq_s of the new - * IRQ filter setting - * If 0, the setting is not updated. - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER -void sched_note_filter_irq(struct note_filter_irq_s *oldf, - struct note_filter_irq_s *newf) -{ - irqstate_t flags; - - flags = spin_lock_irqsave(NULL); - - if (oldf != NULL) - { - /* Return the current filter setting */ - - *oldf = g_sysview.irq_mask; - } - - if (newf != NULL) - { - /* Replace the syscall filter mask by the provided setting */ - - g_sysview.irq_mask = *newf; - } - - spin_unlock_irqrestore(NULL, flags); -} -#endif - -/**************************************************************************** - * Name: sched_note_filter_syscall - * - * Description: - * Set and get syscall filter setting - * (Same as NOTECTL_GETSYSCALLFILTER / NOTECTL_SETSYSCALLFILTER ioctls) - * - * Input Parameters: - * oldf - A writable pointer to struct note_filter_syscall_s to get - * current syscall filter setting - * If 0, no data is written. - * newf - A read-only pointer to struct note_filter_syscall_s of the - * new syscall filter setting - * If 0, the setting is not updated. - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL -void sched_note_filter_syscall(struct note_filter_syscall_s *oldf, - struct note_filter_syscall_s *newf) -{ - irqstate_t flags; - - flags = spin_lock_irqsave(NULL); - - if (oldf != NULL) - { - /* Return the current filter setting */ - - *oldf = g_sysview.syscall_mask; - } - - if (newf != NULL) - { - /* Replace the syscall filter mask by the provided setting */ - - g_sysview.syscall_mask = *newf; - } - - spin_unlock_irqrestore(NULL, flags); -} -#endif - -#endif /* CONFIG_SCHED_INSTRUMENTATION_FILTER */ diff --git a/include/nuttx/note/note_driver.h b/include/nuttx/note/note_driver.h index 8a2f8ad810..f16d3a86b7 100644 --- a/include/nuttx/note/note_driver.h +++ b/include/nuttx/note/note_driver.h @@ -154,4 +154,10 @@ int note_get_taskname(pid_t pid, FAR char *name); #endif /* CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE > 0 */ +/**************************************************************************** + * Name: note_driver_register + ****************************************************************************/ + +int note_driver_register(FAR struct note_driver_s *driver); + #endif /* __INCLUDE_NUTTX_NOTE_NOTE_DRIVER_H */