nuttx-apps/examples/nxscope/nxscope_main.c
raiden00pl ee1e84a261 examples/nxscope: add a new option to wake up the samples thread with timer.
Now we can add samples with at a higher frequency than with usleep().
2023-02-08 02:54:56 +08:00

733 lines
17 KiB
C

/****************************************************************************
* apps/examples/nxscope/nxscope_main.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/boardctl.h>
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#ifdef CONFIG_EXAMPLES_NXSCOPE_TIMER
# include <sys/ioctl.h>
# include <fcntl.h>
# include <stdlib.h>
# include <signal.h>
# include <nuttx/timers/timer.h>
#endif
#include "logging/nxscope/nxscope.h"
/****************************************************************************
* Private Type Definition
****************************************************************************/
struct nxscope_thr_env_s
{
FAR struct nxscope_s *nxs;
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: nxscope_cb_userid
****************************************************************************/
int nxscope_cb_userid(FAR void *priv, uint8_t id, FAR uint8_t *buff)
{
UNUSED(priv);
printf("--> nxscope_cb_userid: id=%d\n", id);
return OK;
}
/****************************************************************************
* Name: nxscope_cb_start
****************************************************************************/
int nxscope_cb_start(FAR void *priv, bool start)
{
UNUSED(priv);
printf("--> nxscope_cb_start: start=%d\n", start);
return OK;
}
#ifdef CONFIG_EXAMPLES_NXSCOPE_TIMER
/****************************************************************************
* Name: nxscope_timer_init
****************************************************************************/
static int nxscope_timer_init(void)
{
int fd = 0;
int ret = 0;
struct timer_notify_s notify;
/* Open the timer driver */
fd = open(CONFIG_EXAMPLES_NXSCOPE_TIMER_PATH, O_RDONLY);
if (fd < 0)
{
printf("ERROR: Failed to open %s: %d\n",
CONFIG_EXAMPLES_NXSCOPE_TIMER_PATH, errno);
goto errout;
}
/* Set the timer interval */
ret = ioctl(fd, TCIOC_SETTIMEOUT,
CONFIG_EXAMPLES_NXSCOPE_TIMER_INTERVAL);
if (ret < 0)
{
printf("ERROR: Failed to set the timer interval: %d\n", errno);
goto errout;
}
/* Configure the timer notifier */
notify.pid = getpid();
notify.periodic = true;
notify.event.sigev_notify = SIGEV_SIGNAL;
notify.event.sigev_signo = CONFIG_EXAMPLES_NXSCOPE_TIMER_SIGNO;
notify.event.sigev_value.sival_ptr = NULL;
ret = ioctl(fd, TCIOC_NOTIFICATION,
(unsigned long)((uintptr_t)&notify));
if (ret < 0)
{
printf("ERROR: Failed to set the timer handler: %d\n", errno);
goto errout;
}
/* Start the timer */
ret = ioctl(fd, TCIOC_START, 0);
if (ret < 0)
{
printf("ERROR: Failed to start the timer: %d\n", errno);
goto errout;
}
errout:
return fd;
}
/****************************************************************************
* Name: nxscope_timer_deinit
****************************************************************************/
static void nxscope_timer_deinit(int fd)
{
int ret = 0;
/* Stop the timer */
ret = ioctl(fd, TCIOC_STOP, 0);
if (ret < 0)
{
printf("ERROR: Failed to stop the timer: %d\n", errno);
}
close(fd);
}
#endif
/****************************************************************************
* Name: nxscope_samples_thr
****************************************************************************/
static FAR void *nxscope_samples_thr(FAR void *arg)
{
FAR struct nxscope_thr_env_s *envp = arg;
FAR uint8_t *ptr = NULL;
uint32_t i = 0;
float v[3];
#ifdef CONFIG_EXAMPLES_NXSCOPE_TIMER
int fd_timer = 0;
int ret = OK;
sigset_t set;
#endif
DEBUGASSERT(envp);
printf("nxscope_samples_thr\n");
#ifdef CONFIG_EXAMPLES_NXSCOPE_TIMER
/* Initialize timer for periodic signal. */
ret = nxscope_timer_init();
if (ret < 0)
{
printf("ERROR: nxscope_timer_init() failed: %d\n", errno);
goto errout;
}
/* Configure the signal set for this thread */
sigemptyset(&set);
sigaddset(&set, CONFIG_EXAMPLES_NXSCOPE_TIMER_SIGNO);
#endif
/* Initialize float vector */
v[0] = -1.0f;
v[1] = 0.0f;
v[2] = 1.0f;
while (1)
{
/* Channel 0 */
nxscope_put_uint8(envp->nxs, 0, i);
/* Channel 1 */
nxscope_put_int8(envp->nxs, 1, -1);
/* Channel 2 */
nxscope_put_uint16(envp->nxs, 2, 300);
/* Channel 3 */
nxscope_put_int16(envp->nxs, 3, -300);
/* Channel 4 */
nxscope_put_uint32(envp->nxs, 4, 35000);
/* Channel 5 */
nxscope_put_int32(envp->nxs, 5, -35000);
/* Channel 6 */
nxscope_put_uint64(envp->nxs, 6, 4294967296);
/* Channel 7 */
nxscope_put_int64(envp->nxs, 7, -4294967296);
/* Channel 8 */
nxscope_put_float(envp->nxs, 8, 1.0f);
/* Channel 9 */
nxscope_put_double(envp->nxs, 9, 1.11111111);
/* Channel 10 */
nxscope_put_ub8(envp->nxs, 10, ftob8(1.0f));
/* Channel 11 */
nxscope_put_b8(envp->nxs, 11, ftob8(-1.0f));
/* Channel 12 */
nxscope_put_ub16(envp->nxs, 12, ftob16(1.0f));
/* Channel 13 */
nxscope_put_b16(envp->nxs, 13, ftob16(-1.0f));
#ifdef CONFIG_HAVE_LONG_LONG
/* Channel 14 */
nxscope_put_ub32(envp->nxs, 14, dtob32(1.0));
/* Channel 15 */
nxscope_put_b32(envp->nxs, 15, dtob32(-1.0));
#endif
/* Channel 16 */
nxscope_put_vfloat(envp->nxs, 16, v, 3);
/* Channel 17 */
ptr = (FAR uint8_t *) &i;
nxscope_put_vfloat_m(envp->nxs, 17, v, 3, ptr, sizeof(uint32_t));
/* Channel 18 */
nxscope_put_none_m(envp->nxs, 18, ptr, sizeof(uint32_t));
i += 1;
#ifdef CONFIG_EXAMPLES_NXSCOPE_TIMER
ret = sigwaitinfo(&set, NULL);
if (ret < 0)
{
printf("ERROR: sigwaitinfo() failed: %d\n", errno);
goto errout;
}
#else
usleep(100);
#endif
}
#ifdef CONFIG_EXAMPLES_NXSCOPE_TIMER
errout:
/* Deinit timer */
nxscope_timer_deinit(fd_timer);
#endif
return NULL;
}
/****************************************************************************
* Name: nxscope_charlog_thr
****************************************************************************/
static FAR void *nxscope_charlog_thr(FAR void *arg)
{
FAR struct nxscope_thr_env_s *envp = arg;
int i = 0;
DEBUGASSERT(envp);
printf("nxscope_charlog_thr\n");
while (1)
{
/* Channel 19 - send hello with metadata */
nxscope_put_vchar_m(envp->nxs, 19, "hello", 64,
(FAR uint8_t *)&i, sizeof(int));
i += 1;
usleep(100000);
}
return NULL;
}
#ifdef CONFIG_LOGGING_NXSCOPE_CRICHANNELS
/****************************************************************************
* Name: nxscope_crichan_thr
****************************************************************************/
static FAR void *nxscope_crichan_thr(FAR void *arg)
{
FAR struct nxscope_thr_env_s *envp = arg;
uint8_t i = 0;
DEBUGASSERT(envp);
printf("nxscope_crichan_thr\n");
while (1)
{
/* Channel 20 */
nxscope_put_uint8(envp->nxs, 20, i);
i += 1;
usleep(100000);
}
return NULL;
}
#endif
#ifdef CONFIG_EXAMPLES_NXSCOPE_CDCACM
/****************************************************************************
* Name: nxscope_cdcacm_init
****************************************************************************/
static int nxscope_cdcacm_init(void)
{
struct boardioc_usbdev_ctrl_s ctrl;
FAR void *handle;
int ret = OK;
ctrl.usbdev = BOARDIOC_USBDEV_CDCACM;
ctrl.action = BOARDIOC_USBDEV_CONNECT;
ctrl.instance = 0;
ctrl.handle = &handle;
ret = boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);
if (ret < 0)
{
printf("ERROR: BOARDIOC_USBDEV_CONTROL failed %d\n", ret);
goto errout;
}
errout:
return ret;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nxscope_main
****************************************************************************/
int main(int argc, FAR char *argv[])
{
struct nxscope_s nxs;
int ret = OK;
pthread_t thread;
struct nxscope_thr_env_s env;
struct nxscope_cfg_s nxs_cfg;
union nxscope_chinfo_type_u u;
struct nxscope_intf_s intf;
struct nxscope_proto_s proto;
struct nxscope_callbacks_s cbs;
#ifdef CONFIG_LOGGING_NXSCOPE_INTF_SERIAL
struct nxscope_ser_cfg_s nxs_ser_cfg;
#endif
#ifdef CONFIG_LOGGING_NXSCOPE_INTF_DUMMY
struct nxscope_dummy_cfg_s nxs_dummy_cfg;
#endif
#ifndef CONFIG_NSH_ARCHINIT
/* Perform architecture-specific initialization (if configured) */
boardctl(BOARDIOC_INIT, 0);
# ifdef CONFIG_BOARDCTL_FINALINIT
/* Perform architecture-specific final-initialization (if configured) */
boardctl(BOARDIOC_FINALINIT, 0);
# endif
#endif
#ifdef CONFIG_EXAMPLES_NXSCOPE_CDCACM
/* Initialize the USB CDCACM device */
ret = nxscope_cdcacm_init();
if (ret < 0)
{
printf("ERROR: nxscope_cdcacm_init failed %d\n", ret);
goto errout_noproto;
}
#endif
/* Default serial protocol */
ret = nxscope_proto_ser_init(&proto, NULL);
if (ret < 0)
{
printf("ERROR: nxscope_proto_ser_init failed %d\n", ret);
goto errout_noproto;
}
#ifdef CONFIG_LOGGING_NXSCOPE_INTF_SERIAL
/* Configuration */
nxs_ser_cfg.path = CONFIG_EXAMPLES_NXSCOPE_SERIAL_PATH;
nxs_ser_cfg.nonblock = true;
nxs_ser_cfg.baud = CONFIG_EXAMPLES_NXSCOPE_SERIAL_BAUD;
/* Initialize serial interface */
ret = nxscope_ser_init(&intf, &nxs_ser_cfg);
if (ret < 0)
{
printf("ERROR: nxscope_ser_init failed %d\n", ret);
goto errout_nointf;
}
#endif
#ifdef CONFIG_LOGGING_NXSCOPE_INTF_DUMMY
/* Configuration */
nxs_dummy_cfg.res = 0;
/* Initialize dummy interface */
ret = nxscope_dummy_init(&intf, &nxs_dummy_cfg);
if (ret < 0)
{
printf("ERROR: nxscope_dummy_init failed %d\n", ret);
goto errout_nointf;
}
#endif
/* Connect callbacks */
cbs.userid_priv = NULL;
cbs.userid = nxscope_cb_userid;
cbs.start_priv = NULL;
cbs.start = nxscope_cb_start;
/* Initialize nxscope */
nxs_cfg.intf_cmd = &intf;
nxs_cfg.intf_stream = &intf;
nxs_cfg.proto_cmd = &proto;
nxs_cfg.proto_stream = &proto;
nxs_cfg.callbacks = &cbs;
nxs_cfg.channels = 32;
nxs_cfg.streambuf_len = CONFIG_EXAMPLES_NXSCOPE_STREAMBUF_LEN;
nxs_cfg.rxbuf_len = CONFIG_EXAMPLES_NXSCOPE_RXBUF_LEN;
#ifdef CONFIG_LOGGING_NXSCOPE_CRICHANNELS
nxs_cfg.cribuf_len = CONFIG_EXAMPLES_NXSCOPE_CRIBUF_LEN;
#endif
nxs_cfg.rx_padding = CONFIG_EXAMPLES_NXSCOPE_RX_PADDING;
ret = nxscope_init(&nxs, &nxs_cfg);
if (ret < 0)
{
printf("ERROR: nxscope_init failed %d\n", ret);
goto errout_nonxscope;
}
/* Create channels */
/* Point data channels */
u.s.dtype = NXSCOPE_TYPE_UINT8;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 0, "chan0", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_INT8;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 1, "chan1", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_UINT16;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 2, "chan2", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_INT16;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 3, "chan3", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_UINT32;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 4, "chan4", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_INT32;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 5, "chan5", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_UINT64;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 6, "chan6", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_INT64;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 7, "chan7", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_FLOAT;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 8, "chan8", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_DOUBLE;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 9, "chan9", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_UB8;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 10, "chan10", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_B8;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 11, "chan11", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_UB16;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 12, "chan12", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_B16;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 13, "chan13", u.u8, 1, 0);
#ifdef CONFIG_HAVE_LONG_LONG
u.s.dtype = NXSCOPE_TYPE_UB32;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 14, "chan14", u.u8, 1, 0);
u.s.dtype = NXSCOPE_TYPE_B32;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 15, "chan15", u.u8, 1, 0);
#endif
/* Vector data channel */
u.s.dtype = NXSCOPE_TYPE_FLOAT;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 16, "chan16", u.u8, 3, 0);
/* Vector data channel with metadata */
u.s.dtype = NXSCOPE_TYPE_FLOAT;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 17, "chan17", u.u8, 3, 4);
/* No-data channel with metadata */
u.s.dtype = NXSCOPE_TYPE_NONE;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 18, "chan18", u.u8, 0, 4);
/* Char channel with metadata */
u.s.dtype = NXSCOPE_TYPE_CHAR;
u.s._res = 0;
u.s.cri = 0;
nxscope_chan_init(&nxs, 19, "chan19", u.u8, 64, 4);
#ifdef CONFIG_LOGGING_NXSCOPE_CRICHANNELS
/* Critical channel */
u.s.dtype = NXSCOPE_TYPE_UINT8;
u.s._res = 0;
u.s.cri = 1;
nxscope_chan_init(&nxs, 20, "chan20c", u.u8, 1, 0);
#endif
/* Channels 20-31: reserved for future use */
/* Create samples thread */
env.nxs = &nxs;
ret = pthread_create(&thread, NULL, nxscope_samples_thr, &env);
if (ret != OK)
{
printf("ERROR: pthread_create failed %d\n", ret);
goto errout;
}
/* Create char log thread */
env.nxs = &nxs;
ret = pthread_create(&thread, NULL, nxscope_charlog_thr, &env);
if (ret != OK)
{
printf("ERROR: pthread_create failed %d\n", ret);
goto errout;
}
#ifdef CONFIG_LOGGING_NXSCOPE_CRICHANNELS
/* Create critical channel thread */
env.nxs = &nxs;
ret = pthread_create(&thread, NULL, nxscope_crichan_thr, &env);
if (ret != OK)
{
printf("ERROR: pthread_create failed %d\n", ret);
goto errout;
}
#endif
#ifdef CONFIG_EXAMPLES_NXSCOPE_FORCE_ENABLE
/* Enable channels and enable stream */
nxscope_chan_all_en(&nxs, true);
nxscope_stream_start(&nxs, true);
#endif
/* Main loop */
while (1)
{
/* Flush stream data */
ret = nxscope_stream(&nxs);
if (ret < 0)
{
printf("ERROR: nxscope_stream failed %d\n", ret);
}
/* Handle recv data */
ret = nxscope_recv(&nxs);
if (ret < 0)
{
printf("ERROR: nxscope_recv failed %d\n", ret);
}
usleep(100000);
}
errout:
/* Deinit nxscope */
nxscope_deinit(&nxs);
errout_nonxscope:
/* Deinit interface */
#if defined(CONFIG_LOGGING_NXSCOPE_INTF_SERIAL)
nxscope_ser_deinit(&intf);
#endif
#if defined(CONFIG_LOGGING_NXSCOPE_INTF_DUMMY)
nxscope_dummy_deinit(&intf);
#endif
errout_nointf:
/* Deinit protocol */
#if defined(CONFIG_LOGGING_NXSCOPE_PROTO_SER)
nxscope_proto_ser_deinit(&proto);
#endif
errout_noproto:
return 0;
}