From d43c52cf037e91d41327fb307204ad58e7c46f12 Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Thu, 18 Jan 2018 12:30:43 +0900 Subject: [PATCH 01/40] arch/arm/src/lc823450: Assign I2S IRQ handling to CPU0 Previous commit assumed that the caller is running on CPU0. However, the caller sometimes runs at CPU1. This patch will assign the caller to CPU0 explicitly. Signed-off-by: Masayuki Ishikawa --- arch/arm/src/lc823450/lc823450_i2s.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm/src/lc823450/lc823450_i2s.c b/arch/arm/src/lc823450/lc823450_i2s.c index 3eced5cb4f2..fb9efa28df1 100644 --- a/arch/arm/src/lc823450/lc823450_i2s.c +++ b/arch/arm/src/lc823450/lc823450_i2s.c @@ -51,6 +51,10 @@ #include #include +#ifdef CONFIG_SMP +# include +#endif + #include "up_arch.h" #include "lc823450_dma.h" #include "lc823450_i2s.h" @@ -460,8 +464,32 @@ FAR struct i2s_dev_s *lc823450_i2sdev_initialize(void) nxsem_init(&_sem_txdma, 0, 0); nxsem_init(&_sem_buf_under, 0, 0); +#ifdef CONFIG_SMP + cpu_set_t cpuset0; + cpu_set_t cpuset1; + + CPU_ZERO(&cpuset1); + CPU_SET(0, &cpuset1); + + /* Backup the current affinity */ + + sched_getaffinity(getpid(), sizeof(cpuset0), &cpuset0); + + /* Set the new affinity which assigns to CPU0 */ + + sched_setaffinity(getpid(), sizeof(cpuset1), &cpuset1); + nxsig_usleep(10 * 1000); +#endif + irq_attach(LC823450_IRQ_AUDIOBUF0, _i2s_isr, NULL); +#ifdef CONFIG_SMP + /* Restore the original affinity */ + + sched_setaffinity(getpid(), sizeof(cpuset0), &cpuset0); + nxsig_usleep(10 * 1000); +#endif + /* Enable IRQ for Audio Buffer */ up_enable_irq(LC823450_IRQ_AUDIOBUF0); From a3ed16dd302ac4a32eff9e233765c342d7a056a0 Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Thu, 18 Jan 2018 12:48:07 +0900 Subject: [PATCH 02/40] arch/arm/src/lc823450: Change irqwarn() to ASSERT() in up_ack_irq() Signed-off-by: Masayuki Ishikawa --- arch/arm/src/lc823450/lc823450_irq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/src/lc823450/lc823450_irq.c b/arch/arm/src/lc823450/lc823450_irq.c index 9339f7cd632..bd159ef545e 100644 --- a/arch/arm/src/lc823450/lc823450_irq.c +++ b/arch/arm/src/lc823450/lc823450_irq.c @@ -711,7 +711,9 @@ void up_ack_irq(int irq) #ifdef CONFIG_SMP if (irq > LC823450_IRQ_LPDSP0 && 1 == up_cpu_index()) { - irqwarn("*** warning irq(%d) handled on CPU1."); + /* IRQ should be handled on CPU0 */ + + ASSERT(false); } #endif From 0fa630d29d81314554fe691b5ec3da54f7e3bdf3 Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Thu, 18 Jan 2018 12:49:46 +0900 Subject: [PATCH 03/40] configs/lc823450-xgevk: Update README.txt and defconfigs Update comments on SMP in README.txt Enable SYSTEM_TIME64 in defconfigs. Enable INSTRUMENTATION in rndis configuration. Signed-off-by: Masayuki Ishikawa --- configs/lc823450-xgevk/README.txt | 30 +++++++++++++++++++++----- configs/lc823450-xgevk/audio/defconfig | 1 + configs/lc823450-xgevk/nsh/defconfig | 1 + configs/lc823450-xgevk/rndis/defconfig | 4 ++++ configs/lc823450-xgevk/usb/defconfig | 1 + 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/configs/lc823450-xgevk/README.txt b/configs/lc823450-xgevk/README.txt index 63db6a0a308..a152c893e1f 100644 --- a/configs/lc823450-xgevk/README.txt +++ b/configs/lc823450-xgevk/README.txt @@ -45,13 +45,33 @@ to set MSP (main stack pointer) as follows. SMP related Status ^^^^^^^^^^^^^^^^^^ -Currently all applications except for ostest work in SMP mode but might stop -due to deadlocks or ASSERT(). - CPU activities are shown at D9 (CPU0) and D10 (CPU1) respectively. -1. "nsh> smp" works but the result will be corrupted. -2. "nsh> ostest" works but might cause a deadlock or assertion. +Currently all applications except for ostest work in SMP mode but might stop +due to deadlocks or ASSERT(). For a workaround, please try + +$ cd apps; git diff +diff --git a/examples/ostest/waitpid.c b/examples/ostest/waitpid.c +index 687f50ca..8418eff8 100644 +--- a/examples/ostest/waitpid.c ++++ b/examples/ostest/waitpid.c +@@ -54,7 +54,7 @@ + ****************************************************************************/ + + #define RETURN_STATUS 14 +-#define NCHILDREN 3 ++#define NCHILDREN 2 + #define PRIORITY 100 + + /**************************************************************************** + +If other deadlocks or ASSERT() still happen, please try the following. + +$ cd nuttx; git revert e238c8b0904988b966c3b33e7df2ba3faba52e2b + +This will revert the changes for clock_systimer() for 64bit so that it can +use spinlock to protect the internal data. We think that there still exist +race conditions somewhere in SMP logic but the revert might relax the conditions. Other Status ^^^^^^^^^^^^ diff --git a/configs/lc823450-xgevk/audio/defconfig b/configs/lc823450-xgevk/audio/defconfig index ae8ef0ad376..e06f30abc50 100644 --- a/configs/lc823450-xgevk/audio/defconfig +++ b/configs/lc823450-xgevk/audio/defconfig @@ -127,6 +127,7 @@ CONFIG_START_MONTH=10 CONFIG_START_YEAR=2013 CONFIG_SYSTEM_I2CTOOL=y CONFIG_SYSTEM_NXPLAYER=y +CONFIG_SYSTEM_TIME64=y CONFIG_SYSTEM_USBMSC_CMD_STACKSIZE=2048 CONFIG_SYSTEM_USBMSC_DEVPATH1="/dev/mtdblock0p10" CONFIG_SYSTEM_USBMSC_DEVPATH2="/dev/mtdblock1" diff --git a/configs/lc823450-xgevk/nsh/defconfig b/configs/lc823450-xgevk/nsh/defconfig index 74040a67398..91b32fbe49b 100644 --- a/configs/lc823450-xgevk/nsh/defconfig +++ b/configs/lc823450-xgevk/nsh/defconfig @@ -124,6 +124,7 @@ CONFIG_START_DAY=3 CONFIG_START_MONTH=10 CONFIG_START_YEAR=2013 CONFIG_SYSTEM_I2CTOOL=y +CONFIG_SYSTEM_TIME64=y CONFIG_TASK_NAME_SIZE=24 CONFIG_UART0_RXBUFSIZE=512 CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/configs/lc823450-xgevk/rndis/defconfig b/configs/lc823450-xgevk/rndis/defconfig index c07e826ca66..32a899edd9d 100644 --- a/configs/lc823450-xgevk/rndis/defconfig +++ b/configs/lc823450-xgevk/rndis/defconfig @@ -150,6 +150,9 @@ CONFIG_SCHED_HAVE_PARENT=y CONFIG_SCHED_HPWORKPERIOD=50000 CONFIG_SCHED_HPWORKPRIORITY=192 CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_INSTRUMENTATION_BUFFER=y +CONFIG_SCHED_INSTRUMENTATION_PREEMPTION=y +CONFIG_SCHED_INSTRUMENTATION=y CONFIG_SCHED_LPWORK=y CONFIG_SCHED_ONEXIT_MAX=32 CONFIG_SCHED_ONEXIT=y @@ -169,6 +172,7 @@ CONFIG_START_YEAR=2013 CONFIG_SYSTEM_I2CTOOL=y CONFIG_SYSTEM_NXPLAYER=y CONFIG_SYSTEM_PING=y +CONFIG_SYSTEM_TIME64=y CONFIG_TASK_NAME_SIZE=24 CONFIG_TELNET_CHARACTER_MODE=y CONFIG_UART0_RXBUFSIZE=512 diff --git a/configs/lc823450-xgevk/usb/defconfig b/configs/lc823450-xgevk/usb/defconfig index 4b680dbd510..3ca1889d1bf 100644 --- a/configs/lc823450-xgevk/usb/defconfig +++ b/configs/lc823450-xgevk/usb/defconfig @@ -126,6 +126,7 @@ CONFIG_START_DAY=3 CONFIG_START_MONTH=10 CONFIG_START_YEAR=2013 CONFIG_SYSTEM_I2CTOOL=y +CONFIG_SYSTEM_TIME64=y CONFIG_SYSTEM_USBMSC_CMD_STACKSIZE=2048 CONFIG_SYSTEM_USBMSC_DEVPATH1="/dev/mtdblock0p10" CONFIG_SYSTEM_USBMSC_DEVPATH2="/dev/mtdblock1" From 1ec8a6f34cc89444e7c41bf0310ecdb30b43e074 Mon Sep 17 00:00:00 2001 From: Matt Thompson Date: Thu, 18 Jan 2018 12:33:41 +0000 Subject: [PATCH 04/40] Merged in extent3d/nuttx (pull request #575) SAMDL: SPI must be disabled before changing the mode bits in CTRLA register * SAMD External Interrupt Controller (EIC) support * removed comment * SAMDL: SPI must be disabled before changing the mode bits in CTRLA register Approved-by: Gregory Nutt --- arch/arm/src/samdl/sam_spi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/src/samdl/sam_spi.c b/arch/arm/src/samdl/sam_spi.c index 0596d9e84c3..dbecb7e09bb 100644 --- a/arch/arm/src/samdl/sam_spi.c +++ b/arch/arm/src/samdl/sam_spi.c @@ -944,7 +944,12 @@ static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode) { /* Yes... Set the mode appropriately */ + /* First we need to disable SPI while we change the mode */ + regval = spi_getreg32(priv, SAM_SPI_CTRLA_OFFSET); + spi_putreg32(priv, regval & ~SPI_CTRLA_ENABLE, SAM_SPI_CTRLA_OFFSET); + spi_wait_synchronization(priv); + regval &= ~(SPI_CTRLA_CPOL | SPI_CTRLA_CPHA); switch (mode) @@ -969,7 +974,7 @@ static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode) return; } - spi_putreg32(priv, regval, SAM_SPI_CTRLA_OFFSET); + spi_putreg32(priv, regval | SPI_CTRLA_ENABLE, SAM_SPI_CTRLA_OFFSET); /* Save the mode so that subsequent re-configurations will be faster */ From ce7df1f961d218e824b88f98f8b9b96a63efed63 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 18 Jan 2018 06:57:13 -0600 Subject: [PATCH 05/40] configst/stm3240g-eval: Remove only bogus logic to start the NX server. That was there only to support the knxwm configuration and was implemented priorit to boardctl(BOARCIOC_NX_START). --- configs/lpcxpresso-lpc54628/README.txt | 1 - configs/stm3240g-eval/src/stm32_boot.c | 111 +--------------------- configs/stm3240g-eval/src/stm32_bringup.c | 22 ++--- configs/stm32f429i-disco/src/stm32_boot.c | 37 -------- 4 files changed, 10 insertions(+), 161 deletions(-) diff --git a/configs/lpcxpresso-lpc54628/README.txt b/configs/lpcxpresso-lpc54628/README.txt index 2cb8625a859..e7b195ef41f 100644 --- a/configs/lpcxpresso-lpc54628/README.txt +++ b/configs/lpcxpresso-lpc54628/README.txt @@ -475,4 +475,3 @@ Configurations $ cd ~//nuttx $ make - diff --git a/configs/stm3240g-eval/src/stm32_boot.c b/configs/stm3240g-eval/src/stm32_boot.c index 2309fc50bba..2861a30b1d3 100644 --- a/configs/stm3240g-eval/src/stm32_boot.c +++ b/configs/stm3240g-eval/src/stm32_boot.c @@ -45,108 +45,10 @@ #include "stm3240g-eval.h" -/************************************************************************************ - * Pre-processor Definitions - ************************************************************************************/ -/* Configuration ********************************************************************/ -/* Should we initialize the NX server using nx_start? This is done for NxWidgets - * (CONFIG_NXWIDGETS=y) and if the NxWidget::CNxServer class expects the RTOS do the - * the NX initialization (CONFIG_NXWIDGET_SERVERINIT=n). This combination of - * settings is normally only used in the kernel build mode* (CONFIG_BUILD_PROTECTED) - * when NxWidgets is unable to initialize NX from user-space. - */ - -#undef HAVE_NXSTART - -#if defined(CONFIG_NXWIDGETS) && !defined(CONFIG_NXWIDGET_SERVERINIT) -# define HAVE_NXSTART -# include -#endif - -/* Should we initialize the touchscreen for the NxWM (CONFIG_NXWM=y)? This - * is done if we have a touchscreen (CONFIG_INPUT_STMPE811=y) and NxWM uses the - * touchscreen (CONFIG_NXWM_TOUCHSCREEN=y). - */ - -#undef HAVE_TCINIT - -#if defined(CONFIG_NXWM_TOUCHSCREEN) -# if !defined(CONFIG_NXWM_TOUCHSCREEN_DEVNO) -# error CONFIG_NXWM_TOUCHSCREEN_DEVNO is not defined -# elif defined(CONFIG_INPUT_STMPE811) -# define HAVE_TCINIT 1 -# include -# else -# error CONFIG_INPUT_STMPE811=y is needed -# endif -#endif - -/* Check if we will need to support the initialization kernel thread */ - -#undef HAVE_INITTHREAD - -#ifdef CONFIG_BOARD_INITIALIZE -# if defined(CONFIG_NSH_LIBRARY) && !defined(CONFIG_LIB_BOARDCTL) -# define HAVE_INITTHREAD 1 -# elif defined(HAVE_NXSTART) -# define HAVE_INITTHREAD 1 -# elif defined(HAVE_TCINIT) -# define HAVE_INITTHREAD 1 -# endif -#endif - -#ifdef HAVE_INITTHREAD -# include -# include -# include -# ifndef CONFIG_STM3240G_BOARDINIT_PRIO -# define CONFIG_STM3240G_BOARDINIT_PRIO 196 -# endif -# ifndef CONFIG_STM3240G_BOARDINIT_STACK -# define CONFIG_STM3240G_BOARDINIT_STACK 2048 -# endif -#endif - /************************************************************************************ * Private Functions ************************************************************************************/ -/************************************************************************************ - * Name: board_initthread - * - * Description: - * Board initialization kernel thread. This thread exists to support - * initialization when CONFIG_BOARD_INITIALIZE is defined. It is started by - * board_initialize() which runs on the IDLE thread. - * - * This function thread exists because some initialization steps may require - * waiting for events. Such waiting is not possible on the IDLE thread. - * - * Input Parameters: - * Standard task start-up parameters (none of which are used) - * - * Returned Value: - * Always returns EXIT_SUCCESS. - * - ************************************************************************************/ - -#ifdef HAVE_INITTHREAD -static int board_initthread(int argc, char *argv[]) -{ - int ret; - - /* Perform the board initialization on an initialization thread */ - - ret = stm32_bringup(); - if (ret < 0) - { - gerr("ERROR: stm32_bringup failed: %d\n", ret); - } - - return EXIT_SUCCESS; -} -#endif - /************************************************************************************ * Public Functions ************************************************************************************/ @@ -184,7 +86,7 @@ void stm32_boardinitialize(void) /* Initialize USB if the 1) OTG FS controller is in the configuration and 2) * disabled, and 3) the weak function stm32_usbinitialize() has been brought * the weak function stm32_usbinitialize() has been brought into the build. - * Presumeably either CONFIG_USBDEV or CONFIG_USBHOST is also selected. + * Presumably either CONFIG_USBDEV or CONFIG_USBHOST is also selected. */ if (stm32_usbinitialize) @@ -216,22 +118,11 @@ void stm32_boardinitialize(void) #ifdef CONFIG_BOARD_INITIALIZE void board_initialize(void) { -#ifdef HAVE_INITTHREAD - pid_t server; - - /* Start the board initialization kernel thread */ - - server = kthread_create("Board Init", CONFIG_STM3240G_BOARDINIT_PRIO, - CONFIG_STM3240G_BOARDINIT_STACK, board_initthread, - NULL); - ASSERT(server > 0); -#else /* Perform the board initialization on the start-up thread. Some * initializations may fail in this case due to the limited capability of * the start-up thread. */ (void)stm32_bringup(); -#endif } #endif diff --git a/configs/stm3240g-eval/src/stm32_bringup.c b/configs/stm3240g-eval/src/stm32_bringup.c index 61d3f4a69c9..7f78ccb8f30 100644 --- a/configs/stm3240g-eval/src/stm32_bringup.c +++ b/configs/stm3240g-eval/src/stm32_bringup.c @@ -71,6 +71,10 @@ # include #endif +#ifdef CONFIG_INPUT_STMPE811 +# include +#endif + #include "stm32.h" #include "stm32_i2c.h" #include "stm3240g-eval.h" @@ -354,20 +358,12 @@ int stm32_bringup(void) } #endif -#ifdef HAVE_NXSTART - /* Initialize the NX server */ +#ifdef CONFIG_INPUT_STMPE811 + /* Initialize the touchscreen. + * WARNING: stm32_tsc_setup() cannot be called from the IDLE thread. + */ - ret = nx_start(); - if (ret < 0) - { - syslog(LOG_ERR, "ERROR: nx_start failed: %d\n", ret); - } -#endif - -#ifdef HAVE_TCINIT - /* Initialize the touchscreen */ - - ret = stm32_tsc_setup(CONFIG_NXWM_TOUCHSCREEN_DEVNO); + ret = stm32_tsc_setup(0); if (ret < 0) { syslog(LOG_ERR, "ERROR: stm32_tsc_setup failed: %d\n", ret); diff --git a/configs/stm32f429i-disco/src/stm32_boot.c b/configs/stm32f429i-disco/src/stm32_boot.c index 9dda08d1de8..d76f3122fac 100644 --- a/configs/stm32f429i-disco/src/stm32_boot.c +++ b/configs/stm32f429i-disco/src/stm32_boot.c @@ -48,43 +48,6 @@ #include "stm32f429i-disco.h" #include "stm32_ccm.h" -/************************************************************************************ - * Pre-processor Definitions - ************************************************************************************/ - -/* Configuration ********************************************************************/ -/* Should we initialize the NX server using nx_start? This is done for NxWidgets - * (CONFIG_NXWIDGETS=y) and if the NxWidget::CNxServer class expects the RTOS do the - * the NX initialization (CONFIG_NXWIDGET_SERVERINIT=n). This combination of - * settings is normally only used in the kernel build mode* (CONFIG_BUILD_PROTECTED) - * when NxWidgets is unable to initialize NX from user-space. - */ - -#undef HAVE_NXSTART - -#if defined(CONFIG_NXWIDGETS) && !defined(CONFIG_NXWIDGET_SERVERINIT) -# define HAVE_NXSTART -# include -#endif - -/* Should we initialize the touchscreen for the NxWM (CONFIG_NXWM=y)? This - * is done if we have a touchscreen (CONFIG_INPUT_STMPE811=y) and NxWM uses the - * touchscreen (CONFIG_NXWM_TOUCHSCREEN=y). - */ - -#undef HAVE_TCINIT - -#if defined(CONFIG_NXWM_TOUCHSCREEN) -# if !defined(CONFIG_NXWM_TOUCHSCREEN_DEVNO) -# error CONFIG_NXWM_TOUCHSCREEN_DEVNO is not defined -# elif defined(CONFIG_INPUT_STMPE811) -# define HAVE_TCINIT -# include -# else -# error CONFIG_INPUT_STMPE811=y is needed -# endif -#endif - /************************************************************************************ * Public Functions ************************************************************************************/ From 3fb0a50036ef30f826e198222d00d0cdfda012f7 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 18 Jan 2018 09:59:31 -0600 Subject: [PATCH 06/40] drivers/input/ft5x06.c: Remove cool logic to disable polling when there there is no client waiting for read data. That was a great idea to save CPU cycles when there is nothing reading from the touchscrren but, unfortunately, does not work with readers that open the driver in non-blocking mode. So I think we just have to eat the CPUs even when there is nothing waiting for touchscreen input. --- drivers/input/ft5x06.c | 40 ++++++---------------------------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/drivers/input/ft5x06.c b/drivers/input/ft5x06.c index 25bd5f15514..de23742fba8 100644 --- a/drivers/input/ft5x06.c +++ b/drivers/input/ft5x06.c @@ -364,15 +364,9 @@ static void ft5x06_data_worker(FAR void *arg) } #ifdef CONFIG_FT5X06_POLLMODE - /* Exit, re-starting the poll (unless there is no longer any task waiting - * for touch data). - */ + /* Exit, re-starting the poll. */ - if (priv->nwaiters > 0) - { - (void)wd_start(priv->polltimer, priv->delay, ft5x06_poll_timeout, 1, - priv); - } + (void)wd_start(priv->polltimer, priv->delay, ft5x06_poll_timeout, 1, priv); #else /* Exit, re-enabling FT5x06 interrupts */ @@ -398,14 +392,11 @@ static void ft5x06_poll_timeout(int argc, wdparm_t arg1, ...) * required to protected the work queue. */ - if (priv->nwaiters > 0) + DEBUGASSERT(priv->work.worker == NULL); + ret = work_queue(HPWORK, &priv->work, ft5x06_data_worker, priv, 0); + if (ret != 0) { - DEBUGASSERT(priv->work.worker == NULL); - ret = work_queue(HPWORK, &priv->work, ft5x06_data_worker, priv, 0); - if (ret != 0) - { - ierr("ERROR: Failed to queue work: %d\n", ret); - } + ierr("ERROR: Failed to queue work: %d\n", ret); } } #endif @@ -682,25 +673,6 @@ static ssize_t ft5x06_waitsample(FAR struct ft5x06_dev_s *priv, priv->nwaiters++; -#ifdef CONFIG_FT5X06_POLLMODE - /* The poll timer is stopped when there are no waiters. So we may - * need to restart with at the maximum rate. - */ - - if (priv->nwaiters == 1) - { - priv->delay = POLL_MINDELAY; - - ret = wd_start(priv->polltimer, priv->delay, ft5x06_poll_timeout, - 1, priv); - if (ret < 0) - { - ierr("ERROR: nxsem_wait failed: %d\n", ret); - goto errout; - } - } -#endif - /* Wait for a change in the FT5x06 state */ ret = nxsem_wait(&priv->waitsem); From c0a343a6f0d5a84a1dc27bba51c7bdcbebe50faf Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 18 Jan 2018 10:00:27 -0600 Subject: [PATCH 07/40] configs/lpcxpresso-lpc54628/lvgl: Add LittlevGL graphics demo configuration. --- configs/lpcxpresso-lpc54628/README.txt | 21 +++++++ configs/lpcxpresso-lpc54628/lvgl/defconfig | 71 ++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 configs/lpcxpresso-lpc54628/lvgl/defconfig diff --git a/configs/lpcxpresso-lpc54628/README.txt b/configs/lpcxpresso-lpc54628/README.txt index e7b195ef41f..ff1597cc4a8 100644 --- a/configs/lpcxpresso-lpc54628/README.txt +++ b/configs/lpcxpresso-lpc54628/README.txt @@ -229,6 +229,27 @@ Configurations interrupts are not supported on P4. So polled mode only for this puppy. + lvgl + ---- + This is a demonstration of the LittlevGL graphics library running on + the NuttX frame buffer driver (as in the fb configuration). You can + find LittlevGL here: + + https://littlevgl.com/ + https://github.com/littlevgl + + This configuration uses the LittlevGL demonstration at apps/examples/lvgldemo. + + NOTES: + + 1. The LittlevGL demonstration is quit large, due mostly to some large + graphic images. So memory is tight in the LPC54628's 512Kb FLASH. In + fact, if you disable optimization, the demo will not fit into FLASH + memory (at least not with debug output also enabled). + + A longer term solution might load the large images into the abundant + SDRAM at runtime instead of linking it statically in FLASH. + netnsh: ------ This is a special version of the NuttShell (nsh) configuration that is diff --git a/configs/lpcxpresso-lpc54628/lvgl/defconfig b/configs/lpcxpresso-lpc54628/lvgl/defconfig new file mode 100644 index 00000000000..69faf20696f --- /dev/null +++ b/configs/lpcxpresso-lpc54628/lvgl/defconfig @@ -0,0 +1,71 @@ +# CONFIG_ARCH_FPU is not set +# CONFIG_LV_FONT_ANTIALIAS is not set +CONFIG_ARCH_BOARD_LPCXPRESSO_LPC54628=y +CONFIG_ARCH_BOARD="lpcxpresso-lpc54628" +CONFIG_ARCH_CHIP_LPC54628=y +CONFIG_ARCH_CHIP_LPC54XX=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_STDARG_H=y +CONFIG_ARCH="arm" +CONFIG_BOARD_LOOPSPERMSEC=21082 +CONFIG_BUILTIN=y +CONFIG_DRIVERS_VIDEO=y +CONFIG_EXAMPLES_LVGLDEMO=y +CONFIG_FS_PROCFS=y +CONFIG_FT5X06_POLLMODE=y +CONFIG_FT5X06_SINGLEPOINT=y +CONFIG_FT5X06_SWAPXY=y +CONFIG_GRAPHICS_LVGL=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_HOST_WINDOWS=y +CONFIG_INPUT_FT5X06=y +CONFIG_INPUT=y +CONFIG_INTELHEX_BINARY=y +CONFIG_LIB_BOARDCTL=y +CONFIG_LPC54_EMC_DYNAMIC_CS0_OFFSET=0x00080000 +CONFIG_LPC54_EMC_DYNAMIC_CS0_SIZE=0x00f80000 +CONFIG_LPC54_EMC_DYNAMIC_CS0=y +CONFIG_LPC54_EMC=y +CONFIG_LPC54_GPIOIRQ=y +CONFIG_LPC54_I2C2_MASTER=y +CONFIG_LPC54_LCD_BGR=y +CONFIG_LPC54_LCD_BPP16_565=y +CONFIG_LPC54_LCD_HBACKPORCH=43 +CONFIG_LPC54_LCD_HFRONTPORCH=8 +CONFIG_LPC54_LCD_VBACKPORCH=12 +CONFIG_LPC54_LCD_VFRONTPORCH=4 +CONFIG_LPC54_LCD_VPULSE=10 +CONFIG_LPC54_LCD_VRAMBASE=0xa0000000 +CONFIG_LPC54_LCD=y +CONFIG_LPC54_USART0=y +CONFIG_LV_HOR_RES=480 +CONFIG_LV_VER_RES=272 +CONFIG_MAX_TASKS=16 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_MM_REGIONS=2 +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=4 +CONFIG_RAM_SIZE=163840 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_TASK_NAME_SIZE=32 +CONFIG_USART0_SERIAL_CONSOLE=y +CONFIG_USE_LV_FONT_DEJAVU_40_CYRILLIC=y +CONFIG_USE_LV_FONT_DEJAVU_40_LATIN_EXT_A=y +CONFIG_USE_LV_FONT_DEJAVU_40_LATIN_EXT_B=y +CONFIG_USE_LV_FONT_DEJAVU_40_SUP=y +CONFIG_USE_LV_FONT_SYMBOL_40_BASIC=y +CONFIG_USE_LV_FONT_SYMBOL_40_FEEDBACK=y +CONFIG_USE_LV_FONT_SYMBOL_40_FILE=y +CONFIG_USER_ENTRYPOINT="lvgldemo_main" +CONFIG_VIDEO_FB=y +CONFIG_WDOG_INTRESERVE=0 From ff8cdcc89f1762fd471f1dccb65c542521361a5b Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 18 Jan 2018 11:14:54 -0600 Subject: [PATCH 08/40] configs/lpcxpresso-lpc54628: Update README --- configs/lpcxpresso-lpc54628/README.txt | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/configs/lpcxpresso-lpc54628/README.txt b/configs/lpcxpresso-lpc54628/README.txt index ff1597cc4a8..c9b3cbb5248 100644 --- a/configs/lpcxpresso-lpc54628/README.txt +++ b/configs/lpcxpresso-lpc54628/README.txt @@ -95,10 +95,12 @@ STATUS more testing is certainly needed. 2018-01-14: The basic SPI driver is code complete but still untested. It is "basic" in the sense that it supports only polled mode (no DMA). + 2018-01-18: Added the lvgl configuration. See notes under "Configuration + Sub-directories" for additional status. - There is still no support for the Accelerometer, SPIFI, or USB. There are - complete but not-yet-functional SD card and SPI drivers. There are no - on-board devices to support SPI testing. + There is still no support for the Accelerometer, SPIFI, or USB. There is + a complete but not-yet-functional SD card driver and and tested SPI + driver. There are no on-board devices to support SPI testing. Configurations ============== @@ -156,7 +158,7 @@ Configurations System Type -> Toolchain: CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIW=y : GNU ARM EABI toolchain - Configuration sub-directories + Configuration Sub-directories ----------------------------- fb: @@ -250,6 +252,18 @@ Configurations A longer term solution might load the large images into the abundant SDRAM at runtime instead of linking it statically in FLASH. + STATUS: + + 2018-01-18: The demo is basically function but has some issues: + + a) The font is too big on the "Write" screen. They don't fit in on + the keyboard. + b) The "List" display is filled with a big box that says "Click a + button to copy its text to Text area." There are no buttons and + nothing to click on (maybe they are behind the big box?). This + may also be a font size issue. + c) The "Chart" display looks okay. + netnsh: ------ This is a special version of the NuttShell (nsh) configuration that is From 9417bfde0ee3aff79d8e8413c3221e66e4f6c8bf Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 18 Jan 2018 12:51:07 -0600 Subject: [PATCH 09/40] include/termios.h: Update comments; fix long lines. --- include/termios.h | 70 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/include/termios.h b/include/termios.h index 8427cbf5991..10e88d7e000 100644 --- a/include/termios.h +++ b/include/termios.h @@ -58,7 +58,8 @@ #define INLCR (1 << 5) /* Bit 5: Map NL to CR on input */ #define INPCK (1 << 6) /* Bit 6: Enable input parity check */ #define ISTRIP (1 << 7) /* Bit 7: Strip character */ -#define IUCLC (1 << 8) /* Bit 8: Map upper-case to lower-case on input (LEGACY) */ +#define IUCLC (1 << 8) /* Bit 8: Map upper-case to lower-case on input + * (LEGACY) */ #define IXANY (1 << 9) /* Bit 9: Enable any character to restart output */ #define IXOFF (1 << 10) /* Bit 10: Enable start/stop input control */ #define IXON (1 << 11) /* Bit 11: Enable start/stop output control */ @@ -67,7 +68,8 @@ /* Terminal output modes (c_oflag in the termios structure) */ #define OPOST (1 << 0) /* Bit 0: Post-process output */ -#define OLCUC (1 << 1) /* Bit 1: Map lower-case to upper-case on output (LEGACY) */ +#define OLCUC (1 << 1) /* Bit 1: Map lower-case to upper-case on +* * output (LEGACY) */ #define ONLCR (1 << 2) /* Bit 2: Map NL to CR-NL on output */ #define OCRNL (1 << 3) /* Bit 3: Map CR to NL on output */ #define ONOCR (1 << 4) /* Bit 4: No CR output at column 0 */ @@ -116,22 +118,47 @@ /* Local Modes (c_lflag in the termios structure) */ #define ECHO (1 << 0) /* Bit 0: Enable echo */ -#define ECHOE (1 << 1) /* Bit 1: Echo erase character as error-correcting backspace */ +#define ECHOE (1 << 1) /* Bit 1: Echo erase character as error- + * correcting backspace */ #define ECHOK (1 << 2) /* Bit 2: Echo KILL */ #define ECHONL (1 << 3) /* Bit 3: Echo NL */ -#define ICANON (1 << 4) /* Bit 4: Canonical input (erase and kill processing) */ -#define IEXTEN (1 << 5) /* Bit 5: Enable extended input character processing */ +#define ICANON (1 << 4) /* Bit 4: Canonical input (erase and kill + * processing) */ +#define IEXTEN (1 << 5) /* Bit 5: Enable extended input character + * processing */ #define ISIG (1 << 6) /* Bit 6: Enable signals */ #define NOFLSH (1 << 7) /* Bit 7: Disable flush after interrupt or quit */ #define TOSTOP (1 << 8) /* Bit 8: Send SIGTTOU for background output */ -#define XCASE (1 << 9) /* Bit 9: Canonical upper/lower presentation (LEGACY) */ +#define XCASE (1 << 9) /* Bit 9: Canonical upper/lower presentation + * (LEGACY) */ -/* The following are subscript names for the termios c_cc array */ +/* The following are subscript names for the termios c_cc array. + * + * Common characters: VINTR, VQUIT, VSTART, VSTOP, VSUSP + * + * VINTR: Interrupt character (Default ETX, Control-C) + * VQUIT: Quit character (Default FS, Control-\) + * VSTART: Start character (Default DC1, Control-Q) + * VSTOP: Stop character (Default DC3, Control-S) + * VSUSP: Suspend character (Default SUB, Control-Z) + * + * Canonical mode: Adds VEOF, VEOL, VERASE, VKILL + * + * VEOL: End-of-file character (Default SUB, Control-Z) + * VEOF: End-of-line character (Default NUL) + * VERASE: Erase character (Default DEL or BS, Control-H) + * VKILL: Kill character (Default NAK or BS, Control-U) + * + * Non-canonical mode: Adds VMIN, VTIME + * + * VMIN: Minimum number of characters for non-canonical read + * VTIME: Timeout in deciseconds for non-canonical read + */ #define VEOF 0 /* Bit 0: EOF character (canonical mode) */ -#define VMIN VEOF /* Bit 0: MIN value (Non-canonical mode) */ +#define VMIN VEOF /* Bit 0: MIN value (non-canonical mode) */ #define VEOL 1 /* Bit 1: EOL character (canonical mode) */ -#define VTIME VEOL /* Bit 1: TIME value (Non-canonical mode) */ +#define VTIME VEOL /* Bit 1: TIME value (non-canonical mode) */ #define VERASE 2 /* Bit 2: ERASE character (canonical mode) */ #define VINTR 3 /* Bit 3: INTR character */ #define VKILL 4 /* Bit 4: KILL character (canonical mode) */ @@ -139,11 +166,13 @@ #define VSTART 6 /* Bit 6: START character */ #define VSTOP 7 /* Bit 7: STOP character */ #define VSUSP 8 /* Bit 8: SUSP character */ -#define NCCS 9 /* Bit 9: Size of the array c_cc for control characters */ +#define NCCS 9 /* Bit 9: Size of the array c_cc for control + * characters */ -/* Baud Rate Selection. These are instances of type speed_t. Values of 38400 - * and below are specified by POSIX; values above 38400 are sometimes referred - * to as extended values and most values appear in most termios.h implementations. +/* Baud Rate Selection. These are instances of type speed_t. Values of + * 38400 and below are specified by POSIX; values above 38400 are sometimes + * referred to as extended values and most values appear in most termios.h + * implementations. * * NOTE that is NuttX that the encoding of the speed_t values is simply the * value of the baud itself. So this opens a window for non-portable abuse @@ -188,18 +217,23 @@ #define TCSANOW 0 /* Change attributes immediately */ #define TCSADRAIN 1 /* Change attributes when output has drained */ -#define TCSAFLUSH 2 /* Change attributes when output has drained; also flush pending input */ +#define TCSAFLUSH 2 /* Change attributes when output has drained; + * also flush pending input */ /* Line Control (used with tcflush()) */ -#define TCIFLUSH 0 /* Flush pending input. Flush untransmitted output */ -#define TCIOFLUSH 1 /* Flush both pending input and untransmitted output */ +#define TCIFLUSH 0 /* Flush pending input. Flush untransmitted + * output */ +#define TCIOFLUSH 1 /* Flush both pending input and untransmitte + * output */ #define TCOFLUSH 2 /* Flush untransmitted output */ /* Constants for use with tcflow() */ -#define TCIOFF 0 /* Transmit a STOP character, intended to suspend input data */ -#define TCION 1 /* Transmit a START character, intended to restart input data */ +#define TCIOFF 0 /* Transmit a STOP character, intended to + * suspend input data */ +#define TCION 1 /* Transmit a START character, intended to + * restart input data */ #define TCOOFF 2 /* Suspend output */ #define TCOON 3 /* Restart output */ From 99b944fb6e09d7d102b8f7904b626e29ee2f2101 Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Fri, 19 Jan 2018 22:11:09 +0900 Subject: [PATCH 10/40] sched/semaphore: Add ASSERT(false) in nxsem_post() if no waiting task is found. Signed-off-by: Masayuki Ishikawa --- sched/semaphore/sem_post.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sched/semaphore/sem_post.c b/sched/semaphore/sem_post.c index 08a399b9166..a550c0aab4d 100644 --- a/sched/semaphore/sem_post.c +++ b/sched/semaphore/sem_post.c @@ -165,6 +165,12 @@ int nxsem_post(FAR sem_t *sem) up_unblock_task(stcb); } + else + { + /* This should not happen. */ + + ASSERT(false); + } } /* Check if we need to drop the priority of any threads holding From f012fe96cb3bc539c6b15dd84af08d3176cbdab3 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 19 Jan 2018 08:49:55 -0600 Subject: [PATCH 11/40] sched/sched/sched_sporadic.c: fix compiler error when priority inheritance is enabled. Noted by eunb.song@samsung.com --- sched/sched/sched_sporadic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sched/sched/sched_sporadic.c b/sched/sched/sched_sporadic.c index 666416cf7dd..dda7a355b83 100644 --- a/sched/sched/sched_sporadic.c +++ b/sched/sched/sched_sporadic.c @@ -138,7 +138,7 @@ static int sporadic_set_lowpriority(FAR struct tcb_s *tcb) * state. */ - tcb->base_priority = sporadic->low_priority; + tcb->base_priority = tcb->low_priority; } #endif @@ -194,7 +194,7 @@ static int sporadic_set_hipriority(FAR struct tcb_s *tcb) { /* Boosted... Do we still need to reprioritize? */ - if (sporadic->hi_priority < sporadic->base_priority) + if (sporadic->hi_priority < tcb->base_priority) { /* No.. the current execution priority is lower than the * boosted priority. Just reset the base priority. @@ -322,7 +322,7 @@ static int sporadic_interval_start(FAR struct replenishment_s *mrepl) /* Start the timer that will terminate the low priority cycle. This timer * expiration is independent of what else may occur (except that it must - * be cancelled if the thread exits. + * be canceled if the thread exits. */ DEBUGVERIFY(wd_start(&mrepl->timer, remainder, sporadic_interval_expire, From be3c2d1e367174e8353bd3293149ee63c5ffcb73 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 19 Jan 2018 09:07:19 -0600 Subject: [PATCH 12/40] Change ASSERT(false) to DEBUGPANIC(). --- sched/semaphore/sem_post.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sched/semaphore/sem_post.c b/sched/semaphore/sem_post.c index a550c0aab4d..f20cb68c774 100644 --- a/sched/semaphore/sem_post.c +++ b/sched/semaphore/sem_post.c @@ -169,7 +169,7 @@ int nxsem_post(FAR sem_t *sem) { /* This should not happen. */ - ASSERT(false); + DEBUGPANIC(); } } From e8e8914cabb0a2bcf069381e01e2e44d7e8f69a3 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 20 Jan 2018 07:11:33 -0600 Subject: [PATCH 13/40] Documentation: Fix copy/paste error in NX graphics document. Noted by Henjiu Kang. --- Documentation/NXGraphicsSubsystem.html | 4 ++-- configs/flipnclick-pic32mz/README.txt | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/NXGraphicsSubsystem.html b/Documentation/NXGraphicsSubsystem.html index 3a58de35fc3..efb8cbf1fe4 100644 --- a/Documentation/NXGraphicsSubsystem.html +++ b/Documentation/NXGraphicsSubsystem.html @@ -12,7 +12,7 @@

NX Graphics Subsystem

-

Last Updated: October 17, 2017

+

Last Updated: January 21, 2018

@@ -542,7 +542,7 @@ void nxgl_yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t *r, uint8_t *g, uint8

Description: - Convert 8-bit RGB triplet to 8-bit YUV triplet. + Convert 8-bit YUV triplet to 8-bit RGB triplet.

2.2.3 nxgl_rectcopy()

diff --git a/configs/flipnclick-pic32mz/README.txt b/configs/flipnclick-pic32mz/README.txt index 000cda2fcc0..3a1c3575d6d 100644 --- a/configs/flipnclick-pic32mz/README.txt +++ b/configs/flipnclick-pic32mz/README.txt @@ -46,7 +46,8 @@ On Board Debug Support There is a simple application available at Mikroe that will allow you to write .hex files via the USB HID bootloader. However, in order to use the bootloader, you will have to control the memory map so that the - downloaded code does not clobber the bootloader. + downloaded code does not clobber the bootloader code FLASH, data + memory, exception vectors, etc. At this point, I have found no documentation describing how to build the code outside of the Mikroe toolchain for use with the Mikroe From 82cc0ead67e74225b0d006762df1372b956a1642 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 20 Jan 2018 07:44:35 -0600 Subject: [PATCH 14/40] sched/sched: Fix some priority inheritance related issues noted during review of logic. Also add some REVISIT comments for some issues noted in the design. --- sched/sched/sched_sporadic.c | 55 ++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/sched/sched/sched_sporadic.c b/sched/sched/sched_sporadic.c index dda7a355b83..35984b72421 100644 --- a/sched/sched/sched_sporadic.c +++ b/sched/sched/sched_sporadic.c @@ -129,7 +129,19 @@ static int sporadic_set_lowpriority(FAR struct tcb_s *tcb) #ifdef CONFIG_PRIORITY_INHERITANCE /* If the priority was boosted above the higher priority, than just - * reset the base priority. + * reset the base priority and continue to run at the boosted priority. + * + * REVISIT: There is a logic flaw here... If the priority was NOT + * boosted above the hi_priority, then it still may still need to + * boosted with respect to the lo_priority. If the highest priority + * thread waiting on a semaphore held by the sporadic thread is greater + * than the low priority (but less than the hi_priority), the new + * sched_priority should be set to that priority, not to the lo_priority + * + * In order to do this we would need a list of all semaphores held by + * the thread. We would need to select the highest priority from among + * all tasks waiting for the semaphores. Unfortunately, at present we + * know nothing about the semaphores held by the sporadic thread. */ if (tcb->sched_priority > tcb->base_priority) @@ -140,18 +152,20 @@ static int sporadic_set_lowpriority(FAR struct tcb_s *tcb) tcb->base_priority = tcb->low_priority; } + else #endif - - /* Otherwise drop the priority of thread, possible causing a context - * switch. - */ - - ret = sched_reprioritize(tcb, sporadic->low_priority); - if (ret < 0) { - int errcode = get_errno(); - serr("ERROR: sched_reprioritize failed: %d\n", errcode); - return -errcode; + /* Otherwise drop the priority of thread, possible causing a context + * switch. + */ + + ret = sched_reprioritize(tcb, sporadic->low_priority); + if (ret < 0) + { + int errcode = get_errno(); + serr("ERROR: sched_reprioritize failed: %d\n", errcode); + return -errcode; + } } return OK; @@ -188,16 +202,27 @@ static int sporadic_set_hipriority(FAR struct tcb_s *tcb) #ifdef CONFIG_PRIORITY_INHERITANCE /* If the priority was boosted above the higher priority, than just * reset the base priority. + * + * First, was the priority boosted above the lo_priority which should be + * the same as the base_priority here? (This is an unnecessary test. + * sched_priority > hi_priority would be sufficient). */ if (tcb->sched_priority > tcb->base_priority) { - /* Boosted... Do we still need to reprioritize? */ + /* Boosted... Do we still need to reprioritize? If we were boosted to + * a priority above the hi_priority then we do not need to do anything + * except to adjust the base_priority + * + * REVISIT: This logic is probably okay. But may lead to problems + * when the hi_priority is resumed. See REVISIT comments in + * sporadic_set_lowpriority(). + */ - if (sporadic->hi_priority < tcb->base_priority) + if (tcb->sched_priority > sporadic->hi_priority) { - /* No.. the current execution priority is lower than the - * boosted priority. Just reset the base priority. + /* No.. the new execution priority is lower than the boosted + * priority. Just reset the base priority. */ tcb->base_priority = sporadic->hi_priority; From bcffeae4fd06b7e937dfc884b6e9dc8539300fe9 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 20 Jan 2018 12:59:56 -0600 Subject: [PATCH 15/40] Update README and some comments --- README.txt | 19 +++++++++++++++++++ sched/sched/sched_sporadic.c | 8 ++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/README.txt b/README.txt index 4dfd513a7f3..719fe60d177 100644 --- a/README.txt +++ b/README.txt @@ -1422,6 +1422,22 @@ Installing GNUWin32 CYGWIN BUILD PROBLEMS ^^^^^^^^^^^^^^^^^^^^^ +Performance +----------- + + Build performance under Cygwin is really not so bad, certainly not as good + as a Linux build. However, often you will find that the performance is + not just bad but terrible. If you are seeing awful performance.. like two + or three compilations per second.. the culprit is usually your Windows + Anti-Virus protection interfering with the build tool program execution. + + I use Cygwin quite often and I use Windows Defender. In order to get good + build performance, I routinely keep the Windows Defender "Virus & Threat + Protections Settings" screen up: I disable "Real-Time Protection" just + before entering 'make' then turn "Real-Time Protection" back on when the + build completes. With this additional nuisance step, I find that build + performance under Cygwin is completely acceptable. + Strange Path Problems --------------------- @@ -1475,6 +1491,7 @@ Window Native Toolchain Issues if you are using a native Windows toolchain. That bring us to #3: General Pre-built Toolchain Issues +---------------------------------- To continue with the list of "Window Native Toolchain Issues" we can add the following. These, however, are really just issues that you will have @@ -1528,6 +1545,7 @@ General Pre-built Toolchain Issues binutils and possibly different ABIs. Building Original Linux Boards in Cygwin +---------------------------------------- Some default board configurations are set to build under Linux and others to build under Windows with Cygwin. Various default toolchains may also @@ -1546,6 +1564,7 @@ Building Original Linux Boards in Cygwin ("Run As" option, right button) you find errors like "Permission denied". Recovering from Bad Configurations +---------------------------------- Many people make the mistake of configuring NuttX with the "canned" configuration and then just typing 'make' with disastrous consequences; diff --git a/sched/sched/sched_sporadic.c b/sched/sched/sched_sporadic.c index 35984b72421..90206c486e6 100644 --- a/sched/sched/sched_sporadic.c +++ b/sched/sched/sched_sporadic.c @@ -138,10 +138,10 @@ static int sporadic_set_lowpriority(FAR struct tcb_s *tcb) * than the low priority (but less than the hi_priority), the new * sched_priority should be set to that priority, not to the lo_priority * - * In order to do this we would need a list of all semaphores held by - * the thread. We would need to select the highest priority from among - * all tasks waiting for the semaphores. Unfortunately, at present we - * know nothing about the semaphores held by the sporadic thread. + * In order to do this we would need to know the highest priority from + * among all tasks waiting for the all semaphores held by the sporadic + * task. Perhaps that information could be retained by the priority + * inheritance logic for use here? */ if (tcb->sched_priority > tcb->base_priority) From d0ae325c15cdecec81666af2e4fda34eaaf88f18 Mon Sep 17 00:00:00 2001 From: Fanda Vacek Date: Sat, 20 Jan 2018 23:00:47 +0100 Subject: [PATCH 16/40] Issue #85: /dev/userleds is not working for nucleo-l432kc fixed --- configs/nucleo-l432kc/README.txt | 2 +- configs/nucleo-l432kc/include/board.h | 4 ++-- configs/nucleo-l432kc/src/nucleo-l432kc.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configs/nucleo-l432kc/README.txt b/configs/nucleo-l432kc/README.txt index 33ebc530cdb..b68e68ebbdc 100644 --- a/configs/nucleo-l432kc/README.txt +++ b/configs/nucleo-l432kc/README.txt @@ -324,7 +324,7 @@ Hardware ---- The Nucleo F401RE and Nucleo F411RE provide a single user LED, LD2. LD2 is the green LED connected to Arduino signal D13 corresponding to MCU I/O - PA5 (pin 21) or PB13 (pin 34) depending on the STM32target. + PB3 (pin 26). - When the I/O is HIGH value, the LED is on. - When the I/O is LOW, the LED is off. diff --git a/configs/nucleo-l432kc/include/board.h b/configs/nucleo-l432kc/include/board.h index dbe6dbe48fa..529accb653a 100644 --- a/configs/nucleo-l432kc/include/board.h +++ b/configs/nucleo-l432kc/include/board.h @@ -147,8 +147,8 @@ /* LEDs * * The Nucleo l476RG board provides a single user LED, LD2. LD2 - * is the green LED connected to Arduino signal D13 corresponding to MCU I/O - * PA5 (pin 21) or PB13 (pin 34) depending on the STM32 target. + * is the green LED connected to Arduino signal D13 corresponding to + * MCU I/O PB3 (pin 26). * * - When the I/O is HIGH value, the LED is on. * - When the I/O is LOW, the LED is off. diff --git a/configs/nucleo-l432kc/src/nucleo-l432kc.h b/configs/nucleo-l432kc/src/nucleo-l432kc.h index 9ce05bc83d3..e5c34816bb9 100644 --- a/configs/nucleo-l432kc/src/nucleo-l432kc.h +++ b/configs/nucleo-l432kc/src/nucleo-l432kc.h @@ -77,7 +77,7 @@ #endif /* LED. User LD2: the green LED is a user LED connected to Arduino signal D13 - * corresponding to MCU I/O PA5 (pin 21) or PB13 (pin 34) depending on the STM32 + * corresponding to MCU I/O PB3 (pin 26) * target. * * - When the I/O is HIGH value, the LED is on. @@ -85,7 +85,7 @@ */ #define GPIO_LD2 \ - (GPIO_PORTA | GPIO_PIN5 | GPIO_OUTPUT_CLEAR | GPIO_OUTPUT | GPIO_PULLUP | \ + (GPIO_PORTB | GPIO_PIN3 | GPIO_OUTPUT_CLEAR | GPIO_OUTPUT | GPIO_PULLUP | \ GPIO_SPEED_50MHz) #define LED_DRIVER_PATH "/dev/userleds" From f153df28d30733588e98122775816a9700dfecda Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 20 Jan 2018 16:16:35 -0600 Subject: [PATCH 17/40] configs/nucleo-l432kc: Fix numerous cloning errors/typos. --- TODO | 4 ++-- configs/nucleo-l432kc/README.txt | 19 ++++++++----------- configs/nucleo-l432kc/include/board.h | 4 ++-- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/TODO b/TODO index 3d92fd7ee2c..19b328e54df 100644 --- a/TODO +++ b/TODO @@ -745,7 +745,7 @@ o Kernel/Protected Build Title: USER MODE TASKS CAN MODIFY PRIVILEGED TASKS Description: Certain interfaces, such as sched_setparam(), sched_setscheduler(), etc. can be used by user mode tasks to - modify the behavior of priviledged kernel threads. + modify the behavior of privileged kernel threads. For a truly secure system. Privileges need to be checked in every interface that permits one thread to modify the properties of another thread. @@ -1282,7 +1282,7 @@ o Network (net/, drivers/net) however, because its priority is low and so it is blocked from execution. - In the mean time, the remote host sends a - packet which is presumeably caught in the read-ahead buffer. + packet which is presumably caught in the read-ahead buffer. - Then the remote host closes the socket. Nothing happens on the target side because net_start_monitor() has not yet been called. diff --git a/configs/nucleo-l432kc/README.txt b/configs/nucleo-l432kc/README.txt index b68e68ebbdc..43eacb43913 100644 --- a/configs/nucleo-l432kc/README.txt +++ b/configs/nucleo-l432kc/README.txt @@ -230,12 +230,10 @@ NuttX EABI "buildroot" Toolchain 1. You must have already configured Nuttx in /nuttx. - $ (cd tools; ./configure.sh nucleo-f4x1re/f401-nsh) + $ tools/configure.sh nucleo-f432kc/nsh $ make qconfig $ V=1 make context all 2>&1 | tee mout - Use the f411-nsh configuration if you have the Nucleo-F411RE board. - 2. Download the latest buildroot package into 3. unpack the buildroot tarball. The resulting directory may @@ -298,14 +296,13 @@ NXFLAT Toolchain mbed ==== - The Nucleo-F401RE includes boot loader from mbed: + The Nucleo-F432KC includes boot loader from mbed: - https://mbed.org/platforms/ST-Nucleo-F401RE/ https://mbed.org/handbook/Homepage Using the mbed loader: - 1. Connect the Nucleo-F4x1RE to the host PC using the USB connector. + 1. Connect the Nucleo-F432kc to the host PC using the USB connector. 2. A new file system will appear called NUCLEO; open it with Windows Explorer (assuming that you are using Windows). 3. Drag and drop nuttx.bin into the MBED window. This will load the @@ -322,7 +319,7 @@ Hardware LEDs ---- - The Nucleo F401RE and Nucleo F411RE provide a single user LED, LD2. LD2 + The Nucleo F401RE and Nucleo F432KC provide a single user LED, LD2. LD2 is the green LED connected to Arduino signal D13 corresponding to MCU I/O PB3 (pin 26). @@ -367,7 +364,7 @@ Serial Consoles TTL to RS-232 converter connection: - Nucleo CN10 STM32F4x1RE + Nucleo CN10 STM32F432KC ----------- ------------ Pin 21 PA9 USART1_RX *Warning you make need to reverse RX/TX on Pin 33 PA10 USART1_TX some RS-232 converters @@ -399,7 +396,7 @@ Serial Consoles TTL to RS-232 converter connection: - Nucleo CN9 STM32F4x1RE + Nucleo CN9 STM32F432KC ----------- ------------ Pin 1 PA3 USART2_RX *Warning you make need to reverse RX/TX on Pin 2 PA2 USART2_TX some RS-232 converters @@ -457,7 +454,7 @@ Configurations nsh: --------- Configures the NuttShell (nsh) located at apps/examples/nsh for the - Nucleo-F401RE board. The Configuration enables the serial interfaces + Nucleo-F432KC board. The Configuration enables the serial interfaces on UART2. Support for builtin applications is enabled, but in the base configuration no builtin applications are selected (see NOTES below). @@ -484,7 +481,7 @@ Configurations Consoles). I have been using a TTL-to-RS-232 converter connected as shown below: - Nucleo CN10 STM32F4x1RE + Nucleo CN10 STM32F432KC ----------- ------------ Pin 21 PA9 USART1_RX *Warning you make need to reverse RX/TX on Pin 33 PA10 USART1_TX some RS-232 converters diff --git a/configs/nucleo-l432kc/include/board.h b/configs/nucleo-l432kc/include/board.h index 529accb653a..3e7e90c4537 100644 --- a/configs/nucleo-l432kc/include/board.h +++ b/configs/nucleo-l432kc/include/board.h @@ -146,7 +146,7 @@ /* LEDs * - * The Nucleo l476RG board provides a single user LED, LD2. LD2 + * The Nucleo l432kc board provides a single user LED, LD2. LD2 * is the green LED connected to Arduino signal D13 corresponding to * MCU I/O PB3 (pin 26). * @@ -266,4 +266,4 @@ void stm32l4_board_initialize(void); #endif #endif /* __ASSEMBLY__ */ -#endif /* __CONFIGS_NUCLEO_F476RG_INCLUDE_BOARD_H */ +#endif /* __CONFIGS_NUCLEO_F432KC_INCLUDE_BOARD_H */ From 0c034c8dd34f8111d7d24e2bc967c9c69f404b3f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 21 Jan 2018 07:47:13 -0600 Subject: [PATCH 18/40] Update TODO list --- TODO | 81 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/TODO b/TODO index 19b328e54df..4d46a3e5b0b 100644 --- a/TODO +++ b/TODO @@ -1,15 +1,15 @@ -NuttX TODO List (Last updated January 3, 2018) +NuttX TODO List (Last updated January 21, 2018) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with standards, things that could be improved, and ideas for enhancements. This -TODO list does not include issues associated with individual boar ports. See +TODO list does not include issues associated with individual board ports. See also the individual README.txt files in the configs/ sub-directories for issues related to each board port. nuttx/: - (12) Task/Scheduler (sched/) + (14) Task/Scheduler (sched/) (1) SMP (1) Memory Management (mm/) (0) Power Management (drivers/pm) @@ -47,7 +47,7 @@ o Task/Scheduler (sched/) Status: Closed. No, this behavior will not be implemented. Priority: Medium, required for good emulation of process/pthread model. The current behavior allows for the main thread of a task to - exit() and any child pthreads will perist. That does raise + exit() and any child pthreads will persist. That does raise some issues: The main thread is treated much like just-another- pthread but must follow the semantics of a task or a process. That results in some inconsistencies (for example, with robust @@ -124,7 +124,7 @@ o Task/Scheduler (sched/) The fix for all of these issues it to have the callbacks run on the caller's thread as is currently done with signal handlers. Signals are delivered differently in - PROTECTED and KERNEL modes: The deliver is involes a + PROTECTED and KERNEL modes: The delivery involves a signal handling trampoline function in the user address space and two signal handlers: One to call the signal handler trampoline in user mode (SYS_signal_handler) and @@ -198,7 +198,7 @@ o Task/Scheduler (sched/) Description: The internal NuttX logic uses the same interfaces as does the application. That sometime produces a problem because there is "overloaded" functionality in those user interfaces - that are not desireable. + that are not desirable. For example, having cancellation points hidden inside of the OS can cause non-cancellation point interfaces to behave @@ -327,6 +327,59 @@ o Task/Scheduler (sched/) Status: Open Priority: Low, only needed for more complete debug. + Title: PRIORITY INHERITANCE WITH SPORADIC SCHEDULER + Description: The sporadic scheduler manages CPU utilization by a task by + alternating between a high and a low priority. In either + state, it may have its priority boosted. However, under + some circumstances, it is impossible in the current design to + switch to the correct correct priority if a semaphore is + participating in priority inheritance: + + There is an when switching from the high to the low priority + state. If the priority was NOT boosted above the higher + priority, it still may still need to boosted with respect to + the lower priority. If the highest priority thread waiting + on a semaphore held by the sporadic thread is higher in + priority than the low priority but less than the higher + priority, then new thread priority should be set to that + middle priority, not to the lower priority + + In order to do this we would need to know the highest + priority from among all tasks waiting for the all semaphores + held by the sporadic task. That information could be + retained by the priority inheritance logic for use by the + sporadic scheduler. The boost priority could be retained in + a new field of the TCB (say, pend_priority). That + pend_priority could then be used when switching from the + higher to the lower priority. + Status: Open + Priority: Low. Does anyone actually use the sporadic scheduler? + + Title: SIMPLIFY SPORADIC SCHEDULER DESIGN + Description: I have been planning to re-implement sporadic scheduling for + some time. I believe that the current implementation is + unnecessarily complex. There is no clear statement for the + requirements of sporadic scheduling that I could find, so I + based the design on some behaviors of another OS that I saw + published (QNX as I recall). + + But I think that the bottom line requirement for sporadic + scheduling is that is it should make a best attempt to + control a fixed percentage of CPU bandwidth for a task in + during an interval only by modifying it is priority between + a low and a high priority. The current design involves + several timers: A "budget" timer plus a variable number of + "replenishment" timers and a lot of nonsense to duplicate QNX + behavior that I think I not necessary. + + It think that the sporadic scheduler could be re-implemented + with only the single "budget" timer. Instead of starting a + new "replenishment" timer when the task is resumed, that + single timer could just be extended. + Status: Open + Priority: Low. This is an enhancement. And does anyone actually use + the sporadic scheduler? + o SMP ^^^ @@ -572,7 +625,7 @@ o pthreads (sched/pthreads) group structure. I am, however, hesitant to make this change: In the FLAT build model, there is nothing that prevents people from accessing the inter-thread controls from threads in - differnt task groups. Making this change, while correct, + different task groups. Making this change, while correct, might introduce subtle bugs in code by people who are not using NuttX correctly. Status: Open @@ -1838,7 +1891,7 @@ o File system / Generic drivers (fs/, drivers/) (using pctl() instead sysctl()). My objective was to be able to control the number of available file descriptors on a task- by-task basis. The complexity due to the partitioning of - desciptor space in a range for file descriptors and a range + descriptor space in a range for file descriptors and a range for socket descriptors made this feature nearly impossible to implement. Status: Open @@ -1920,8 +1973,8 @@ o File system / Generic drivers (fs/, drivers/) 4) When comparing the checksum in the long file name entry with the checksum of the short file name, the checksum fails and the entire directory sequence is - ignored by readder() logic. This the file does not - appear in the 'ls'. + ignored by readdir() logic. This is why the file does + not appear in the 'ls'. o Graphics Subsystem (graphics/) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -2014,7 +2067,7 @@ o Graphics Subsystem (graphics/) Title: LOW-RES FRAMEBUFFER RENDERERING Description: There are obvious issues in the low-res, < 8 BPP, implemenation of - the framebuffer rendereing logic of graphics/nxglib/fb. I see two + the framebuffer rendering logic of graphics/nxglib/fb. I see two obvious problems in reviewing nxglib_copyrectangle(): 1. The masking logic might work 1 BPP, but is insufficient for other @@ -2026,7 +2079,7 @@ o Graphics Subsystem (graphics/) derives from nxglib_copyrectangle() and all of those issues have been resolved in that file. - Other frambuffer rendering functions probably have similary issues. + Other frambuffer rendering functions probably have similar issues. Status: Open Priority: Low. It is not surprising that there would be bugs in this logic: I have never encountered a hardware framebuffer with sub-byte pixel @@ -2279,11 +2332,11 @@ o Modbus (apps/modbus) Title: MODBUS NOT USABLE WITH USB SERIAL Description: Modbus can be used with USB serial, however, if the USB - serial connectiont is lost, Modbus will hang in an infinite + serial connection is lost, Modbus will hang in an infinite loop. This is a problem in the handling of select() and read() - and could probabaly resolved by studying the Modbus error + and could probably resolved by studying the Modbus error handling. A more USB-friendly solution would be to: (1) Re-connect and From 9916ca89e6fb8dae1cc0f5c22201704ed8de96f7 Mon Sep 17 00:00:00 2001 From: Fanda Vacek Date: Sun, 21 Jan 2018 19:06:22 +0100 Subject: [PATCH 19/40] NUCLEO F432KC typo fixed, correct name is L432KC Just README.txt and comments affected, no changes in the code --- configs/nucleo-l432kc/README.txt | 16 ++++++++-------- configs/nucleo-l432kc/include/board.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/configs/nucleo-l432kc/README.txt b/configs/nucleo-l432kc/README.txt index 43eacb43913..a922e176386 100644 --- a/configs/nucleo-l432kc/README.txt +++ b/configs/nucleo-l432kc/README.txt @@ -230,7 +230,7 @@ NuttX EABI "buildroot" Toolchain 1. You must have already configured Nuttx in /nuttx. - $ tools/configure.sh nucleo-f432kc/nsh + $ tools/configure.sh nucleo-l432kc/nsh $ make qconfig $ V=1 make context all 2>&1 | tee mout @@ -296,13 +296,13 @@ NXFLAT Toolchain mbed ==== - The Nucleo-F432KC includes boot loader from mbed: + The Nucleo-L432KC includes boot loader from mbed: https://mbed.org/handbook/Homepage Using the mbed loader: - 1. Connect the Nucleo-F432kc to the host PC using the USB connector. + 1. Connect the Nucleo-L432kc to the host PC using the USB connector. 2. A new file system will appear called NUCLEO; open it with Windows Explorer (assuming that you are using Windows). 3. Drag and drop nuttx.bin into the MBED window. This will load the @@ -319,7 +319,7 @@ Hardware LEDs ---- - The Nucleo F401RE and Nucleo F432KC provide a single user LED, LD2. LD2 + The Nucleo L432KC provides a single user LED, LD2. LD2 is the green LED connected to Arduino signal D13 corresponding to MCU I/O PB3 (pin 26). @@ -364,7 +364,7 @@ Serial Consoles TTL to RS-232 converter connection: - Nucleo CN10 STM32F432KC + Nucleo CN10 STM32L432KC ----------- ------------ Pin 21 PA9 USART1_RX *Warning you make need to reverse RX/TX on Pin 33 PA10 USART1_TX some RS-232 converters @@ -396,7 +396,7 @@ Serial Consoles TTL to RS-232 converter connection: - Nucleo CN9 STM32F432KC + Nucleo CN9 STM32L432KC ----------- ------------ Pin 1 PA3 USART2_RX *Warning you make need to reverse RX/TX on Pin 2 PA2 USART2_TX some RS-232 converters @@ -454,7 +454,7 @@ Configurations nsh: --------- Configures the NuttShell (nsh) located at apps/examples/nsh for the - Nucleo-F432KC board. The Configuration enables the serial interfaces + Nucleo-L432KC board. The Configuration enables the serial interfaces on UART2. Support for builtin applications is enabled, but in the base configuration no builtin applications are selected (see NOTES below). @@ -481,7 +481,7 @@ Configurations Consoles). I have been using a TTL-to-RS-232 converter connected as shown below: - Nucleo CN10 STM32F432KC + Nucleo CN10 STM32L432KC ----------- ------------ Pin 21 PA9 USART1_RX *Warning you make need to reverse RX/TX on Pin 33 PA10 USART1_TX some RS-232 converters diff --git a/configs/nucleo-l432kc/include/board.h b/configs/nucleo-l432kc/include/board.h index 3e7e90c4537..041a755787c 100644 --- a/configs/nucleo-l432kc/include/board.h +++ b/configs/nucleo-l432kc/include/board.h @@ -266,4 +266,4 @@ void stm32l4_board_initialize(void); #endif #endif /* __ASSEMBLY__ */ -#endif /* __CONFIGS_NUCLEO_F432KC_INCLUDE_BOARD_H */ +#endif /* __CONFIGS_NUCLEO_L432KC_INCLUDE_BOARD_H */ From 5af7e3de2a43277b0de6e55affcab4253780a6f1 Mon Sep 17 00:00:00 2001 From: Mateusz Szafoni Date: Sun, 21 Jan 2018 18:28:09 +0000 Subject: [PATCH 20/40] Merged in raiden00/nuttx (pull request #579) Master * stm32_hritm: add interface to get timer clock frequency stm32_hrtim: fix timer freq calculation stm32_hrtim: add compar/capture registers significant bits checking stm32_hrtim: minor changes * stm32f334-disco: add buck converter and boost converter logic Approved-by: Gregory Nutt --- arch/arm/src/stm32/stm32_hrtim.c | 415 +++++++++++++------ arch/arm/src/stm32/stm32_hrtim.h | 38 +- configs/stm32f334-disco/include/board.h | 34 +- configs/stm32f334-disco/src/stm32_smps.c | 493 ++++++++++++++++++++--- 4 files changed, 790 insertions(+), 190 deletions(-) diff --git a/arch/arm/src/stm32/stm32_hrtim.c b/arch/arm/src/stm32/stm32_hrtim.c index 44f78bff6f6..121b0e2e4f1 100644 --- a/arch/arm/src/stm32/stm32_hrtim.c +++ b/arch/arm/src/stm32/stm32_hrtim.c @@ -375,12 +375,13 @@ struct stm32_hrtim_capture_s struct stm32_hrtim_timcmn_s { uint32_t base; /* The base adress of the timer */ - uint32_t pclk; /* The frequency of the peripheral clock + uint64_t fclk; /* The frequency of the peripheral clock * that drives the timer module. */ + uint8_t prescaler:3; /* Prescaler */ uint8_t mode; /* Timer mode */ uint8_t dac:2; /* DAC triggering */ - uint8_t reserved:6; + uint8_t reserved:3; #ifdef CONFIG_STM32_HRTIM_INTERRUPTS uint16_t irq; /* interrupts configuration */ #endif @@ -623,6 +624,8 @@ static uint32_t hrtim_tim_getreg(FAR struct stm32_hrtim_s *priv, uint8_t timer, uint32_t offset); static FAR struct stm32_hrtim_tim_s *hrtim_tim_get(FAR struct stm32_hrtim_s *priv, uint8_t timer); +static FAR struct stm32_hrtim_slave_priv_s *hrtim_slave_get(FAR struct stm32_hrtim_s *priv, + uint8_t timer); static uint32_t hrtim_base_get(FAR struct stm32_hrtim_s *priv, uint8_t timer); /* Configuration */ @@ -665,7 +668,8 @@ static int hrtim_tim_dma_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer, #ifdef CONFIG_STM32_HRTIM_DEADTIME static int hrtim_deadtime_update(FAR struct hrtim_dev_s *dev, uint8_t timer, uint8_t dt, uint16_t value); -static uint16_t hrtim_deadtime_get(FAR struct hrtim_dev_s *dev, uint8_t dt); +static uint16_t hrtim_deadtime_get(FAR struct hrtim_dev_s *dev, uint8_t timer, + uint8_t dt); static int hrtim_tim_deadtime_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer); static int hrtim_deadtime_config(FAR struct stm32_hrtim_s *priv); #endif @@ -705,6 +709,7 @@ static int hrtim_per_update(FAR struct hrtim_dev_s *dev, uint8_t timer, static uint16_t hrtim_per_get(FAR struct hrtim_dev_s *dev, uint8_t timer); static uint16_t hrtim_cmp_get(FAR struct hrtim_dev_s *dev, uint8_t timer, uint8_t index); +static uint64_t hrtim_fclk_get(FAR struct hrtim_dev_s *dev, uint8_t timer); static int hrtim_tim_reset_set(FAR struct stm32_hrtim_s *priv, uint8_t timer, uint32_t reset); static int hrtim_reset_config(FAR struct stm32_hrtim_s *priv); @@ -753,20 +758,21 @@ static struct stm32_hrtim_tim_s g_master = /* If MASTER is disabled, we need only MASTER base */ #ifdef CONFIG_STM32_HRTIM_MASTER - .pclk = HRTIM_CLOCK/(HRTIM_MASTER_PRESCALER+1), - .mode = HRTIM_MASTER_MODE, + .fclk = HRTIM_CLOCK/(1<priv; + +errout: + return slave; +} + /**************************************************************************** * Name: hrtim_base_get * @@ -2049,7 +2108,7 @@ static void hrtim_dumpregs(FAR struct stm32_hrtim_s *priv, uint8_t timer, * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -2093,7 +2152,7 @@ static int hrtim_dll_cal(FAR struct stm32_hrtim_s *priv) * timer - An HRTIM Timer index * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -2182,7 +2241,7 @@ errout: * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -2264,7 +2323,7 @@ errout: * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -2467,7 +2526,7 @@ static int hrtim_gpios_config(FAR struct stm32_hrtim_s *priv) * capture - capture trigers configuration * * Returned Value: - * None + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -2478,7 +2537,9 @@ static int hrtim_tim_capture_cfg(FAR struct stm32_hrtim_s *priv, int ret = OK; uint32_t offset = 0; - if (timer == HRTIM_TIMER_MASTER) + /* Sanity checking */ + + if (timer == HRTIM_TIMER_MASTER || timer == HRTIM_TIMER_COMMON) { ret = -EINVAL; goto errout; @@ -2521,7 +2582,7 @@ errout: * priv - A reference to the HRTIM block * * Returned Value: - * None + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -2574,7 +2635,7 @@ static int hrtim_capture_config(FAR struct stm32_hrtim_s *priv) * index - Capture register index * * Returned Value: - * None + * Timer Capture value on success, 0 on failure * ****************************************************************************/ @@ -2623,7 +2684,7 @@ errout: * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -2645,37 +2706,26 @@ static int hrtim_synch_config(FAR struct stm32_hrtim_s *priv) * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ #if defined(CONFIG_STM32_HRTIM_PWM) static int hrtim_tim_outputs_config(FAR struct stm32_hrtim_s *priv, uint8_t timer) { - FAR struct stm32_hrtim_tim_s* tim; FAR struct stm32_hrtim_slave_priv_s* slave; uint32_t regval = 0; int ret = OK; - /* Master Timer has no outputs */ + /* Get Slave Timer data structure */ - if (timer == HRTIM_TIMER_MASTER) + slave = hrtim_slave_get(priv, timer); + if (slave == NULL) { ret = -EINVAL; goto errout; } - /* Get Timer data strucutre */ - - tim = hrtim_tim_get(priv, timer); - if (tim == NULL) - { - ret = -EINVAL; - goto errout; - } - - slave = (struct stm32_hrtim_slave_priv_s*)tim->priv; - /* Configure CH1 SET events */ regval = slave->pwm.ch1.set; @@ -2773,7 +2823,7 @@ errout: * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -2848,7 +2898,7 @@ errout: * state - Enable/disable operation * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -3009,7 +3059,6 @@ static int hrtim_output_set_set(FAR struct hrtim_dev_s *dev, uint16_t output, uint32_t set) { FAR struct stm32_hrtim_s *priv = (FAR struct stm32_hrtim_s *)dev->hd_priv; - FAR struct stm32_hrtim_tim_s* tim; FAR struct stm32_hrtim_slave_priv_s* slave; uint8_t timer = 0; int ret = OK; @@ -3018,17 +3067,15 @@ static int hrtim_output_set_set(FAR struct hrtim_dev_s *dev, uint16_t output, timer = output_tim_index_get(output); - /* Get Timer data strucutre */ + /* Get Slave Timer data strucutre */ - tim = hrtim_tim_get(priv, timer); - if (tim == NULL) + slave = hrtim_slave_get(priv, timer); + if (slave == NULL) { ret = -EINVAL; goto errout; } - slave = (struct stm32_hrtim_slave_priv_s*)tim->priv; - /* Set new SET value */ switch (output_tim_ch_get(output)) @@ -3065,7 +3112,6 @@ static int hrtim_output_rst_set(FAR struct hrtim_dev_s *dev, uint16_t output, uint32_t rst) { FAR struct stm32_hrtim_s *priv = (FAR struct stm32_hrtim_s *)dev->hd_priv; - FAR struct stm32_hrtim_tim_s* tim; FAR struct stm32_hrtim_slave_priv_s* slave; uint8_t timer = 0; int ret = OK; @@ -3074,17 +3120,15 @@ static int hrtim_output_rst_set(FAR struct hrtim_dev_s *dev, uint16_t output, timer = output_tim_index_get(output); - /* Get Timer data strucutre */ + /* Get Salve Timer data strucutre */ - tim = hrtim_tim_get(priv, timer); - if (tim == NULL) + slave = hrtim_slave_get(priv, timer); + if (slave == NULL) { ret = -EINVAL; goto errout; } - slave = (struct stm32_hrtim_slave_priv_s*)tim->priv; - /* Set new RST value */ switch (output_tim_ch_get(output)) @@ -3124,7 +3168,7 @@ errout: * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -3172,7 +3216,7 @@ static int hrtim_adc_config(FAR struct stm32_hrtim_s *priv) * dac - DAC synchronisation event configuration * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -3203,7 +3247,7 @@ static int hrtim_tim_dac_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer, * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -3268,6 +3312,14 @@ static int hrtim_tim_dma_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer, int ret = OK; uint32_t regval = 0; + /* Sanity checking */ + + if (timer == HRTIM_TIMER_COMMON) + { + ret = -EINVAL; + goto errout; + } + if (timer == HRTIM_TIMER_MASTER) { /* Master support first 7 DMA requests */ @@ -3397,7 +3449,8 @@ errout: * Name: hrtim_deadtime_get ****************************************************************************/ -static uint16_t hrtim_deadtime_get(FAR struct hrtim_dev_s *dev, uint8_t dt) +static uint16_t hrtim_deadtime_get(FAR struct hrtim_dev_s *dev, uint8_t timer, + uint8_t dt) { #warning missing logic } @@ -3408,30 +3461,27 @@ static uint16_t hrtim_deadtime_get(FAR struct hrtim_dev_s *dev, uint8_t dt) static int hrtim_tim_deadtime_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer) { - FAR struct stm32_hrtim_tim_s* tim; FAR struct stm32_hrtim_slave_priv_s* slave; uint32_t regval = 0; int ret = OK; - /* Master Timer has no outputs */ + /* Sanity checking */ - if (timer == HRTIM_TIMER_MASTER) + if (timer == HRTIM_TIMER_MASTER || timer == HRTIM_TIMER_COMMON) { ret = -EINVAL; goto errout; } - /* Get Timer data strucutre */ + /* Get Slave Timer data strucutre */ - tim = hrtim_tim_get(priv, timer); - if (tim == NULL) + slave = hrtim_slave_get(priv, timer); + if (slave == NULL) { ret = -EINVAL; goto errout; } - slave = (struct stm32_hrtim_slave_priv_s*)tim->priv; - /* Configure deadtime prescaler */ regval |= slave->pwm.dt.prescaler << HRTIM_TIMDT_DTPRSC_SHIFT; @@ -3550,7 +3600,7 @@ static int hrtim_deadtime_config(FAR struct stm32_hrtim_s *priv) * state - Enable/disable operation * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -3610,31 +3660,28 @@ errout: static int hrtim_tim_chopper_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer) { - FAR struct stm32_hrtim_tim_s* tim; FAR struct stm32_hrtim_slave_priv_s* slave; int ret = OK; uint32_t regval = 0; - /* Master Timer has no outputs */ + /* Sanity checking */ - if (timer == HRTIM_TIMER_MASTER) + if (timer == HRTIM_TIMER_MASTER || timer == HRTIM_TIMER_COMMON) { ret = -EINVAL; goto errout; } - /* Get Timer data strucutre */ + /* Get Slave Timer data strucutre */ - tim = hrtim_tim_get(priv, timer); - if (tim == NULL) + slave = hrtim_slave_get(priv, timer); + if (slave == NULL) { ret = -EINVAL; goto errout; } - slave = (struct stm32_hrtim_slave_priv_s*)tim->priv; - /* Configure start pulsewidth */ regval |= slave->pwm.chp.start_pulse << HRTIM_TIMCHP_STRTPW_SHIFT; @@ -3891,19 +3938,22 @@ static int hrtim_burst_config(FAR struct stm32_hrtim_s *priv) * timer - timer index * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ static int hrtim_tim_faults_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer) { - FAR struct stm32_hrtim_tim_s *tim; FAR struct stm32_hrtim_slave_priv_s *slave; uint32_t regval = 0; + int ret = OK; - tim = hrtim_tim_get(priv, timer); - - slave = tim->priv; + slave = hrtim_slave_get(priv, timer); + if (slave == NULL) + { + ret = -EINVAL; + goto errout; + } /* Get lock configuration */ @@ -3917,7 +3967,8 @@ static int hrtim_tim_faults_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer) hrtim_tim_putreg(priv, timer, STM32_HRTIM_TIM_FLTR_OFFSET, regval); - return OK; +errout: + return ret; } /**************************************************************************** @@ -3931,7 +3982,7 @@ static int hrtim_tim_faults_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer) * index - Fault index * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -4073,7 +4124,7 @@ errout: * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -4147,7 +4198,7 @@ static int hrtim_faults_config(FAR struct stm32_hrtim_s *priv) * index - External Event index * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -4322,7 +4373,7 @@ errout: * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -4392,7 +4443,7 @@ static int hrtim_events_config(FAR struct stm32_hrtim_s *priv) * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -4483,7 +4534,7 @@ static void hrtim_tim_mode_set(FAR struct stm32_hrtim_s *priv, uint8_t timer, * priv - A reference to the HRTIM structure * * Returned Value: - * None + * None * ****************************************************************************/ @@ -4514,6 +4565,77 @@ static void hrtim_mode_config(FAR struct stm32_hrtim_s *priv) #endif } +/**************************************************************************** + * Name: hrtim_cmpcap_mask_get + * + * Description: + * This function returns not significant bits in counter/capture + * regsiters for given HRTIM Timer index. + * + * Input Parameters: + * priv - A reference to the HRTIM structure + * timer - HRTIM Timer index + * + * Returned Value: + * Not significant bits for counter/capture registers + * + ****************************************************************************/ + +static uint8_t hrtim_cmpcap_mask_get(FAR struct stm32_hrtim_s *priv, + uint8_t timer) +{ + FAR struct stm32_hrtim_tim_s* tim; + uint8_t mask = 0; + + /* Get Timer data strucutre */ + + tim = hrtim_tim_get(priv, timer); + if (tim == NULL) + { + mask = 0; + goto errout; + } + + /* Not significant bits depens on timer prescaler */ + + switch(tim->tim.prescaler) + { + case HRTIM_PRESCALER_1: + { + mask = 0b11111; + break; + } + case HRTIM_PRESCALER_2: + { + mask = 0b1111; + break; + } + case HRTIM_PRESCALER_4: + { + mask = 0b111; + break; + } + case HRTIM_PRESCALER_8: + { + mask = 0b11; + break; + } + case HRTIM_PRESCALER_16: + { + mask = 0b1; + break; + } + default: + { + mask = 0; + break; + } + } + +errout: + return mask; +} + /**************************************************************************** * Name: hrtim_cmp_update * @@ -4527,7 +4649,7 @@ static void hrtim_mode_config(FAR struct stm32_hrtim_s *priv) * cmp - New compare register value * * Returned Value: - * Zero on success; a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -4537,6 +4659,7 @@ static int hrtim_cmp_update(FAR struct hrtim_dev_s *dev, uint8_t timer, FAR struct stm32_hrtim_s *priv = (FAR struct stm32_hrtim_s *)dev->hd_priv; int ret = OK; uint32_t offset = 0; + uint8_t mask = 0; switch (index) { @@ -4571,6 +4694,16 @@ static int hrtim_cmp_update(FAR struct hrtim_dev_s *dev, uint8_t timer, } } + /* REVISIT: what should we do if cmp value is not significant ? + * At this moment we set compare register to the nearest significant value. + */ + + mask = hrtim_cmpcap_mask_get(priv, timer); + if (cmp <= mask) + { + cmp = mask + 1; + } + hrtim_tim_putreg(priv, timer, offset, cmp); errout: @@ -4589,7 +4722,7 @@ errout: * per - New period register value * * Returned Value: - * Zero on success; a negated errno value on failure + * 0 on success; a negated errno value on failure * ****************************************************************************/ @@ -4613,7 +4746,7 @@ static int hrtim_per_update(FAR struct hrtim_dev_s *dev, uint8_t timer, * timer - HRTIM Timer index * * Returned Value: - * Zero on success; a negated errno value on failure + * Timer period value * ****************************************************************************/ @@ -4636,7 +4769,7 @@ static uint16_t hrtim_per_get(FAR struct hrtim_dev_s *dev, uint8_t timer) * index - Compare register timer * * Returned Value: - * Zero on success; a negated errno value on failure + * Timer compare value * ****************************************************************************/ @@ -4686,6 +4819,42 @@ errout: return cmpx; } +/**************************************************************************** + * Name: hrtim_fclk_get + * + * Description: + * Get HRTIM Timer clock value + * + * Input parameters: + * dev - HRTIM device structure + * timer - HRTIM Timer index + * + * Returned Value: + * Timer clock value + * + ****************************************************************************/ + +static uint64_t hrtim_fclk_get(FAR struct hrtim_dev_s *dev, uint8_t timer) +{ + FAR struct stm32_hrtim_s *priv = (FAR struct stm32_hrtim_s *)dev->hd_priv; + FAR struct stm32_hrtim_tim_s *tim; + uint64_t fclk = 0; + + /* Get Slave Timer data structure */ + + tim = hrtim_tim_get(priv, timer); + if (tim == NULL) + { + fclk = 0; + goto errout; + } + + fclk = tim->tim.fclk; + +errout: + return fclk; +} + /**************************************************************************** * Name: hrtim_tim_reset_set * @@ -4707,7 +4876,9 @@ static int hrtim_tim_reset_set(FAR struct stm32_hrtim_s *priv, uint8_t timer, { int ret = OK; - if (timer == HRTIM_TIMER_MASTER) + /* Sanity checking */ + + if (timer == HRTIM_TIMER_MASTER || timer == HRTIM_TIMER_COMMON) { ret = -EINVAL; goto errout; @@ -4811,7 +4982,7 @@ static int hrtim_update_config(FAR struct stm32_hrtim_s *priv) * priv - A reference to the HRTIM structure * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ diff --git a/arch/arm/src/stm32/stm32_hrtim.h b/arch/arm/src/stm32/stm32_hrtim.h index 40ffe37b8dc..da02364460f 100644 --- a/arch/arm/src/stm32/stm32_hrtim.h +++ b/arch/arm/src/stm32/stm32_hrtim.h @@ -187,7 +187,7 @@ # error "APB2 prescaler factor can not be greater than 2" # else # define HRTIM_HAVE_CLK_FROM_PLL 1 -# define HRTIM_CLOCK 2*STM32_PLL_FREQUENCY +# define HRTIM_MAIN_CLOCK 2*STM32_PLL_FREQUENCY # endif # else # error "Clock system must be set to PLL" @@ -195,19 +195,27 @@ #else # error "Not supported yet: system freezes when no PLL selected." # define HRTIM_HAVE_CLK_FROM_APB2 1 -# if STM32_RCC_CFGR_PPRE2 == RCC_CFGR_PPRE2_HCLK -# define HRTIM_CLOCK STM32_PCLK2_FREQUENCY +# if STM32_RCC_CFGR_PPRE2 == RCC_CFGR_PPRE2_HCLK +# define HRTIM_MAIN_CLOCK STM32_PCLK2_FREQUENCY # else -# define HRTIM_CLOCK 2*STM32_PCLK2_FREQUENCY +# define HRTIM_MAIN_CLOCK 2*STM32_PCLK2_FREQUENCY # endif #endif +/* High-resolution equivalent clock */ + +#define HRTIM_CLOCK (HRTIM_MAIN_CLOCK*32ull) + /* Helpers **************************************************************************/ #define HRTIM_CMP_SET(hrtim, tim, index, cmp) \ (hrtim)->hd_ops->cmp_update(hrtim, tim, index, cmp) #define HRTIM_PER_SET(hrtim, tim, per) \ (hrtim)->hd_ops->per_update(hrtim, tim, per) +#define HRTIM_PER_GET(hrtim, tim) \ + (hrtim)->hd_ops->per_get(hrtim, tim) +#define HRTIM_FCLK_GET(hrtim, tim) \ + (hrtim)->hd_ops->fclk_get(hrtim, tim) #define HRTIM_OUTPUTS_ENABLE(hrtim, outputs, state) \ (hrtim)->hd_ops->outputs_enable(hrtim, outputs, state) #define HRTIM_OUTPUT_SET_SET(hrtim, output, set) \ @@ -225,6 +233,11 @@ #define HRTIM_DEADTIME_UPDATE(hrtim, tim, dt, val) \ (hrtim)->hd_ops->deadtime_update(hrtim, tim, dt, val) +#define HRTIM_PER_MAX 0xFFFF +#define HRTIM_CMP_MAX 0xFFFF +#define HRTIM_CPT_MAX 0xFFFF +#define HRTIM_REP_MAX 0xFF + /************************************************************************************ * Public Types ************************************************************************************/ @@ -384,14 +397,14 @@ enum stm32_hrtim_tim_rst_e enum stm32_hrtim_tim_prescaler_e { - HRTIM_PRESCALER_1, - HRTIM_PRESCALER_2, - HRTIM_PRESCALER_4, - HRTIM_PRESCALER_8, - HRTIM_PRESCALER_16, - HRTIM_PRESCALER_32, - HRTIM_PRESCALER_64, - HRTIM_PRESCALER_128 + HRTIM_PRESCALER_1, /* CKPSC = 0 */ + HRTIM_PRESCALER_2, /* CKPSC = 1 */ + HRTIM_PRESCALER_4, /* CKPSC = 2 */ + HRTIM_PRESCALER_8, /* CKPSC = 3 */ + HRTIM_PRESCALER_16, /* CKPSC = 4 */ + HRTIM_PRESCALER_32, /* CKPSC = 5 */ + HRTIM_PRESCALER_64, /* CKPSC = 6 */ + HRTIM_PRESCALER_128 /* CKPSC = 7 */ }; /* HRTIM Timer Master/Slave mode */ @@ -971,6 +984,7 @@ struct stm32_hrtim_ops_s uint16_t (*per_get)(FAR struct hrtim_dev_s *dev, uint8_t timer); uint16_t (*cmp_get)(FAR struct hrtim_dev_s *dev, uint8_t timer, uint8_t index); + uint64_t (*fclk_get)(FAR struct hrtim_dev_s *dev, uint8_t timer); #ifdef CONFIG_STM32_HRTIM_INTERRUPTS void (*irq_ack)(FAR struct hrtim_dev_s *dev, uint8_t timer, int source); #endif diff --git a/configs/stm32f334-disco/include/board.h b/configs/stm32f334-disco/include/board.h index 115b02abd48..c138e01cabf 100644 --- a/configs/stm32f334-disco/include/board.h +++ b/configs/stm32f334-disco/include/board.h @@ -277,12 +277,42 @@ /* HRTIM configuration ******************************************************/ -#define HRTIM_TIMA_PRESCALER HRTIM_PRESCALER_32 +/* Timer A configuration - Buck operations */ + +#define HRTIM_TIMA_PRESCALER HRTIM_PRESCALER_1 #define HRTIM_TIMA_MODE HRTIM_MODE_CONT -#define HRTIM_TIMB_PRESCALER HRTIM_PRESCALER_32 +#define HRTIM_TIMA_CH1_SET HRTIM_OUT_SET_NONE +#define HRTIM_TIMA_CH1_RST HRTIM_OUT_RST_NONE +#define HRTIM_TIMA_CH2_SET HRTIM_OUT_SET_NONE +#define HRTIM_TIMA_CH2_RST HRTIM_OUT_RST_NONE + +#define HRTIM_TIMA_DT_FSLOCK HRTIM_DT_LOCK +#define HRTIM_TIMA_DT_RSLOCK HRTIM_DT_LOCK +#define HRTIM_TIMA_DT_FVLOCK HRTIM_DT_RW +#define HRTIM_TIMA_DT_RVLOCK HRTIM_DT_RW +#define HRTIM_TIMA_DT_FSIGN HRTIM_DT_SIGN_POSITIVE +#define HRTIM_TIMA_DT_RSIGN HRTIM_DT_SIGN_POSITIVE +#define HRTIM_TIMA_DT_PRESCALER HRTIM_DEADTIME_PRESCALER_1 + +/* Timer B configuration - Boost operations */ + +#define HRTIM_TIMB_PRESCALER HRTIM_PRESCALER_1 #define HRTIM_TIMB_MODE HRTIM_MODE_CONT +#define HRTIM_TIMB_CH1_SET HRTIM_OUT_SET_NONE +#define HRTIM_TIMB_CH1_RST HRTIM_OUT_RST_NONE +#define HRTIM_TIMB_CH2_SET HRTIM_OUT_SET_NONE +#define HRTIM_TIMB_CH2_RST HRTIM_OUT_RST_NONE + +#define HRTIM_TIMB_DT_FSLOCK HRTIM_DT_LOCK +#define HRTIM_TIMB_DT_RSLOCK HRTIM_DT_LOCK +#define HRTIM_TIMB_DT_FVLOCK HRTIM_DT_RW +#define HRTIM_TIMB_DT_RVLOCK HRTIM_DT_RW +#define HRTIM_TIMB_DT_FSIGN HRTIM_DT_SIGN_POSITIVE +#define HRTIM_TIMB_DT_RSIGN HRTIM_DT_SIGN_POSITIVE +#define HRTIM_TIMB_DT_PRESCALER HRTIM_DEADTIME_PRESCALER_1 + #define HRTIM_ADC_TRG2 HRTIM_ADCTRG24_AC4 /* DMA channels *************************************************************/ diff --git a/configs/stm32f334-disco/src/stm32_smps.c b/configs/stm32f334-disco/src/stm32_smps.c index 952af64c1b1..b1ae43e216c 100644 --- a/configs/stm32f334-disco/src/stm32_smps.c +++ b/configs/stm32f334-disco/src/stm32_smps.c @@ -105,8 +105,8 @@ /* ADC1 injected channels numeration */ -#define VIN_ADC_INJ_CHANNEL 0 -#define VOUT_ADC_INJ_CHANNEL 1 +#define V_IN_ADC_INJ_CHANNEL 0 +#define V_OUT_ADC_INJ_CHANNEL 1 /* Voltage reference for ADC */ @@ -118,11 +118,11 @@ /* Input voltage convertion ratio - 6.8k/(6.8k + 27k) */ -#define VIN_RATIO (float)((float)(6800+27000)/(float)6800) +#define V_IN_RATIO (float)((float)(6800+27000)/(float)6800) /* Output voltage convertion ratio - 3.3k/(3.3k + 13.3k) */ -#define VOUT_RATIO (float)((float)(3300+13300)/(float)3300) +#define V_OUT_RATIO (float)((float)(3300+13300)/(float)3300) /* Some absolute limits */ @@ -130,6 +130,61 @@ #define SMPS_ABSOLUTE_OUT_VOLTAGE_LIMIT_mV 15000 #define SMPS_ABSOLUTE_IN_VOLTAGE_LIMIT_mV 15000 +#if CONFIG_EXAMPLES_SMPS_OUT_CURRENT_LIMIT > SMPS_ABSOLUTE_OUT_CURRENT_LIMIT_mA +# error "Output current limit great than absolute limit!" +#endif +#if CONFIG_EXAMPLES_SMPS_OUT_VOLTAGE_LIMIT > SMPS_ABSOLUTE_OUT_VOLTAGE_LIMIT_mV +# error "Output voltage limit greater than absolute limit!" +#endif +#if CONFIG_EXAMPLES_SMPS_IN_VOLTAGE_LIMIT > SMPS_ABSOLUTE_IN_VOLTAGE_LIMIT_mV +# error "Input voltage limit greater than absolute limit!" +#endif + +/* Maximum output voltage for boost conveter in float */ + +#define BOOST_VOLT_MAX ((float)CONFIG_EXAMPLES_SMPS_OUT_VOLTAGE_LIMIT/1000.0) + +/* Current limit table dimmension */ + +#define SMPS_CURRENT_LIMIT_TAB_DIM 15 + +/* At this time only PID controller implemented */ + +#define SMPS_CONTROLLER_PID 1 + +/* Converter's finite accuracy */ + +#define SMPS_VOLTAGE_ACCURACY ((float)0.01) + +/* Buck-boost mode threshold */ + +#define SMPS_BUCKBOOST_RANGE ((float)0.5) + +/* PID controller configuration */ + +#define PID_KP ((float)1.0) +#define PID_KI ((float)0.1) +#define PID_KD ((float)0.0) + +/* Converter frequncies: + * - TIMA_PWM_FREQ - buck converter 250kHz + * - TIMB_PWM_FREQ - boost converter 250kHz + */ + +#define TIMA_PWM_FREQ 250000 +#define TIMB_PWM_FREQ 250000 + +/* Deadtime configuration */ + +#define DT_RISING 0x0A0 +#define DT_FALLING 0x0A0 + +/* Helper macros */ + +#define HRTIM_ALL_OUTPUTS_ENABLE(hrtim, state) \ + HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMA_CH1|HRTIM_OUT_TIMA_CH2| \ + HRTIM_OUT_TIMB_CH1|HRTIM_OUT_TIMB_CH2, state); + /**************************************************************************** * Private Types ****************************************************************************/ @@ -138,6 +193,7 @@ enum converter_mode_e { + CONVERTER_MODE_INIT, /* Initial mode */ CONVERTER_MODE_BUCK, /* Buck mode operations (V_in > V_out) */ CONVERTER_MODE_BOOST, /* Boost mode operations (V_in < V_out) */ CONVERTER_MODE_BUCKBOOST, /* Buck-boost operations (V_in near V_out)*/ @@ -159,11 +215,13 @@ struct smps_lower_dev_s struct smps_priv_s { uint8_t conv_mode; /* Converter mode */ - uint16_t vin_raw; /* Voltage input RAW value */ - uint16_t vout_raw; /* Voltage output RAW value */ - float vin; /* Voltage input real value in V */ - float vout; /* Voltage output real value in V */ + uint16_t v_in_raw; /* Voltage input RAW value */ + uint16_t v_out_raw; /* Voltage output RAW value */ + float v_in; /* Voltage input real value in V */ + float v_out; /* Voltage output real value in V */ bool running; /* Running flag */ + float state[3]; /* Controller state vartiables */ + float *c_limit_tab; /* Current limit tab */ }; /**************************************************************************** @@ -215,8 +273,9 @@ struct smps_ops_s g_smps_ops = struct smps_dev_s g_smps_dev = { - .ops = &g_smps_ops, - .priv = &g_smps + .ops = &g_smps_ops, + .priv = &g_smps, + .lower = NULL }; /* ADC configuration: @@ -232,16 +291,16 @@ struct smps_dev_s g_smps_dev = * Transistors configuration in boost mode: * - T4 - ON * - T11 - OFF - * - T5 and T15 - boost operation + * - T5 and T12 - boost operation * Transistors configuration in buck-boost mode: * - T4, T11 - buck operation - * - T5 and T15 - boost operation + * - T5 and T12 - boost operation * * HRTIM outputs configuration: * - T4 -> PA8 -> HRTIM_CHA1 * - T5 -> PA11 -> HRTIM_CHB2 * - T11 -> PA9 -> HRTIM_CHA2 - * - T15 -> PA10 -> HRTIM_CHB1 + * - T12 -> PA10 -> HRTIM_CHB1 * */ @@ -257,8 +316,8 @@ static const uint8_t g_adc1chan[ADC1_NCHANNELS] = static const uint32_t g_adc1pins[ADC1_NCHANNELS] = { - GPIO_ADC1_IN2, /* PA1 - VIN */ - GPIO_ADC1_IN4, /* PA3 - VOUT */ + GPIO_ADC1_IN2, /* PA1 - V_IN */ + GPIO_ADC1_IN4, /* PA3 - V_OUT */ }; /**************************************************************************** @@ -290,7 +349,7 @@ static int smps_shutdown(FAR struct smps_dev_s *dev) * Description: * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ @@ -300,6 +359,7 @@ static int smps_setup(FAR struct smps_dev_s *dev) FAR struct smps_s *smps = (FAR struct smps_s *)dev->priv; FAR struct hrtim_dev_s *hrtim = NULL; FAR struct adc_dev_s *adc = NULL; + FAR struct smps_priv_s *priv; /* Initialize smps structure */ @@ -321,6 +381,8 @@ static int smps_setup(FAR struct smps_dev_s *dev) printf("ERROR: failed to get ADC lower level interface"); } + /* TODO: create current limit table */ + errout: return OK; } @@ -331,28 +393,89 @@ static int smps_start(FAR struct smps_dev_s *dev) FAR struct stm32_adc_dev_s *stm32_adc = (FAR struct stm32_adc_dev_s *) lower->adc->ad_priv; FAR struct smps_s *smps = (FAR struct smps_s *)dev->priv; + FAR struct smps_priv_s *priv = (struct smps_priv_s *)smps->priv; FAR struct hrtim_dev_s *hrtim = lower->hrtim; + volatile uint64_t per = 0; + uint64_t fclk = 0; + int ret = OK; - /* Stop HRTIM PWM */ + /* Disable HRTIM outputs */ - HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMA_CH1, false); - HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMA_CH2, false); + HRTIM_ALL_OUTPUTS_ENABLE(hrtim, false); - HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMB_CH1, false); - HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMB_CH2, false); + /* Reset SMPS private structure */ - /* 1 period is 4us - 100% time */ + memset(priv, 0, sizeof(struct smps_priv_s)); - HRTIM_PER_SET(hrtim, HRTIM_TIMER_TIMA, 18432); - HRTIM_PER_SET(hrtim, HRTIM_TIMER_TIMB, 18432); + /* Get TIMA period value for given frequency */ + + fclk = HRTIM_FCLK_GET(hrtim, HRTIM_TIMER_TIMA); + per = fclk/TIMA_PWM_FREQ; + if (per > HRTIM_PER_MAX) + { + printf("ERROR: can not achieve tima pwm freq=%u if fclk=%llu\n", + (uint32_t)TIMA_PWM_FREQ, (uint64_t)fclk); + ret = -EINVAL; + goto errout; + } + + /* Set TIMA period value */ + + HRTIM_PER_SET(hrtim, HRTIM_TIMER_TIMA, (uint16_t)per); + + /* Get TIMB period value for given frequency */ + + fclk = HRTIM_FCLK_GET(hrtim, HRTIM_TIMER_TIMB); + per = fclk/TIMB_PWM_FREQ; + if (per > HRTIM_PER_MAX) + { + printf("ERROR: can not achieve timb pwm freq=%u if fclk=%llu\n", + (uint32_t)TIMB_PWM_FREQ, (uint64_t)fclk); + ret = -EINVAL; + goto errout; + } + + /* Set TIMB period value */ + + HRTIM_PER_SET(hrtim, HRTIM_TIMER_TIMB, (uint16_t)per); /* ADC trigger on TIMA CMP4 */ HRTIM_CMP_SET(hrtim, HRTIM_TIMER_TIMA, HRTIM_CMP4, 10000); + /* Configure TIMER A and TIMER B deadtime mode + * + * NOTE: In deadtime mode we have to configure output 1 only (SETx1, RSTx1), + * output 2 configuration is not significant. + */ + + HRTIM_DEADTIME_UPDATE(hrtim, HRTIM_TIMER_TIMA, HRTIM_DT_EDGE_RISING, DT_RISING); + HRTIM_DEADTIME_UPDATE(hrtim, HRTIM_TIMER_TIMA, HRTIM_DT_EDGE_FALLING, DT_FALLING); + HRTIM_DEADTIME_UPDATE(hrtim, HRTIM_TIMER_TIMB, HRTIM_DT_EDGE_RISING, DT_RISING); + HRTIM_DEADTIME_UPDATE(hrtim, HRTIM_TIMER_TIMB, HRTIM_DT_EDGE_FALLING, DT_FALLING); + + /* Set T4 and T12 to a low state. + * Deadtime mode force T11 and T5 to a high state. + */ + + HRTIM_OUTPUT_SET_SET(hrtim, HRTIM_OUT_TIMA_CH1, HRTIM_OUT_SET_NONE); + HRTIM_OUTPUT_RST_SET(hrtim, HRTIM_OUT_TIMA_CH1, HRTIM_OUT_RST_PER); + + HRTIM_OUTPUT_SET_SET(hrtim, HRTIM_OUT_TIMB_CH1, HRTIM_OUT_SET_NONE); + HRTIM_OUTPUT_RST_SET(hrtim, HRTIM_OUT_TIMB_CH1, HRTIM_OUT_RST_PER); + + /* Set running flag */ + + priv->running = true; + + HRTIM_ALL_OUTPUTS_ENABLE(hrtim, true); + /* Enable ADC interrupts */ stm32_adc->ops->int_en(stm32_adc, ADC_INT_JEOS); + +errout: + return ret; } static int smps_stop(FAR struct smps_dev_s *dev) @@ -366,11 +489,7 @@ static int smps_stop(FAR struct smps_dev_s *dev) /* Disable HRTIM outputs */ - HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMA_CH1, false); - HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMA_CH2, false); - - HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMB_CH1, false); - HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMB_CH2, false); + HRTIM_ALL_OUTPUTS_ENABLE(hrtim, false); /* Disable ADC interrupts */ @@ -459,27 +578,27 @@ static int smps_limits_set(FAR struct smps_dev_s *dev, goto errout; } - if (limits->v_out * 1000 > SMPS_ABSOLUTE_OUT_VOLTAGE_LIMIT_mV) + if (limits->v_out * 1000 > CONFIG_EXAMPLES_SMPS_OUT_VOLTAGE_LIMIT) { - limits->v_out = (float)SMPS_ABSOLUTE_OUT_VOLTAGE_LIMIT_mV/1000.0; + limits->v_out = (float)CONFIG_EXAMPLES_SMPS_OUT_VOLTAGE_LIMIT/1000.0; printf("SMPS output voltage limiit > SMPS absoulute output voltage limit." - " Set output voltage limit to %d.\n", + " Set output voltage limit to %.2f.\n", limits->v_out); } - if (limits->v_in * 1000 > SMPS_ABSOLUTE_IN_VOLTAGE_LIMIT_mV) + if (limits->v_in * 1000 > CONFIG_EXAMPLES_SMPS_IN_VOLTAGE_LIMIT) { - limits->v_in = (float)SMPS_ABSOLUTE_IN_VOLTAGE_LIMIT_mV/1000.0; + limits->v_in = (float)CONFIG_EXAMPLES_SMPS_IN_VOLTAGE_LIMIT/1000.0; printf("SMPS input voltage limiit > SMPS absoulute input voltage limit." - " Set input voltage limit to %d.\n", + " Set input voltage limit to %.2f.\n", limits->v_in); } - if (limits->i_out * 1000 > SMPS_ABSOLUTE_OUT_CURRENT_LIMIT_mA) + if (limits->i_out * 1000 > CONFIG_EXAMPLES_SMPS_OUT_CURRENT_LIMIT) { - limits->i_out = (float)SMPS_ABSOLUTE_OUT_CURRENT_LIMIT_mA/1000.0; + limits->i_out = (float)CONFIG_EXAMPLES_SMPS_OUT_CURRENT_LIMIT/1000.0; printf("SMPS output current limiit > SMPS absoulute output current limit." - " Set output current limit to %d.\n", + " Set output current limit to %.2f.\n", limits->i_out); } @@ -510,8 +629,8 @@ static int smps_state_get(FAR struct smps_dev_s *dev, /* Copy localy stored feedbacks data to status structure */ - smps->state.fb.v_in = g_smps_priv.vin; - smps->state.fb.v_out = g_smps_priv.vout; + smps->state.fb.v_in = g_smps_priv.v_in; + smps->state.fb.v_out = g_smps_priv.v_out; /* Return state structure to caller */ @@ -544,36 +663,302 @@ static int smps_ioctl(FAR struct smps_dev_s *dev, int cmd, unsigned long arg) return OK; } +/**************************************************************************** + * Name: pid_controller + ****************************************************************************/ + +static float pid_controller(struct smps_priv_s *priv, float err) +{ + float out; + float A0 = PID_KP + PID_KD + PID_KI; + float A1 = -PID_KP - 2.0*PID_KD; + float A2 = PID_KD; + + /* Get PID controller output */ + + out = (A0 * err) + (A1 * priv->state[0]) + (A2 * priv->state[1]) + priv->state[2]; + + /* Store PID contrroller variables */ + + priv->state[1] = priv->state[0]; + priv->state[0] = err; + priv->state[2] = out; + + return out; +} + +/**************************************************************************** + * Name: smps_controller + ****************************************************************************/ + +static float smps_controller(struct smps_priv_s *priv, float err) +{ +#ifdef SMPS_CONTROLLER_PID + return pid_controller(priv, err); +#else +# error "At this time only PID controller implemented" +#endif +} + +/**************************************************************************** + * Name: smps_duty_set + ****************************************************************************/ + +static void smps_duty_set(struct smps_priv_s *priv, struct smps_lower_dev_s *lower, + float out) +{ + FAR struct hrtim_dev_s *hrtim = lower->hrtim; + uint8_t mode = priv->conv_mode; + uint16_t cmp = 0; + float duty = 0.0; + uint16_t per = 0; + + switch (mode) + { + case CONVERTER_MODE_INIT: + { + /* Do nothing */ + + break; + } + + case CONVERTER_MODE_BUCK: + { + if (out >= priv->v_in) out = priv->v_in; + if (out < 0.0) out = 0.0; + + duty = out/priv->v_in; + +#warning TODO: current limit in buck mode + + per = HRTIM_PER_GET(hrtim, HRTIM_TIMER_TIMA); + + cmp = (uint16_t)(per * duty); + + if (cmp > per-30) cmp = per - 30; + + /* Set T4 duty cycle. T11 is complementary to T4 */ + + HRTIM_CMP_SET(hrtim, HRTIM_TIMER_TIMA, HRTIM_CMP1, cmp); + + break; + } + + case CONVERTER_MODE_BOOST: + { + per = HRTIM_PER_GET(hrtim, HRTIM_TIMER_TIMA); + + + if (out < priv->v_in) out = priv->v_in; + if (out >= BOOST_VOLT_MAX) out = BOOST_VOLT_MAX; + + duty = 1.0 - priv->v_in/out; + +#warning TODO: current limit in boost mode + + cmp = (uint16_t)(per * duty); + + /* Set T12 duty cycle. T5 is complementary to T12 */ + + HRTIM_CMP_SET(hrtim, HRTIM_TIMER_TIMB, HRTIM_CMP1, cmp); + + break; + } + + case CONVERTER_MODE_BUCKBOOST: + { + /* do something */ + +#warning TODO: buck boost mode + + break; + } + + default: + { + printf("ERROR: unknown converter mode %d!\n", mode); + break; + } + } +} + +/**************************************************************************** + * Name: smps_conv_mode_set + * + * Description: + * Change converter mode (buck/boost/buck-boost). + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void smps_conv_mode_set(struct smps_priv_s *priv, struct smps_lower_dev_s *lower, + uint8_t mode) +{ + FAR struct hrtim_dev_s *hrtim = lower->hrtim; + + /* Disable all outputs */ + + HRTIM_ALL_OUTPUTS_ENABLE(hrtim, false); + + switch (mode) + { + case CONVERTER_MODE_INIT: + { + + break; + } + + case CONVERTER_MODE_BUCK: + { + /* Set T12 low (T5 high) on the next PER */ + + HRTIM_OUTPUT_SET_SET(hrtim, HRTIM_OUT_TIMB_CH1, HRTIM_OUT_SET_NONE); + HRTIM_OUTPUT_RST_SET(hrtim, HRTIM_OUT_TIMB_CH1, HRTIM_OUT_RST_PER); + + + /* Set T4 to a high state on PER and reset on CMP1. + T11 is complementary to T4. */ + + HRTIM_OUTPUT_SET_SET(hrtim, HRTIM_OUT_TIMA_CH1, HRTIM_OUT_SET_PER); + HRTIM_OUTPUT_RST_SET(hrtim, HRTIM_OUT_TIMA_CH1, HRTIM_OUT_RST_CMP1); + + break; + } + + case CONVERTER_MODE_BOOST: + { + /* Set T4 high (T11 low) on the next PER */ + + HRTIM_OUTPUT_SET_SET(hrtim, HRTIM_OUT_TIMA_CH1, HRTIM_OUT_SET_PER); + HRTIM_OUTPUT_RST_SET(hrtim, HRTIM_OUT_TIMA_CH1, HRTIM_OUT_RST_NONE); + + /* Set T12 to a high state on PER and reset on CMP1. + T5 is complementary to T12. */ + + HRTIM_OUTPUT_SET_SET(hrtim, HRTIM_OUT_TIMB_CH1, HRTIM_OUT_SET_PER); + HRTIM_OUTPUT_RST_SET(hrtim, HRTIM_OUT_TIMB_CH1, HRTIM_OUT_RST_CMP1); + + break; + } + + case CONVERTER_MODE_BUCKBOOST: + { + /* Set T4 to a high state on PER and reset on CMP1. + T11 is complementary to T4. */ + + HRTIM_OUTPUT_SET_SET(hrtim, HRTIM_OUT_TIMA_CH1, HRTIM_OUT_SET_PER); + HRTIM_OUTPUT_RST_SET(hrtim, HRTIM_OUT_TIMA_CH1, HRTIM_OUT_RST_CMP1); + + /* Set T12 to a high state on PER and reset on CMP1. + T5 is complementary to T12. */ + + HRTIM_OUTPUT_SET_SET(hrtim, HRTIM_OUT_TIMB_CH1, HRTIM_OUT_SET_PER); + HRTIM_OUTPUT_RST_SET(hrtim, HRTIM_OUT_TIMB_CH1, HRTIM_OUT_RST_CMP1); + + break; + } + + default: + { + printf("ERROR: unknown converter mode %d!\n", mode); + break; + } + } + + /* Set mode in private data */ + + priv->conv_mode = mode; + + /* Enable outputs */ + + HRTIM_ALL_OUTPUTS_ENABLE(hrtim, true); + +} + +/**************************************************************************** + * Name: adc12_handler + ****************************************************************************/ + static void adc12_handler(void) { - FAR struct smps_lower_dev_s *lower = g_smps_dev.lower; - FAR struct stm32_adc_dev_s *stm32_adc = + FAR struct smps_dev_s *dev = &g_smps_dev; + FAR struct smps_s *smps = (FAR struct smps_s *)dev->priv; + FAR struct smps_priv_s *priv = (struct smps_priv_s *)smps->priv; + FAR struct smps_lower_dev_s *lower = dev->lower; + FAR struct stm32_adc_dev_s *adc = (FAR struct stm32_adc_dev_s*)lower->adc->ad_priv; + uint32_t pending; float ref = ADC_REF_VOLTAGE; float bit = ADC_VAL_MAX; - uint32_t pending; + float err; + float out; + uint8_t mode; - pending = stm32_adc->ops->int_get(stm32_adc); + pending = adc->ops->int_get(adc); - if (pending & ADC_INT_JEOC) + if (pending & ADC_INT_JEOC && priv->running == true) { /* Get raw ADC values */ - g_smps_priv.vout_raw = stm32_adc->ops->inj_get(stm32_adc, VOUT_ADC_INJ_CHANNEL); - g_smps_priv.vin_raw = stm32_adc->ops->inj_get(stm32_adc, VIN_ADC_INJ_CHANNEL); + priv->v_out_raw = adc->ops->inj_get(adc, V_OUT_ADC_INJ_CHANNEL); + priv->v_in_raw = adc->ops->inj_get(adc, V_IN_ADC_INJ_CHANNEL); /* Convert raw values to real values */ - g_smps_priv.vout = (g_smps_priv.vout_raw * ref / bit) * VOUT_RATIO; - g_smps_priv.vin = (g_smps_priv.vin_raw * ref / bit) * VIN_RATIO; + priv->v_out = (priv->v_out_raw * ref / bit) * V_OUT_RATIO; + priv->v_in = (priv->v_in_raw * ref / bit) * V_IN_RATIO; -#warning "missing regulator logic!" + /* According to measured voltages we set converter in appropriate mode */ + if (smps->param.v_out > (priv->v_in+SMPS_BUCKBOOST_RANGE)) + { + /* Desired output voltage greather than input voltage - set boost converter */ + + mode = CONVERTER_MODE_BOOST; + } + + else if (smps->param.v_out < (priv->v_in-SMPS_BUCKBOOST_RANGE)) + { + /* Desired output voltage lower than input voltage - set buck converter */ + + mode = CONVERTER_MODE_BUCK; + } + + else + { + /* Desired output voltage close to input voltage - set buck-boost converter */ + + mode = CONVERTER_MODE_BUCKBOOST; + } + + /* Configure converter to the new mode if needed */ + + if (priv->conv_mode != mode) + { + smps_conv_mode_set(priv, lower, mode); + } + + /* Get regualtor error */ + + err = smps->param.v_out - priv->v_out; + + if (err >= SMPS_VOLTAGE_ACCURACY || err <= (-SMPS_VOLTAGE_ACCURACY)) + { + /* PID controller */ + + out = smps_controller(priv, err); + + /* Update duty cycle */ + + smps_duty_set(priv, lower, out); + } } /* Clear pending */ - stm32_adc->ops->int_ack(stm32_adc, pending); + adc->ops->int_ack(adc, pending); } /**************************************************************************** @@ -584,12 +969,12 @@ static void adc12_handler(void) * Name: stm32_smps_setup * * Description: - * Initialize SMPS driver. + * Initialize SMPS driver. * - * This function should be call by board_app_initialize(). + * This function should be call by board_app_initialize(). * * Returned Value: - * 0 on success, a negated errno value on failure + * 0 on success, a negated errno value on failure * ****************************************************************************/ From 83a87e08e8ed1e24204694a13e1880235404421b Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Mon, 22 Jan 2018 07:14:32 -0600 Subject: [PATCH 21/40] fs/userfs: use correct req type in userfs_truncate, remove use of undeclared buf --- fs/userfs/fs_userfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/userfs/fs_userfs.c b/fs/userfs/fs_userfs.c index bf91d58c1ec..3cb7a10b21e 100644 --- a/fs/userfs/fs_userfs.c +++ b/fs/userfs/fs_userfs.c @@ -944,7 +944,7 @@ static int userfs_truncate(FAR struct file *filep, off_t length) /* Construct and send the request to the server */ req = (FAR struct userfs_truncate_request_s *)priv->iobuffer; - req->req = USERFS_REQ_FSTAT; + req->req = USERFS_REQ_TRUNCATE; req->openinfo = filep->f_priv; req->length = length; @@ -986,7 +986,6 @@ static int userfs_truncate(FAR struct file *filep, off_t length) /* Return the result of truncate operation */ - DEBUGASSERT(buf != NULL); return resp->ret; } From 6ae6ecc958d207fcab26e0811bfa07a1744ca9ac Mon Sep 17 00:00:00 2001 From: David Alessio Date: Mon, 22 Jan 2018 13:20:35 +0000 Subject: [PATCH 22/40] Merged in david_alessio/nuttx/refactor-pll-setup (pull request #581) Refactor pll setup * fix typo in #def * refactor PLL setup code... * refactored PLL/CLK config, easier, checks for correctness * call go_os_start if STACK_COLORIZED * smarter config of EXTCLK output freq * cosmetic Approved-by: Gregory Nutt --- arch/arm/src/xmc4/chip/xmc4_scu.h | 2 +- arch/arm/src/xmc4/xmc4_clockconfig.c | 37 +++- arch/arm/src/xmc4/xmc4_start.c | 8 + configs/xmc4500-relax/include/board.h | 235 +++++++++++++------------- 4 files changed, 156 insertions(+), 126 deletions(-) diff --git a/arch/arm/src/xmc4/chip/xmc4_scu.h b/arch/arm/src/xmc4/chip/xmc4_scu.h index 2d22084252d..afa4d0f8a7f 100644 --- a/arch/arm/src/xmc4/chip/xmc4_scu.h +++ b/arch/arm/src/xmc4/chip/xmc4_scu.h @@ -938,7 +938,7 @@ #define SCU_SLEEPCR_SYSSEL (1 << 0) /* Bit 0: System Clock Selection Value */ # define SCU_SLEEPCR_SYSSEL_OFI (0) /* 0=fOFI */ -# define SCU_SLEEPCR_SYSSEL_ PLL (1 << 0) /* 1=fPLL */ +# define SCU_SLEEPCR_SYSSEL_FPLL (1 << 0) /* 1=fPLL */ #define SCU_SLEEPCR_USBCR (1 << 16) /* Bit 6: USB Clock Control in Sleep Mode */ #define SCU_SLEEPCR_MMCCR (1 << 17) /* Bit 17: MMC Clock Control in Sleep Mode */ #define SCU_SLEEPCR_ETH0CR (1 << 18) /* Bit 18: Ethernet Clock Control in Sleep Mode */ diff --git a/arch/arm/src/xmc4/xmc4_clockconfig.c b/arch/arm/src/xmc4/xmc4_clockconfig.c index eeb71dbe0b4..9d6cc0621eb 100644 --- a/arch/arm/src/xmc4/xmc4_clockconfig.c +++ b/arch/arm/src/xmc4/xmc4_clockconfig.c @@ -58,6 +58,7 @@ #include "up_arch.h" #include "chip/xmc4_scu.h" #include "xmc4_clockconfig.h" +#include "chip/xmc4_ports.h" #include @@ -105,7 +106,7 @@ #define CLKSET_VALUE (0x00000000) #define USBCLKCR_VALUE (0x00010000) -#if BOARD_PBDIV == 1 +#if BOARD_PLL_PBDIV == 1 # define PBCLKCR_VALUE SCU_PBCLKCR_PBDIV_FCPU #else /* BOARD_PBDIV == 2 */ # define PBCLKCR_VALUE SCU_PBCLKCR_PBDIV_DIV2 @@ -387,8 +388,8 @@ void xmc4_clock_configure(void) /* Setup fSYS clock */ - regval = (BOARD_ENABLE_PLL << SCU_SYSCLKCR_SYSSEL); - regval |= SCU_SYSCLKCR_SYSDIV(BOARD_SYSDIV); + regval = (BOARD_ENABLE_PLL ? SCU_SYSCLKCR_SYSSEL : 0); + regval |= SCU_SYSCLKCR_SYSDIV(BOARD_PLL_SYSDIV); putreg32(regval, XMC4_SCU_SYSCLKCR); /* Setup peripheral clock divider */ @@ -411,7 +412,7 @@ void xmc4_clock_configure(void) /* Setup EBU clock */ - regval = SCU_EBUCLKCR_EBUDIV(BOARD_EBUDIV); + regval = SCU_EBUCLKCR_EBUDIV(BOARD_PLL_EBUDIV); putreg32(regval, XMC4_SCU_EBUCLKCR); #ifdef BOARD_ENABLE_USBPLL @@ -423,7 +424,7 @@ void xmc4_clock_configure(void) /* Setup EXT */ regval = (BOARD_EXT_SOURCE << SCU_EXTCLKCR_ECKSEL_SHIFT); - regval |= SCU_EXTCLKCR_ECKDIV(BOARD_EXTDIV); + regval |= SCU_EXTCLKCR_ECKDIV(BOARD_PLL_ECKDIV); putreg32(regval, XMC4_SCU_EXTCLKCR); #if BOARD_ENABLE_PLL @@ -561,4 +562,30 @@ void xmc4_clock_configure(void) /* Enable selected clocks */ putreg32(CLKSET_VALUE, XMC4_SCU_CLKSET); + +#if BOARD_PLL_CLOCKSRC_XTAL == 1 + regval = SCU_SLEEPCR_SYSSEL_FPLL; + putreg32(regval, XMC4_SCU_SLEEPCR); +#endif /* BOARD_PLL_CLOCKSRC_XTAL == 1 */ + +#if BOARD_EXTCKL_ENABLE +#if BOARD_EXTCLK_PIN == EXTCLK_PIN_P0_8 + /* enable EXTCLK output on P0.8 */ + regval = getreg32(XMC4_PORT0_HWSEL); + regval &= ~PORT_HWSEL_HW8_MASK; + putreg32(regval, XMC4_PORT0_HWSEL); + + regval = getreg32(XMC4_PORT0_PDR1); + regval &= ~PORT_PDR1_PD8_MASK; + putreg32(regval, XMC4_PORT0_PDR1); + + regval = getreg32(XMC4_PORT0_IOCR8); + regval &= ~PORT_IOCR8_PC8_MASK; + regval |= PORT_IOCR8_PC8(0x11); /* push-pull output, alt func 1 */ + putreg32(regval, XMC4_PORT0_IOCR8); +#else + /* enable EXTCLK output on P1.15 */ +# warn "Not yet implemented" +#endif +#endif } diff --git a/arch/arm/src/xmc4/xmc4_start.c b/arch/arm/src/xmc4/xmc4_start.c index d1a1b4a1c3f..5e65aecaac7 100644 --- a/arch/arm/src/xmc4/xmc4_start.c +++ b/arch/arm/src/xmc4/xmc4_start.c @@ -396,9 +396,17 @@ void __start(void) /* Then start NuttX */ +#ifdef CONFIG_STACK_COLORATION + /* Set the IDLE stack to the coloration value and jump into os_start() */ + + go_os_start((FAR void *)&_ebss, CONFIG_IDLETHREAD_STACKSIZE); +#else + /* Call os_start() */ + os_start(); /* Shouldn't get here */ for (; ; ); +#endif } diff --git a/configs/xmc4500-relax/include/board.h b/configs/xmc4500-relax/include/board.h index 7190d1c9394..0dfd182eb6c 100644 --- a/configs/xmc4500-relax/include/board.h +++ b/configs/xmc4500-relax/include/board.h @@ -82,99 +82,8 @@ #define BOARD_XTAL_FREQUENCY 12000000 /* 12MHz XTAL */ #undef BOARD_RTC_XTAL_FRQUENCY /* 32.768KHz RTC XTAL not available on the Relax Lite */ - -#if defined(BOARD_FCPU_144MHZ) -/* Default clock initialization - * - * fXTAL = 12Mhz - * -> fPLL = (fXTAL / (2 * 1) * 48) = 288MHz - * -> fSYS = (fPLL / 1) = 288MHz - * -> fCPU = (fSYS / 2) = 144MHz - * -> fPERIPH = (fCPU / 1) = 144MHz - * -> fCCU = (fSYS / 2) = 144MHz - * -> fETH = 72MHz (REVISIT) - * -> fUSB = 48MHz (REVISIT) - * -> fEBU = 72MHz (REVISIT) - * - * fUSBPLL Disabled, only enabled if SCU_CLK_USBCLKCR_USBSEL_USBPLL is selected - * - * fOFI = 24MHz - * -> fWDT = 24MHz (REVISIT) - */ - -/* Select the external crystal as the PLL clock source */ - -# define BOARD_PLL_CLOCKSRC_XTAL 1 /* PLL Clock source == external crystal */ -# undef BOARD_PLL_CLOCKSRC_OFI /* PLL Clock source != internal fast oscillator */ - -/* PLL Configuration: - * - * fPLL = (fPLLSRC / (pdiv * k2div) * ndiv - * - * fPLL = (12000000 / (2 * 1)) * 48 - * = 288MHz - */ - -# define BOARD_ENABLE_PLL 1 -# define BOARD_PLL_PDIV 2 -# define BOARD_PLL_NDIV 48 -# define BOARD_PLL_K2DIV 1 -# define BOARD_PLL_FREQUENCY 288000000 - -/* System frequency, fSYS, is divided down from PLL output */ - -# define BOARD_SYSDIV 1 /* PLL Output divider to get fSYS */ -# define BOARD_SYS_FREQUENCY 288000000 - -/* CPU frequency, fCPU, may be divided down from system frequency */ - -# define BOARD_CPUDIV_ENABLE 1 /* Enable PLL divide by 2 for fCPU */ -# define BOARD_CPU_FREQUENCY 144000000 - -/* CCU frequency may be divided down from system frequency */ - -# define BOARD_CCUDIV_ENABLE 1 /* Enable PLL div by 2 */ -# define BOARD_CCU_FREQUENCY 144000000 - -/* Watchdog clock settings */ - -# define BOARD_WDT_SOURCE WDT_CLKSRC_FOFI -# define BOARD_WDTDIV 1 -# define BOARD_WDT_FREQUENCY 24000000 - -/* EBU frequency may be divided down from system frequency */ - -# define BOARD_EBUDIV 2 /* fSYS / 2 */ -# define BOARD_EBU_FREQUENCY 72000000 - -/* EXT clock settings */ - -# define BOARD_EXT_SOURCE EXT_CLKSRC_FPLL -# define BOARD_EXTDIV 289 /* REVISIT */ -# define BOARD_EXT_FREQUENCY 498270 /* REVISIT */ - -/* The peripheral clock, fPERIPH, derives from fCPU with no division */ - -# define BOARD_PBDIV 1 /* No division */ -# define BOARD_PERIPH_FREQUENCY 144000000 - -#elif defined(BOARD_FCPU_120MHZ) -/* Default clock initialization - * - * fXTAL = 12Mhz - * -> fPLL = (fXTAL / (2 * 4) * 80) = 120 - * -> fSYS = (fPLL / 1) = 120MHz - * -> fCPU = (fSYS / 1) = 120MHz - * -> fPERIPH = (fCPU / 1) = 120MHz - * -> fCCU = (fSYS / 1) = 120MHz - * -> fETH = 60MHz (REVISIT) - * -> fUSB = 48MHz (REVISIT) - * -> fEBU = 60MHz (REVISIT) - * - * fUSBPLL Disabled, only enabled if SCU_CLK_USBCLKCR_USBSEL_USBPLL is selected - * - * fOFI = 24MHz - * -> fWDT = 24MHz (REVISIT) +/* + * TODO: enable the RTC osc, use RTC for time/date */ /* Select the external crystal as the PLL clock source */ @@ -184,56 +93,142 @@ /* PLL Configuration: * - * fPLL = (fPLLSRC / (pdiv * k2div) * ndiv + * fXTAL = 12Mhz + * 260 MHz <= fVCO <= 520 MHz * - * fPLL = (12000000 / (2 * 4)) * 80 - * = 120MHz + * fVCO = fXTAL * ndiv / pdiv + * fPLL = fVCO / k2div + * fSYS = fPLL / sysdiv + * fETH = fSYS / 2 (fixed div by 2) + * fCCU = fSYS / ccudiv (div by 1 or 2) + * fCPU = fSYS / cpudiv (div by 1 or 2) + * fPERIPH = fCPU / pbdiv (div by 1 or 2) */ -# define BOARD_ENABLE_PLL 1 -# define BOARD_PLL_PDIV 2 -# define BOARD_PLL_NDIV 80 +# define BOARD_ENABLE_PLL 1 /* enable the PLL */ +# define CPU_FREQ 120 /* MHz */ + +/* TODO: Automate PLL calculations */ + +#if CPU_FREQ == 120 +/* + * 120 MHz + * + * fVCO = 12MHz * 40 / 2 = 480MHz + * fPLL = 480MHz / 2 = 240MHz + * fSYS = fPLL / 2 = 120MHz + * fCCU = fSYS / 2 = 60MHz + * fCPU = fSYS / 1 = 120MHz + * fPB = fCPU / 2 = 60MHz + * fETH = fSYS / 2 = 60MHz + */ + +# define BOARD_PLL_NDIV 40 +# define BOARD_PLL_PDIV 1 # define BOARD_PLL_K2DIV 4 -# define BOARD_PLL_FREQUENCY 120000000 +# define BOARD_PLL_SYSDIV 1 +# define BOARD_PLL_CPUDIV 1 +# define BOARD_PLL_PBDIV 2 +# define BOARD_PLL_CCUDIV 2 +# define BOARD_PLL_EBUDIV 4 -/* System frequency, fSYS, is divided down from PLL output */ +#elif CPU_FREQ == 144 +/* + * 144 MHz + * + * fVCO = 12MHz * 36 / 1 = 432MHz + * fPLL = 432MHz / 3 = 144MHz + * fSYS = fPLL / 1 = 144MHz + * fCCU = fSYS / 2 = 72MHz + * fCPU = fSYS / 1 = 144MHz + * fPB = fCPU / 2 = 72MHz + * fETH = fSYS / 2 = 72MHz + */ -# define BOARD_SYSDIV 1 /* No division */ -# define BOARD_SYS_FREQUENCY 120000000 +# define BOARD_PLL_NDIV 36 +# define BOARD_PLL_PDIV 1 +# define BOARD_PLL_K2DIV 3 +# define BOARD_PLL_SYSDIV 1 +# define BOARD_PLL_CPUDIV 1 +# define BOARD_PLL_PBDIV 2 +# define BOARD_PLL_CCUDIV 2 +# define BOARD_PLL_EBUDIV 2 -/* CPU frequency, fCPU, may be divided down from system frequency */ +#else +# error "Illegal or Unsupported CPU Frequency" +#endif -# define BOARD_CPUDIV_ENABLE 0 /* No divison */ -# define BOARD_CPU_FREQUENCY 120000000 -/* CCU frequency may be divided down from system frequency */ +# define BOARD_CCUDIV_ENABLE (BOARD_PLL_CCUDIV - 1) +# define BOARD_CPUDIV_ENABLE (BOARD_PLL_CPUDIV - 1) -# define BOARD_CCUDIV_ENABLE 0 /* No divison */ -# define BOARD_CCU_FREQUENCY 120000000 - -/* Watchdog clock setting */ +# define BOARD_VCO_FREQUENCY (BOARD_XTAL_FREQUENCY * BOARD_PLL_NDIV / BOARD_PLL_PDIV) +# define BOARD_PLL_FREQUENCY (BOARD_VCO_FREQUENCY / BOARD_PLL_K2DIV) +# define BOARD_SYS_FREQUENCY (BOARD_PLL_FREQUENCY / BOARD_PLL_SYSDIV) +# define BOARD_CCU_FREQUENCY (BOARD_SYS_FREQUENCY / BOARD_PLL_CCUDIV) +# define BOARD_CPU_FREQUENCY (BOARD_SYS_FREQUENCY / BOARD_PLL_CPUDIV) +# define BOARD_PERIPH_FREQUENCY (BOARD_CPU_FREQUENCY / BOARD_PLL_PBDIV) +# define BOARD_ETH_FREQUENCY (BOARD_SYS_FREQUENCY / 2) # define BOARD_WDT_SOURCE WDT_CLKSRC_FOFI # define BOARD_WDTDIV 1 # define BOARD_WDT_FREQUENCY 24000000 -/* EBU frequency may be divided down from system frequency */ +# define BOARD_EXT_SOURCE EXT_CLKSRC_FPLL +# define BOARD_PLL_ECKDIV 480 /* [1,512] */ + +# define kHz_1 1000 +# define MHz_1 (kHz_1 * kHz_1) +# define MHz_50 ( 50 * MHz_1) +# define MHz_260 (260 * MHz_1) +# define MHz_520 (520 * MHz_1) + + /* range check VCO frequency */ +# if (BOARD_VCO_FREQUENCY < MHz_260) +# error "VCO freq must be >= 260 MHz" +# endif + +# if (BOARD_VCO_FREQUENCY > MHz_520) +# error "VCO freq must be <= 520 MHz" +# endif + + /* range check Ethernet MAC frequency */ +# if (BOARD_ETH_FREQUENCY <= MHz_50) +# error "ETH freq must be > 50 MHz" +# endif + + + +/* check ccudiv cpudiv pbdiv against Table 11-5 + * of XMC4500 User Manual + */ +#define CLKDIV_INDEX (4 * (BOARD_PLL_CCUDIV-1) + \ + 2 * (BOARD_PLL_CPUDIV-1) + \ + (BOARD_PLL_PBDIV-1) ) + +#if (CLKDIV_INDEX == 3) || (CLKDIV_INDEX == 4) || (CLKDIV_INDEX > 6) +# error "Illegal combination of dividers! Ref: Table 11-5 of UM" +#endif -# define BOARD_EBUDIV 2 /* fSYS/2 */ -# define BOARD_EBU_FREQUENCY 60000000 /* EXT clock settings */ +#define BOARD_EXTCKL_ENABLE 1 /* 0 disables output */ +#if BOARD_EXTCKL_ENABLE +# define EXTCLK_PIN_P0_8 8 +# define EXTCLK_PIN_P1_15 15 +# define BOARD_EXTCLK_PIN EXTCLK_PIN_P0_8 # define BOARD_EXT_SOURCE EXT_CLKSRC_FPLL -# define BOARD_EXTDIV 289 /* REVISIT */ -# define BOARD_EXT_FREQUENCY 415225 /* REVISIT */ +# define BOARD_EXT_FREQUENCY (250 * kHz_1) /* Desired output freq */ +# define BOARD_EXTDIV (BOARD_PLL_FREQUENCY / BOARD_EXT_FREQUENCY) -/* The peripheral clock, fPERIPH, derives from fCPU with no division */ - -# define BOARD_PBDIV 1 /* No division */ -# define BOARD_PERIPH_FREQUENCY 120000000 +/* range check EXTDIV */ +# if BOARD_EXTDIV > 512 +# error "EXTCLK Divisor out of range!" +# endif #endif + /* Standby clock source selection * * BOARD_STDBY_CLOCKSRC_OSI - Internal 32.768KHz slow oscillator From a8b6be4aafea0c9e87cab6b82a2b1be9eea0294f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 22 Jan 2018 08:17:31 -0600 Subject: [PATCH 23/40] The existence of the network driver ioctl() method should depend on CONFIG_NETDEV_IOCTL rather than CONFIG_NETDEV_PHY_IOCTL. The former enables the method, the later enables a subset of possible driver IOCTLs. This change should be basically a no-operation. The affected ioctl methods only support those subset of driver IOCTLs selected by CONFIG_NETDEV_PHY_IOCTL and the network logic will tolerate a nul ioctl method. --- arch/arm/src/c5471/c5471_ethernet.c | 2 +- arch/arm/src/kinetis/kinetis_enet.c | 70 ++++----- arch/arm/src/lpc17xx/lpc17_ethernet.c | 2 +- arch/arm/src/lpc43xx/lpc43_ethernet.c | 16 +- arch/arm/src/lpc54xx/lpc54_ethernet.c | 4 + arch/arm/src/sam34/sam_emac.c | 138 +++++++++--------- arch/arm/src/sama5/sam_emaca.c | 138 +++++++++--------- arch/arm/src/sama5/sam_emacb.c | 134 ++++++++--------- arch/arm/src/sama5/sam_gmac.c | 132 +++++++++-------- arch/arm/src/samv7/sam_emac.c | 136 ++++++++--------- arch/arm/src/stm32/stm32_eth.c | 82 ++++++----- arch/arm/src/stm32f7/stm32_ethernet.c | 14 +- arch/arm/src/tiva/tm4c_ethernet.c | 80 +++++----- arch/hc/src/m9s12/m9s12_ethernet.c | 2 +- arch/mips/src/pic32mx/pic32mx-ethernet.c | 2 +- arch/mips/src/pic32mz/pic32mz-ethernet.c | 2 +- arch/misoc/src/common/misoc_net.c | 2 +- arch/z80/src/ez80/ez80_emac.c | 2 +- drivers/net/dm90x0.c | 2 +- drivers/net/enc28j60.c | 2 +- drivers/net/encx24j600.c | 2 +- drivers/net/ftmac100.c | 2 +- drivers/net/tun.c | 2 +- .../wireless/ieee802154/xbee/xbee_netdev.c | 2 +- .../wireless/spirit/drivers/spirit_netdev.c | 2 +- wireless/ieee802154/mac802154_netdev.c | 2 +- 26 files changed, 505 insertions(+), 469 deletions(-) diff --git a/arch/arm/src/c5471/c5471_ethernet.c b/arch/arm/src/c5471/c5471_ethernet.c index b98fd6ecac9..f38497a37ed 100644 --- a/arch/arm/src/c5471/c5471_ethernet.c +++ b/arch/arm/src/c5471/c5471_ethernet.c @@ -2447,7 +2447,7 @@ void up_netinitialize(void) #endif g_c5471[0].c_dev.d_private = (void *)g_c5471; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ g_c5471[0].c_txpoll = wd_create(); /* Create periodic poll timer */ g_c5471[0].c_txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/arch/arm/src/kinetis/kinetis_enet.c b/arch/arm/src/kinetis/kinetis_enet.c index 8f51cc6a7b8..4a7e1ba7caa 100644 --- a/arch/arm/src/kinetis/kinetis_enet.c +++ b/arch/arm/src/kinetis/kinetis_enet.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/kinetis/kinetis_enet.c * - * Copyright (C) 2011-2012, 2014-2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2011-2012, 2014-2018 Gregory Nutt. All rights reserved. * Authors: Gregory Nutt * David Sidrane * @@ -310,7 +310,7 @@ static int kinetis_addmac(struct net_driver_s *dev, static int kinetis_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac); #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int kinetis_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif @@ -1449,48 +1449,52 @@ static int kinetis_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac) * ****************************************************************************/ -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int kinetis_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { - int ret; +#ifdef CONFIG_NETDEV_PHY_IOCTL FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)dev->d_private; +#endif + int ret; switch (cmd) - { - case SIOCGMIIPHY: /* Get MII PHY address */ { - struct mii_ioctl_data_s *req = - (struct mii_ioctl_data_s *)((uintptr_t)arg); - req->phy_id = priv->phyaddr; - ret = OK; - } - break; +#ifdef CONFIG_NETDEV_PHY_IOCTL + case SIOCGMIIPHY: /* Get MII PHY address */ + { + struct mii_ioctl_data_s *req = + (struct mii_ioctl_data_s *)((uintptr_t)arg); + req->phy_id = priv->phyaddr; + ret = OK; + } + break; - case SIOCGMIIREG: /* Get register from MII PHY */ - { - struct mii_ioctl_data_s *req = - (struct mii_ioctl_data_s *)((uintptr_t)arg); - ret = kinetis_readmii(priv, req->phy_id, req->reg_num, &req->val_out); - } - break; + case SIOCGMIIREG: /* Get register from MII PHY */ + { + struct mii_ioctl_data_s *req = + (struct mii_ioctl_data_s *)((uintptr_t)arg); + ret = kinetis_readmii(priv, req->phy_id, req->reg_num, &req->val_out); + } + break; - case SIOCSMIIREG: /* Set register in MII PHY */ - { - struct mii_ioctl_data_s *req = - (struct mii_ioctl_data_s *)((uintptr_t)arg); - ret = kinetis_writemii(priv, req->phy_id, req->reg_num, req->val_in); - } - break; + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = + (struct mii_ioctl_data_s *)((uintptr_t)arg); + ret = kinetis_writemii(priv, req->phy_id, req->reg_num, req->val_in); + } + break; +#endif /* ifdef CONFIG_NETDEV_PHY_IOCTL */ - default: - ret = -ENOTTY; - break; - } + default: + ret = -ENOTTY; + break; + } return ret; } -#endif /* CONFIG_NETDEV_PHY_IOCTL */ +#endif /* CONFIG_NETDEV_IOCTL */ /**************************************************************************** * Function: kinetis_initmii @@ -2127,12 +2131,12 @@ int kinetis_netinitialize(int intf) priv->dev.d_addmac = kinetis_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = kinetis_rmmac; /* Remove multicast MAC address */ #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL priv->dev.d_ioctl = kinetis_ioctl; /* Support PHY ioctl() calls */ #endif priv->dev.d_private = (void *)g_enet; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->txpoll = wd_create(); /* Create periodic poll timer */ priv->txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/arch/arm/src/lpc17xx/lpc17_ethernet.c b/arch/arm/src/lpc17xx/lpc17_ethernet.c index dd1c05d0d14..196b15bab83 100644 --- a/arch/arm/src/lpc17xx/lpc17_ethernet.c +++ b/arch/arm/src/lpc17xx/lpc17_ethernet.c @@ -3056,7 +3056,7 @@ static inline int lpc17_ethinitialize(int intf) priv->lp_irq = ??; /* Ethernet controller IRQ number */ #endif - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->lp_txpoll = wd_create(); /* Create periodic poll timer */ priv->lp_txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/arch/arm/src/lpc43xx/lpc43_ethernet.c b/arch/arm/src/lpc43xx/lpc43_ethernet.c index f5a9cb1e580..e5981788117 100644 --- a/arch/arm/src/lpc43xx/lpc43_ethernet.c +++ b/arch/arm/src/lpc43xx/lpc43_ethernet.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/lpc43/lpc43_eth.c * - * Copyright (C) 2011-2015, 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2011-2015, 2017-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -621,7 +621,7 @@ static int lpc43_addmac(struct net_driver_s *dev, FAR const uint8_t *mac); #ifdef CONFIG_NET_IGMP static int lpc43_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac); #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int lpc43_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif @@ -2744,16 +2744,17 @@ static void lpc43_rxdescinit(FAR struct lpc43_ethmac_s *priv) * ****************************************************************************/ -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int lpc43_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { -#ifdef CONFIG_ARCH_PHY_INTERRUPT +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)dev->d_private; #endif int ret; switch (cmd) { +#ifdef CONFIG_NETDEV_PHY_IOCTL #ifdef CONFIG_ARCH_PHY_INTERRUPT case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { @@ -2791,6 +2792,7 @@ static int lpc43_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) ret = lpc43_phywrite(req->phy_id, req->reg_num, req->val_in); } break; +#endif /* ifdef CONFIG_NETDEV_PHY_IOCTL */ default: ret = -ENOTTY; @@ -2799,7 +2801,7 @@ static int lpc43_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) return ret; } -#endif /* CONFIG_NETDEV_PHY_IOCTL */ +#endif /* CONFIG_NETDEV_IOCTL */ /**************************************************************************** * Function: lpc43_phyintenable @@ -3823,12 +3825,12 @@ static inline int lpc43_ethinitialize(void) priv->dev.d_addmac = lpc43_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = lpc43_rmmac; /* Remove multicast MAC address */ #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL priv->dev.d_ioctl = lpc43_ioctl; /* Support PHY ioctl() calls */ #endif priv->dev.d_private = (void *)&g_lpc43ethmac; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmission */ priv->txpoll = wd_create(); /* Create periodic poll timer */ priv->txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/arch/arm/src/lpc54xx/lpc54_ethernet.c b/arch/arm/src/lpc54xx/lpc54_ethernet.c index d89317247dc..dde91da5c17 100644 --- a/arch/arm/src/lpc54xx/lpc54_ethernet.c +++ b/arch/arm/src/lpc54xx/lpc54_ethernet.c @@ -2392,13 +2392,16 @@ static int lpc54_eth_rmmac(struct net_driver_s *dev, const uint8_t *mac) static int lpc54_eth_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { +#ifdef CONFIG_NETDEV_PHY_IOCTL struct lpc54_ethdriver_s *priv = (struct lpc54_ethdriver_s *)dev->d_private; +#endif int ret; /* Decode and dispatch the driver-specific IOCTL command */ switch (cmd) { +#ifdef CONFIG_NETDEV_PHY_IOCTL case SIOCGMIIPHY: /* Get MII PHY address */ { struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); @@ -2422,6 +2425,7 @@ static int lpc54_eth_ioctl(struct net_driver_s *dev, int cmd, ret = OK } break; +#endif /* ifdef CONFIG_NETDEV_PHY_IOCTL */ default: nerr("ERROR: Unrecognized IOCTL command: %d\n", command); diff --git a/arch/arm/src/sam34/sam_emac.c b/arch/arm/src/sam34/sam_emac.c index c45ea9f3838..88d43258d56 100644 --- a/arch/arm/src/sam34/sam_emac.c +++ b/arch/arm/src/sam34/sam_emac.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/sam34/sam_emac.c * - * Copyright (C) 2014-2015, 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2015, 2017-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * This logic derives from the SAM34D3 Ethernet driver. @@ -408,7 +408,7 @@ static int sam_addmac(struct net_driver_s *dev, const uint8_t *mac); static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac); #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif @@ -2309,86 +2309,90 @@ static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac) * ****************************************************************************/ -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { +#ifdef CONFIG_NETDEV_PHY_IOCTL struct sam_emac_s *priv = (struct sam_emac_s *)dev->d_private; +#endif int ret; switch (cmd) - { -#ifdef CONFIG_ARCH_PHY_INTERRUPT - case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - - ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); - if (ret == OK) +#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_ARCH_PHY_INTERRUPT + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - /* Enable PHY link up/down interrupts */ + struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - ret = sam_phyintenable(priv); + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = sam_phyintenable(priv); + } } - } - break; + break; #endif - case SIOCGMIIPHY: /* Get MII PHY address */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - req->phy_id = priv->phyaddr; - ret = OK; + case SIOCGMIIPHY: /* Get MII PHY address */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + req->phy_id = priv->phyaddr; + ret = OK; + } + break; + + case SIOCGMIIREG: /* Get register from MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + uint32_t regval; + + /* Enable management port */ + + regval = sam_getreg(priv, SAM_EMAC_NCR); + sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); + + /* Read from the requested register */ + + ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); + + /* Disable management port (probably) */ + + sam_putreg(priv, SAM_EMAC_NCR, regval); + } + break; + + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + uint32_t regval; + + /* Enable management port */ + + regval = sam_getreg(priv, SAM_EMAC_NCR); + sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); + + /* Write to the requested register */ + + ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); + + /* Disable management port (probably) */ + + sam_putreg(priv, SAM_EMAC_NCR, regval); + } + break; +#endif /* ifdef CONFIG_NETDEV_PHY_IOCTL */ + + default: + ret = -ENOTTY; + break; } - break; - - case SIOCGMIIREG: /* Get register from MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - uint32_t regval; - - /* Enable management port */ - - regval = sam_getreg(priv, SAM_EMAC_NCR); - sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); - - /* Read from the requested register */ - - ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); - - /* Disable management port (probably) */ - - sam_putreg(priv, SAM_EMAC_NCR, regval); - } - break; - - case SIOCSMIIREG: /* Set register in MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - uint32_t regval; - - /* Enable management port */ - - regval = sam_getreg(priv, SAM_EMAC_NCR); - sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); - - /* Write to the requested register */ - - ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); - - /* Disable management port (probably) */ - - sam_putreg(priv, SAM_EMAC_NCR, regval); - } - break; - - default: - ret = -ENOTTY; - break; - } return ret; } -#endif /* CONFIG_NETDEV_PHY_IOCTL */ +#endif /* CONFIG_NETDEV_IOCTL */ /**************************************************************************** * Function: sam_phydump @@ -3630,7 +3634,7 @@ void up_netinitialize(void) priv->dev.d_addmac = sam_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = sam_rmmac; /* Remove multicast MAC address */ #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL priv->dev.d_ioctl = sam_ioctl; /* Support PHY ioctl() calls */ #endif priv->dev.d_private = (void *)&g_emac; /* Used to recover private state from dev */ diff --git a/arch/arm/src/sama5/sam_emaca.c b/arch/arm/src/sama5/sam_emaca.c index 1648cab5258..3a011a5b7cb 100644 --- a/arch/arm/src/sama5/sam_emaca.c +++ b/arch/arm/src/sama5/sam_emaca.c @@ -4,7 +4,7 @@ * 10/100 Base-T Ethernet driver for the SAMA5D3. Denoted as 'A' to * distinguish it from the SAMA5D4 EMAC driver. * - * Copyright (C) 2013-2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * References: @@ -413,7 +413,7 @@ static int sam_addmac(struct net_driver_s *dev, const uint8_t *mac); static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac); #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif @@ -2345,86 +2345,90 @@ static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac) * ****************************************************************************/ -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { +#ifdef CONFIG_NETDEV_PHY_IOCTL struct sam_emac_s *priv = (struct sam_emac_s *)dev->d_private; +#endif int ret; switch (cmd) - { -#ifdef CONFIG_ARCH_PHY_INTERRUPT - case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - - ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); - if (ret == OK) +#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_ARCH_PHY_INTERRUPT + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - /* Enable PHY link up/down interrupts */ + struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - ret = sam_phyintenable(priv); + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = sam_phyintenable(priv); + } } - } - break; + break; #endif - case SIOCGMIIPHY: /* Get MII PHY address */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - req->phy_id = priv->phyaddr; - ret = OK; + case SIOCGMIIPHY: /* Get MII PHY address */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + req->phy_id = priv->phyaddr; + ret = OK; + } + break; + + case SIOCGMIIREG: /* Get register from MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + uint32_t regval; + + /* Enable management port */ + + regval = sam_getreg(priv, SAM_EMAC_NCR); + sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); + + /* Read from the requested register */ + + ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); + + /* Disable management port (probably) */ + + sam_putreg(priv, SAM_EMAC_NCR, regval); + } + break; + + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + uint32_t regval; + + /* Enable management port */ + + regval = sam_getreg(priv, SAM_EMAC_NCR); + sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); + + /* Write to the requested register */ + + ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); + + /* Disable management port (probably) */ + + sam_putreg(priv, SAM_EMAC_NCR, regval); + } + break; +#endif /* CONFIG_NETDEV_PHY_IOCTL */ + + default: + ret = -ENOTTY; + break; } - break; - - case SIOCGMIIREG: /* Get register from MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - uint32_t regval; - - /* Enable management port */ - - regval = sam_getreg(priv, SAM_EMAC_NCR); - sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); - - /* Read from the requested register */ - - ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); - - /* Disable management port (probably) */ - - sam_putreg(priv, SAM_EMAC_NCR, regval); - } - break; - - case SIOCSMIIREG: /* Set register in MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - uint32_t regval; - - /* Enable management port */ - - regval = sam_getreg(priv, SAM_EMAC_NCR); - sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); - - /* Write to the requested register */ - - ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); - - /* Disable management port (probably) */ - - sam_putreg(priv, SAM_EMAC_NCR, regval); - } - break; - - default: - ret = -ENOTTY; - break; - } return ret; } -#endif /* CONFIG_NETDEV_PHY_IOCTL */ +#endif /* CONFIG_NETDEV_IOCTL */ /**************************************************************************** * Function: sam_phydump @@ -3672,7 +3676,7 @@ int sam_emac_initialize(void) priv->dev.d_addmac = sam_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = sam_rmmac; /* Remove multicast MAC address */ #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL priv->dev.d_ioctl = sam_ioctl; /* Support PHY ioctl() calls */ #endif priv->dev.d_private = (void *)&g_emac; /* Used to recover private state from dev */ diff --git a/arch/arm/src/sama5/sam_emacb.c b/arch/arm/src/sama5/sam_emacb.c index c9fb251acac..9f6f366e245 100644 --- a/arch/arm/src/sama5/sam_emacb.c +++ b/arch/arm/src/sama5/sam_emacb.c @@ -507,7 +507,7 @@ static int sam_addmac(struct net_driver_s *dev, const uint8_t *mac); static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac); #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif @@ -2715,79 +2715,83 @@ static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac) #ifdef CONFIG_NETDEV_PHY_IOCTL static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { +#ifdef CONFIG_NETDEV_PHY_IOCTL struct sam_emac_s *priv = (struct sam_emac_s *)dev->d_private; +#endif int ret; switch (cmd) - { -#ifdef CONFIG_ARCH_PHY_INTERRUPT - case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); +#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_ARCH_PHY_INTERRUPT + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ + { + struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); - if (ret == OK) - { - /* Enable PHY link up/down interrupts */ + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ - ret = sam_phyintenable(priv); + ret = sam_phyintenable(priv); + } } - } - break; + break; #endif - case SIOCGMIIPHY: /* Get MII PHY address */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - req->phy_id = priv->phyaddr; - ret = OK; + case SIOCGMIIPHY: /* Get MII PHY address */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + req->phy_id = priv->phyaddr; + ret = OK; + } + break; + + case SIOCGMIIREG: /* Get register from MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + uint32_t regval; + + /* Enable management port */ + + regval = sam_getreg(priv, SAM_EMAC_NCR_OFFSET); + sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval | EMAC_NCR_MPE); + + /* Read from the requested register */ + + ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); + + /* Disable management port (probably) */ + + sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval); + } + break; + + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + uint32_t regval; + + /* Enable management port */ + + regval = sam_getreg(priv, SAM_EMAC_NCR_OFFSET); + sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval | EMAC_NCR_MPE); + + /* Write to the requested register */ + + ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); + + /* Disable management port (probably) */ + + sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval); + } + break; +#endif /* CONFIG_NETDEV_PHY_IOCTL */ + + default: + ret = -ENOTTY; + break; } - break; - - case SIOCGMIIREG: /* Get register from MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - uint32_t regval; - - /* Enable management port */ - - regval = sam_getreg(priv, SAM_EMAC_NCR_OFFSET); - sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval | EMAC_NCR_MPE); - - /* Read from the requested register */ - - ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); - - /* Disable management port (probably) */ - - sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval); - } - break; - - case SIOCSMIIREG: /* Set register in MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - uint32_t regval; - - /* Enable management port */ - - regval = sam_getreg(priv, SAM_EMAC_NCR_OFFSET); - sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval | EMAC_NCR_MPE); - - /* Write to the requested register */ - - ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); - - /* Disable management port (probably) */ - - sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval); - } - break; - - default: - ret = -ENOTTY; - break; - } return ret; } @@ -4357,9 +4361,9 @@ int sam_emac_initialize(int intf) priv->dev.d_addmac = sam_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = sam_rmmac; /* Remove multicast MAC address */ #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL priv->dev.d_ioctl = sam_ioctl; /* Support PHY ioctl() calls */ -#ifdef CONFIG_ARCH_PHY_INTERRUPT +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) priv->phytype = phytype; /* Type of PHY on port */ #endif #endif diff --git a/arch/arm/src/sama5/sam_gmac.c b/arch/arm/src/sama5/sam_gmac.c index d9099621906..d70a40c5a33 100644 --- a/arch/arm/src/sama5/sam_gmac.c +++ b/arch/arm/src/sama5/sam_gmac.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/sama5/sam_gmac.c * - * Copyright (C) 2013-2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * References: @@ -338,7 +338,7 @@ static int sam_addmac(struct net_driver_s *dev, const uint8_t *mac); static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac); #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif @@ -2300,82 +2300,86 @@ static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac) * ****************************************************************************/ -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { +#ifdef CONFIG_NETDEV_PHY_IOCTL struct sam_gmac_s *priv = (struct sam_gmac_s *)dev->d_private; +#endif int ret; switch (cmd) - { -#ifdef CONFIG_ARCH_PHY_INTERRUPT - case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - - ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); - if (ret == OK) +#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_ARCH_PHY_INTERRUPT + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - /* Enable PHY link up/down interrupts */ + struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - ret = sam_phyintenable(priv); + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = sam_phyintenable(priv); + } } - } - break; + break; #endif - case SIOCGMIIPHY: /* Get MII PHY address */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - req->phy_id = priv->phyaddr; - ret = OK; + case SIOCGMIIPHY: /* Get MII PHY address */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + req->phy_id = priv->phyaddr; + ret = OK; + } + break; + + case SIOCGMIIREG: /* Get register from MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + + /* Enable the management port */ + + sam_enablemdio(priv); + + /* Read from the requested register */ + + ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); + + /* Disable the management port */ + + sam_disablemdio(priv); + } + break; + + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + + /* Enable the management port */ + + sam_enablemdio(priv); + + /* Write to the requested register */ + + ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); + + /* Disable the management port */ + + sam_disablemdio(priv); + } + break; +#endif /* CONFIG_NETDEV_PHY_IOCTL */ + + default: + ret = -ENOTTY; + break; } - break; - - case SIOCGMIIREG: /* Get register from MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - - /* Enable the management port */ - - sam_enablemdio(priv); - - /* Read from the requested register */ - - ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); - - /* Disable the management port */ - - sam_disablemdio(priv); - } - break; - - case SIOCSMIIREG: /* Set register in MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - - /* Enable the management port */ - - sam_enablemdio(priv); - - /* Write to the requested register */ - - ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); - - /* Disable the management port */ - - sam_disablemdio(priv); - } - break; - - default: - ret = -ENOTTY; - break; - } return ret; } -#endif /* CONFIG_NETDEV_PHY_IOCTL */ +#endif /* CONFIG_NETDEV_IOCTL */ /**************************************************************************** * Function: sam_phydump @@ -3744,12 +3748,12 @@ int sam_gmac_initialize(void) priv->dev.d_addmac = sam_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = sam_rmmac; /* Remove multicast MAC address */ #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL priv->dev.d_ioctl = sam_ioctl; /* Support PHY ioctl() calls */ #endif priv->dev.d_private = (void *)&g_gmac; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->txpoll = wd_create(); if (!priv->txpoll) diff --git a/arch/arm/src/samv7/sam_emac.c b/arch/arm/src/samv7/sam_emac.c index 3496331898c..94c5956b2bd 100644 --- a/arch/arm/src/samv7/sam_emac.c +++ b/arch/arm/src/samv7/sam_emac.c @@ -2,7 +2,7 @@ * arch/arm/src/samv7/sam_emac.c * 10/100 Base-T Ethernet driver for the SAMV71. * - * Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2015, 2017-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * This logic derives from the SAMA5 Ethernet driver which, in turn, derived @@ -622,7 +622,7 @@ static int sam_addmac(struct net_driver_s *dev, const uint8_t *mac); static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac); #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif @@ -3196,86 +3196,90 @@ static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac) * ****************************************************************************/ -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { +#ifdef CONFIG_NETDEV_PHY_IOCTL struct sam_emac_s *priv = (struct sam_emac_s *)dev->d_private; +#endif int ret; switch (cmd) - { + { +#ifdef CONFIG_NETDEV_PHY_IOCTL #ifdef CONFIG_ARCH_PHY_INTERRUPT case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); + struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); - if (ret == OK) - { - /* Enable PHY link up/down interrupts */ + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ - ret = sam_phyintenable(priv); + ret = sam_phyintenable(priv); + } } - } - break; + break; #endif - case SIOCGMIIPHY: /* Get MII PHY address */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - req->phy_id = priv->phyaddr; - ret = OK; + case SIOCGMIIPHY: /* Get MII PHY address */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + req->phy_id = priv->phyaddr; + ret = OK; + } + break; + + case SIOCGMIIREG: /* Get register from MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + uint32_t regval; + + /* Enable management port */ + + regval = sam_getreg(priv, SAM_EMAC_NCR_OFFSET); + sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval | EMAC_NCR_MPE); + + /* Read from the requested register */ + + ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); + + /* Disable management port (probably) */ + + sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval); + } + break; + + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + uint32_t regval; + + /* Enable management port */ + + regval = sam_getreg(priv, SAM_EMAC_NCR_OFFSET); + sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval | EMAC_NCR_MPE); + + /* Write to the requested register */ + + ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); + + /* Disable management port (probably) */ + + sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval); + } + break; +#endif /* CONFIG_NETDEV_PHY_IOCTL */ + + default: + ret = -ENOTTY; + break; } - break; - - case SIOCGMIIREG: /* Get register from MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - uint32_t regval; - - /* Enable management port */ - - regval = sam_getreg(priv, SAM_EMAC_NCR_OFFSET); - sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval | EMAC_NCR_MPE); - - /* Read from the requested register */ - - ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); - - /* Disable management port (probably) */ - - sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval); - } - break; - - case SIOCSMIIREG: /* Set register in MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - uint32_t regval; - - /* Enable management port */ - - regval = sam_getreg(priv, SAM_EMAC_NCR_OFFSET); - sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval | EMAC_NCR_MPE); - - /* Write to the requested register */ - - ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); - - /* Disable management port (probably) */ - - sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval); - } - break; - - default: - ret = -ENOTTY; - break; - } return ret; } -#endif /* CONFIG_NETDEV_PHY_IOCTL */ +#endif /* CONFIG_NETDEV_IOCTL */ /**************************************************************************** * Function: sam_phydump @@ -5017,9 +5021,9 @@ int sam_emac_initialize(int intf) priv->dev.d_addmac = sam_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = sam_rmmac; /* Remove multicast MAC address */ #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL priv->dev.d_ioctl = sam_ioctl; /* Support PHY ioctl() calls */ -#ifdef CONFIG_ARCH_PHY_INTERRUPT +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) priv->phytype = phytype; /* Type of PHY on port */ #endif #endif diff --git a/arch/arm/src/stm32/stm32_eth.c b/arch/arm/src/stm32/stm32_eth.c index 62e44a0ff23..0c2aac13116 100644 --- a/arch/arm/src/stm32/stm32_eth.c +++ b/arch/arm/src/stm32/stm32_eth.c @@ -721,7 +721,7 @@ static int stm32_addmac(struct net_driver_s *dev, FAR const uint8_t *mac); #ifdef CONFIG_NET_IGMP static int stm32_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac); #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int stm32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif @@ -2847,62 +2847,64 @@ static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv) * ****************************************************************************/ -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int stm32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { -#ifdef CONFIG_ARCH_PHY_INTERRUPT +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; #endif int ret; switch (cmd) - { -#ifdef CONFIG_ARCH_PHY_INTERRUPT - case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - - ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); - if (ret == OK) +#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_ARCH_PHY_INTERRUPT + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - /* Enable PHY link up/down interrupts */ + struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - ret = stm32_phyintenable(priv); + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = stm32_phyintenable(priv); + } } - } - break; + break; #endif - case SIOCGMIIPHY: /* Get MII PHY address */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - req->phy_id = CONFIG_STM32_PHYADDR; - ret = OK; - } - break; + case SIOCGMIIPHY: /* Get MII PHY address */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + req->phy_id = CONFIG_STM32_PHYADDR; + ret = OK; + } + break; - case SIOCGMIIREG: /* Get register from MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - ret = stm32_phyread(req->phy_id, req->reg_num, &req->val_out); - } - break; + case SIOCGMIIREG: /* Get register from MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + ret = stm32_phyread(req->phy_id, req->reg_num, &req->val_out); + } + break; - case SIOCSMIIREG: /* Set register in MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - ret = stm32_phywrite(req->phy_id, req->reg_num, req->val_in); - } - break; + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + ret = stm32_phywrite(req->phy_id, req->reg_num, req->val_in); + } + break; +#endif /* CONFIG_NETDEV_PHY_IOCTL */ - default: - ret = -ENOTTY; - break; - } + default: + ret = -ENOTTY; + break; + } return ret; } -#endif /* CONFIG_NETDEV_PHY_IOCTL */ +#endif /* CONFIG_NETDEV_IOCTL */ /**************************************************************************** * Function: stm32_phyintenable @@ -4014,12 +4016,12 @@ int stm32_ethinitialize(int intf) priv->dev.d_addmac = stm32_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = stm32_rmmac; /* Remove multicast MAC address */ #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL priv->dev.d_ioctl = stm32_ioctl; /* Support PHY ioctl() calls */ #endif priv->dev.d_private = (void *)g_stm32ethmac; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->txpoll = wd_create(); /* Create periodic poll timer */ priv->txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/arch/arm/src/stm32f7/stm32_ethernet.c b/arch/arm/src/stm32f7/stm32_ethernet.c index 8c0eddd847e..d5337d8f48c 100644 --- a/arch/arm/src/stm32f7/stm32_ethernet.c +++ b/arch/arm/src/stm32f7/stm32_ethernet.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/stm32f7/stm32_ethernet.c * - * Copyright (C) 2015-2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2015-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -732,7 +732,7 @@ static int stm32_addmac(struct net_driver_s *dev, const uint8_t *mac); #ifdef CONFIG_NET_IGMP static int stm32_rmmac(struct net_driver_s *dev, const uint8_t *mac); #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int stm32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif @@ -2958,16 +2958,17 @@ static void stm32_rxdescinit(struct stm32_ethmac_s *priv, * ****************************************************************************/ -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int stm32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { -#ifdef CONFIG_ARCH_PHY_INTERRUPT +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) struct stm32_ethmac_s *priv = (struct stm32_ethmac_s *)dev->d_private; #endif int ret; switch (cmd) { +#ifdef CONFIG_NETDEV_PHY_IOCTL #ifdef CONFIG_ARCH_PHY_INTERRUPT case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { @@ -3005,6 +3006,7 @@ static int stm32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) ret = stm32_phywrite(req->phy_id, req->reg_num, req->val_in); } break; +#endif /* CONFIG_NETDEV_PHY_IOCTL */ default: ret = -ENOTTY; @@ -3013,7 +3015,7 @@ static int stm32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) return ret; } -#endif /* CONFIG_NETDEV_PHY_IOCTL */ +#endif /* CONFIG_NETDEV_IOCTL */ /**************************************************************************** * Function: stm32_phyintenable @@ -4095,7 +4097,7 @@ int stm32_ethinitialize(int intf) priv->dev.d_addmac = stm32_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = stm32_rmmac; /* Remove multicast MAC address */ #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL priv->dev.d_ioctl = stm32_ioctl; /* Support PHY ioctl() calls */ #endif priv->dev.d_private = (void *)g_stm32ethmac; /* Used to recover private state from dev */ diff --git a/arch/arm/src/tiva/tm4c_ethernet.c b/arch/arm/src/tiva/tm4c_ethernet.c index 3458db363cd..be2dd123502 100644 --- a/arch/arm/src/tiva/tm4c_ethernet.c +++ b/arch/arm/src/tiva/tm4c_ethernet.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/tiva/tm4c_ethernet.c * - * Copyright (C) 2014-2015, 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2015, 2017-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -733,7 +733,7 @@ static int tiva_addmac(struct net_driver_s *dev, FAR const uint8_t *mac); #ifdef CONFIG_NET_IGMP static int tiva_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac); #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int tiva_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif @@ -2860,59 +2860,61 @@ static void tiva_rxdescinit(FAR struct tiva_ethmac_s *priv) * ****************************************************************************/ -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL static int tiva_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { int ret; switch (cmd) - { -#ifdef CONFIG_TIVA_PHY_INTERRUPTS - case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - - ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); - if (ret == OK) +#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_TIVA_PHY_INTERRUPTS + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { - /* Enable PHY link up/down interrupts */ + struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); - tiva_phy_intenable(true); + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + tiva_phy_intenable(true); + } } - } - break; + break; #endif - case SIOCGMIIPHY: /* Get MII PHY address */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - req->phy_id = CONFIG_TIVA_PHYADDR; - ret = OK; - } - break; + case SIOCGMIIPHY: /* Get MII PHY address */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + req->phy_id = CONFIG_TIVA_PHYADDR; + ret = OK; + } + break; - case SIOCGMIIREG: /* Get register from MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - ret = tiva_phyread(req->phy_id, req->reg_num, &req->val_out); - } - break; + case SIOCGMIIREG: /* Get register from MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + ret = tiva_phyread(req->phy_id, req->reg_num, &req->val_out); + } + break; - case SIOCSMIIREG: /* Set register in MII PHY */ - { - struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); - ret = tiva_phywrite(req->phy_id, req->reg_num, req->val_in); - } - break; + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + ret = tiva_phywrite(req->phy_id, req->reg_num, req->val_in); + } + break; +#endif /* CONFIG_NETDEV_PHY_IOCTL */ - default: - ret = -ENOTTY; - break; - } + default: + ret = -ENOTTY; + break; + } return ret; } -#endif /* CONFIG_NETDEV_PHY_IOCTL */ +#endif /* CONFIG_NETDEV_IOCTL */ /**************************************************************************** * Function: tiva_phy_intenable @@ -4040,7 +4042,7 @@ int tiva_ethinitialize(int intf) priv->dev.d_addmac = tiva_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = tiva_rmmac; /* Remove multicast MAC address */ #endif -#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_NETDEV_IOCTL priv->dev.d_ioctl = tiva_ioctl; /* Support PHY ioctl() calls */ #endif priv->dev.d_private = (void *)g_tiva_ethmac; /* Used to recover private state from dev */ diff --git a/arch/hc/src/m9s12/m9s12_ethernet.c b/arch/hc/src/m9s12/m9s12_ethernet.c index 3b3fcf0d741..a56a267c910 100644 --- a/arch/hc/src/m9s12/m9s12_ethernet.c +++ b/arch/hc/src/m9s12/m9s12_ethernet.c @@ -772,7 +772,7 @@ int emac_initialize(int intf) #endif priv->d_dev.d_private = (void*)g_emac; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->d_txpoll = wd_create(); /* Create periodic poll timer */ priv->d_txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/arch/mips/src/pic32mx/pic32mx-ethernet.c b/arch/mips/src/pic32mx/pic32mx-ethernet.c index f436b298b6a..d772a8ba14b 100644 --- a/arch/mips/src/pic32mx/pic32mx-ethernet.c +++ b/arch/mips/src/pic32mx/pic32mx-ethernet.c @@ -3348,7 +3348,7 @@ static inline int pic32mx_ethinitialize(int intf) priv->pd_irqsrc = ??; /* Ethernet controller IRQ source number */ #endif - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->pd_txpoll = wd_create(); /* Create periodic poll timer */ priv->pd_txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/arch/mips/src/pic32mz/pic32mz-ethernet.c b/arch/mips/src/pic32mz/pic32mz-ethernet.c index 5e1b2f5e046..046b2861e93 100644 --- a/arch/mips/src/pic32mz/pic32mz-ethernet.c +++ b/arch/mips/src/pic32mz/pic32mz-ethernet.c @@ -3384,7 +3384,7 @@ static inline int pic32mz_ethinitialize(int intf) priv->pd_irqsrc = ??; /* Ethernet controller IRQ source number */ #endif - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->pd_txpoll = wd_create(); /* Create periodic poll timer */ priv->pd_txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/arch/misoc/src/common/misoc_net.c b/arch/misoc/src/common/misoc_net.c index a7df3654352..595cbbbcff2 100644 --- a/arch/misoc/src/common/misoc_net.c +++ b/arch/misoc/src/common/misoc_net.c @@ -1172,7 +1172,7 @@ int misoc_net_initialize(int intf) #endif priv->misoc_net_dev.d_private = (FAR void *)g_misoc_net; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->misoc_net_txpoll = wd_create(); /* Create periodic poll timer */ priv->misoc_net_txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/arch/z80/src/ez80/ez80_emac.c b/arch/z80/src/ez80/ez80_emac.c index 55896c08ff6..7ef110f8112 100644 --- a/arch/z80/src/ez80/ez80_emac.c +++ b/arch/z80/src/ez80/ez80_emac.c @@ -2537,7 +2537,7 @@ int up_netinitialize(void) #endif priv->dev.d_private = (FAR void*)&g_emac; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->txpoll = wd_create(); /* Create periodic poll timer */ priv->txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/drivers/net/dm90x0.c b/drivers/net/dm90x0.c index b6cfa6dfb74..c55c222a99c 100644 --- a/drivers/net/dm90x0.c +++ b/drivers/net/dm90x0.c @@ -1948,7 +1948,7 @@ int dm9x_initialize(void) #endif g_dm9x[0].dm_dev.d_private = (FAR void *)g_dm9x; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ g_dm9x[0].dm_txpoll = wd_create(); /* Create periodic poll timer */ g_dm9x[0].dm_txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index 23c4c770671..9c45d4b115b 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c @@ -2632,7 +2632,7 @@ int enc_initialize(FAR struct spi_dev_s *spi, #endif priv->dev.d_private = priv; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->txpoll = wd_create(); /* Create periodic poll timer */ priv->txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/drivers/net/encx24j600.c b/drivers/net/encx24j600.c index 5c2b590e2e5..31732a0b687 100644 --- a/drivers/net/encx24j600.c +++ b/drivers/net/encx24j600.c @@ -2815,7 +2815,7 @@ int enc_initialize(FAR struct spi_dev_s *spi, #endif priv->dev.d_private = priv; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->txpoll = wd_create(); /* Create periodic poll timer */ priv->txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/drivers/net/ftmac100.c b/drivers/net/ftmac100.c index 9acc93d643b..cb7749706f2 100644 --- a/drivers/net/ftmac100.c +++ b/drivers/net/ftmac100.c @@ -1554,7 +1554,7 @@ int ftmac100_initialize(int intf) #endif priv->ft_dev.d_private = (FAR void *)g_ftmac100; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->ft_txpoll = wd_create(); /* Create periodic poll timer */ priv->ft_txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 6c5beeba5e0..f397f847df4 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -891,7 +891,7 @@ static int tun_dev_init(FAR struct tun_device_s *priv, FAR struct file *filep, nxsem_setprotocol(&priv->read_wait_sem, SEM_PRIO_NONE); - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->txpoll = wd_create(); /* Create periodic poll timer */ diff --git a/drivers/wireless/ieee802154/xbee/xbee_netdev.c b/drivers/wireless/ieee802154/xbee/xbee_netdev.c index d408d21ec34..1c0c682057d 100644 --- a/drivers/wireless/ieee802154/xbee/xbee_netdev.c +++ b/drivers/wireless/ieee802154/xbee/xbee_netdev.c @@ -1392,7 +1392,7 @@ int xbee_netdev_register(XBEEHANDLE xbee) #endif dev->d_private = (FAR void *)priv; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->xd_mac = xbee; /* Save the MAC interface instance */ priv->xd_txpoll = wd_create(); /* Create periodic poll timer */ diff --git a/drivers/wireless/spirit/drivers/spirit_netdev.c b/drivers/wireless/spirit/drivers/spirit_netdev.c index 9e9b0655c08..e951f3fe0a9 100644 --- a/drivers/wireless/spirit/drivers/spirit_netdev.c +++ b/drivers/wireless/spirit/drivers/spirit_netdev.c @@ -2812,7 +2812,7 @@ int spirit_netdev_initialize(FAR struct spi_dev_s *spi, priv->lower = lower; - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->txpoll = wd_create(); /* Create periodic poll timer */ priv->txtimeout = wd_create(); /* Create TX timeout timer */ diff --git a/wireless/ieee802154/mac802154_netdev.c b/wireless/ieee802154/mac802154_netdev.c index 953c37f26da..aa4abe8ab2a 100644 --- a/wireless/ieee802154/mac802154_netdev.c +++ b/wireless/ieee802154/mac802154_netdev.c @@ -1400,7 +1400,7 @@ int mac802154netdev_register(MACHANDLE mac) #endif dev->d_private = (FAR void *)priv; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->md_mac = mac; /* Save the MAC interface instance */ priv->md_txpoll = wd_create(); /* Create periodic poll timer */ From 12d7125b759b02f50d53bf806376a940e729a071 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 22 Jan 2018 11:11:23 -0600 Subject: [PATCH 24/40] net/tcp: Write buffering logic should not wait for a free buffer if the socket was opened non-blocking. Also, rename the TCP write buffering macros from WRB_* to TCPWB_* to make room in the namespace for write buffering with other protocols. --- TODO | 20 +++--- net/tcp/tcp.h | 37 ++++++------ net/tcp/tcp_send_buffered.c | 117 ++++++++++++++++++++---------------- net/tcp/tcp_wrbuffer_dump.c | 6 +- 4 files changed, 98 insertions(+), 82 deletions(-) diff --git a/TODO b/TODO index 4d46a3e5b0b..dd4dca76ac2 100644 --- a/TODO +++ b/TODO @@ -332,17 +332,17 @@ o Task/Scheduler (sched/) alternating between a high and a low priority. In either state, it may have its priority boosted. However, under some circumstances, it is impossible in the current design to - switch to the correct correct priority if a semaphore is - participating in priority inheritance: + switch to the correct priority if a semaphore held by the + sporadic thread is participating in priority inheritance: - There is an when switching from the high to the low priority - state. If the priority was NOT boosted above the higher - priority, it still may still need to boosted with respect to - the lower priority. If the highest priority thread waiting - on a semaphore held by the sporadic thread is higher in - priority than the low priority but less than the higher - priority, then new thread priority should be set to that - middle priority, not to the lower priority + There is an issue when switching from the high to the low + priority state. If the priority was NOT boosted above the + higher priority, it still may still need to boosted with + respect to the lower priority. If the highest priority + thread waiting on a semaphore held by the sporadic thread is + higher in priority than the low priority but less than the + higher priority, then new thread priority should be set to + that middle priority, not to the lower priority. In order to do this we would need to know the highest priority from among all tasks waiting for the all semaphores diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index 91e13ffe7ba..bf8948da73a 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -1,7 +1,7 @@ /**************************************************************************** * net/tcp/tcp.h * - * Copyright (C) 2014-2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2016, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -77,23 +77,26 @@ #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* TCP write buffer access macros */ -# define WRB_SEQNO(wrb) ((wrb)->wb_seqno) -# define WRB_PKTLEN(wrb) ((wrb)->wb_iob->io_pktlen) -# define WRB_SENT(wrb) ((wrb)->wb_sent) -# define WRB_NRTX(wrb) ((wrb)->wb_nrtx) -# define WRB_IOB(wrb) ((wrb)->wb_iob) -# define WRB_COPYOUT(wrb,dest,n) (iob_copyout(dest,(wrb)->wb_iob,(n),0)) -# define WRB_COPYIN(wrb,src,n) (iob_copyin((wrb)->wb_iob,src,(n),0,false)) +# define TCPWB_SEQNO(wrb) ((wrb)->wb_seqno) +# define TCPWB_PKTLEN(wrb) ((wrb)->wb_iob->io_pktlen) +# define TCPWB_SENT(wrb) ((wrb)->wb_sent) +# define TCPWB_NRTX(wrb) ((wrb)->wb_nrtx) +# define TCPWB_IOB(wrb) ((wrb)->wb_iob) +# define TCPWB_COPYOUT(wrb,dest,n) (iob_copyout(dest,(wrb)->wb_iob,(n),0)) +# define TCPWB_COPYIN(wrb,src,n) \ + (iob_copyin((wrb)->wb_iob,src,(n),0,false)) +# define TCPWB_TRYCOPYIN(wrb,src,n) \ + (iob_trycopyin((wrb)->wb_iob,src,(n),0,false)) -# define WRB_TRIM(wrb,n) \ - do { (wrb)->wb_iob = iob_trimhead((wrb)->wb_iob,(n)); } while (0) +# define TCPWB_TRIM(wrb,n) \ + do { (wrb)->wb_iob = iob_trimhead((wrb)->wb_iob,(n)); } while (0) #ifdef CONFIG_DEBUG_FEATURES -# define WRB_DUMP(msg,wrb,len,offset) \ +# define TCPWB_DUMP(msg,wrb,len,offset) \ tcp_wrbuffer_dump(msg,wrb,len,offset) -#else -# define WRB_DUMP(msg,wrb,len,offset) -#endif +# else +# define TCPWB_DUMP(msg,wrb,len,offset) +# endif #endif /**************************************************************************** @@ -438,7 +441,7 @@ int tcp_local_ipv6_device(FAR struct tcp_conn_s *conn); * * Description: * Select the network driver to use with the IPv6 TCP transaction based - * on the remotely conected IPv6 address + * on the remotely connected IPv6 address * * Input Parameters: * conn - TCP connection structure. The remotely connected address, raddr, @@ -558,7 +561,7 @@ int tcp_start_monitor(FAR struct socket *psock); * * Description: * Stop monitoring TCP connection changes for a sockets associated with - * a given TCP connection stucture. + * a given TCP connection structure. * * Input Parameters: * conn - The TCP connection of interest @@ -1282,7 +1285,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, * * Returned Value: * OK - * At least one byte of data could be succesfully written. + * At least one byte of data could be successfully written. * -EWOULDBLOCK * There is no room in the output buffer. * -EBADF diff --git a/net/tcp/tcp_send_buffered.c b/net/tcp/tcp_send_buffered.c index df54f338c37..5abb417e701 100644 --- a/net/tcp/tcp_send_buffered.c +++ b/net/tcp/tcp_send_buffered.c @@ -1,7 +1,7 @@ /**************************************************************************** * net/tcp/tcp_send_buffered.c * - * Copyright (C) 2007-2014, 2016-2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2014, 2016-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * Jason Jiang * @@ -98,8 +98,8 @@ # define BUF_DUMP(msg,buf,len) lib_dumpbuffer(msg,buf,len) #else # define BUF_DUMP(msg,buf,len) -# undef WRB_DUMP -# define WRB_DUMP(msg,wrb,len,offset) +# undef TCPWB_DUMP +# define TCPWB_DUMP(msg,wrb,len,offset) #endif /**************************************************************************** @@ -135,7 +135,7 @@ static void psock_insert_segment(FAR struct tcp_wrbuffer_s *wrb, for (itr = sq_peek(q); itr; itr = sq_next(itr)) { FAR struct tcp_wrbuffer_s *wrb0 = (FAR struct tcp_wrbuffer_s *)itr; - if (WRB_SEQNO(wrb0) < WRB_SEQNO(wrb)) + if (TCPWB_SEQNO(wrb0) < TCPWB_SEQNO(wrb)) { insert = itr; } @@ -417,13 +417,14 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * the write buffer has been ACKed. */ - if (ackno > WRB_SEQNO(wrb)) + if (ackno > TCPWB_SEQNO(wrb)) { /* Get the sequence number at the end of the data */ - lastseq = WRB_SEQNO(wrb) + WRB_PKTLEN(wrb); + lastseq = TCPWB_SEQNO(wrb) + TCPWB_PKTLEN(wrb); ninfo("ACK: wrb=%p seqno=%u lastseq=%u pktlen=%u ackno=%u\n", - wrb, WRB_SEQNO(wrb), lastseq, WRB_PKTLEN(wrb), ackno); + wrb, TCPWB_SEQNO(wrb), lastseq, TCPWB_PKTLEN(wrb), + ackno); /* Has the entire buffer been ACKed? */ @@ -449,24 +450,24 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * buffers in the chain. */ - trimlen = ackno - WRB_SEQNO(wrb); - if (trimlen > WRB_SENT(wrb)) + trimlen = ackno - TCPWB_SEQNO(wrb); + if (trimlen > TCPWB_SENT(wrb)) { /* More data has been ACKed then we have sent? */ - trimlen = WRB_SENT(wrb); + trimlen = TCPWB_SENT(wrb); } ninfo("ACK: wrb=%p trim %u bytes\n", wrb, trimlen); - WRB_TRIM(wrb, trimlen); - WRB_SEQNO(wrb) = ackno; - WRB_SENT(wrb) -= trimlen; + TCPWB_TRIM(wrb, trimlen); + TCPWB_SEQNO(wrb) = ackno; + TCPWB_SENT(wrb) -= trimlen; /* Set the new sequence number for what remains */ ninfo("ACK: wrb=%p seqno=%u pktlen=%u\n", - wrb, WRB_SEQNO(wrb), WRB_PKTLEN(wrb)); + wrb, TCPWB_SEQNO(wrb), TCPWB_PKTLEN(wrb)); } } } @@ -477,31 +478,31 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, */ wrb = (FAR struct tcp_wrbuffer_s *)sq_peek(&conn->write_q); - if (wrb && WRB_SENT(wrb) > 0 && ackno > WRB_SEQNO(wrb)) + if (wrb && TCPWB_SENT(wrb) > 0 && ackno > TCPWB_SEQNO(wrb)) { uint32_t nacked; /* Number of bytes that were ACKed */ - nacked = ackno - WRB_SEQNO(wrb); - if (nacked > WRB_SENT(wrb)) + nacked = ackno - TCPWB_SEQNO(wrb); + if (nacked > TCPWB_SENT(wrb)) { /* More data has been ACKed then we have sent? ASSERT? */ - nacked = WRB_SENT(wrb); + nacked = TCPWB_SENT(wrb); } ninfo("ACK: wrb=%p seqno=%u nacked=%u sent=%u ackno=%u\n", - wrb, WRB_SEQNO(wrb), nacked, WRB_SENT(wrb), ackno); + wrb, TCPWB_SEQNO(wrb), nacked, TCPWB_SENT(wrb), ackno); /* Trim the ACKed bytes from the beginning of the write buffer. */ - WRB_TRIM(wrb, nacked); - WRB_SEQNO(wrb) = ackno; - WRB_SENT(wrb) -= nacked; + TCPWB_TRIM(wrb, nacked); + TCPWB_SEQNO(wrb) = ackno; + TCPWB_SENT(wrb) -= nacked; ninfo("ACK: wrb=%p seqno=%u pktlen=%u sent=%u\n", - wrb, WRB_SEQNO(wrb), WRB_PKTLEN(wrb), WRB_SENT(wrb)); + wrb, TCPWB_SEQNO(wrb), TCPWB_PKTLEN(wrb), TCPWB_SENT(wrb)); } } @@ -543,16 +544,16 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, */ wrb = (FAR struct tcp_wrbuffer_s *)sq_peek(&conn->write_q); - ninfo("REXMIT: wrb=%p sent=%u\n", wrb, wrb ? WRB_SENT(wrb) : 0); + ninfo("REXMIT: wrb=%p sent=%u\n", wrb, wrb ? TCPWB_SENT(wrb) : 0); - if (wrb != NULL && WRB_SENT(wrb) > 0) + if (wrb != NULL && TCPWB_SENT(wrb) > 0) { FAR struct tcp_wrbuffer_s *tmp; uint16_t sent; /* Yes.. Reset the number of bytes sent sent from the write buffer */ - sent = WRB_SENT(wrb); + sent = TCPWB_SENT(wrb); if (conn->unacked > sent) { conn->unacked -= sent; @@ -571,16 +572,16 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, conn->sent = 0; } - WRB_SENT(wrb) = 0; + TCPWB_SENT(wrb) = 0; ninfo("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n", - wrb, WRB_SENT(wrb), conn->unacked, conn->sent); + wrb, TCPWB_SENT(wrb), conn->unacked, conn->sent); /* Increment the retransmit count on this write buffer. */ - if (++WRB_NRTX(wrb) >= TCP_MAXRTX) + if (++TCPWB_NRTX(wrb) >= TCP_MAXRTX) { nwarn("WARNING: Expiring wrb=%p nrtx=%u\n", - wrb, WRB_NRTX(wrb)); + wrb, TCPWB_NRTX(wrb)); /* The maximum retry count as been exhausted. Remove the write * buffer at the head of the queue. @@ -618,7 +619,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, /* Reset the number of bytes sent sent from the write buffer */ - sent = WRB_SENT(wrb); + sent = TCPWB_SENT(wrb); if (conn->unacked > sent) { conn->unacked -= sent; @@ -637,16 +638,16 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, conn->sent = 0; } - WRB_SENT(wrb) = 0; + TCPWB_SENT(wrb) = 0; ninfo("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n", - wrb, WRB_SENT(wrb), conn->unacked, conn->sent); + wrb, TCPWB_SENT(wrb), conn->unacked, conn->sent); /* Free any write buffers that have exceed the retry count */ - if (++WRB_NRTX(wrb) >= TCP_MAXRTX) + if (++TCPWB_NRTX(wrb) >= TCP_MAXRTX) { nwarn("WARNING: Expiring wrb=%p nrtx=%u\n", - wrb, WRB_NRTX(wrb)); + wrb, TCPWB_NRTX(wrb)); /* Return the write buffer to the free list */ @@ -671,7 +672,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * is pulled from the write_q again. */ - ninfo("REXMIT: Moving wrb=%p nrtx=%u\n", wrb, WRB_NRTX(wrb)); + ninfo("REXMIT: Moving wrb=%p nrtx=%u\n", wrb, TCPWB_NRTX(wrb)); psock_insert_segment(wrb, &conn->write_q); } @@ -726,7 +727,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * window size. */ - sndlen = WRB_PKTLEN(wrb) - WRB_SENT(wrb); + sndlen = TCPWB_PKTLEN(wrb) - TCPWB_SENT(wrb); if (sndlen > conn->mss) { sndlen = conn->mss; @@ -738,16 +739,16 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, } ninfo("SEND: wrb=%p pktlen=%u sent=%u sndlen=%u\n", - wrb, WRB_PKTLEN(wrb), WRB_SENT(wrb), sndlen); + wrb, TCPWB_PKTLEN(wrb), TCPWB_SENT(wrb), sndlen); /* Set the sequence number for this segment. If we are * retransmitting, then the sequence number will already * be set for this write buffer. */ - if (WRB_SEQNO(wrb) == (unsigned)-1) + if (TCPWB_SEQNO(wrb) == (unsigned)-1) { - WRB_SEQNO(wrb) = conn->isn + conn->sent; + TCPWB_SEQNO(wrb) = conn->isn + conn->sent; } /* The TCP stack updates sndseq on receipt of ACK *before* @@ -757,7 +758,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * before the packet is sent. */ - tcp_setsequence(conn->sndseq, WRB_SEQNO(wrb) + WRB_SENT(wrb)); + tcp_setsequence(conn->sndseq, TCPWB_SEQNO(wrb) + TCPWB_SENT(wrb)); #ifdef NEED_IPDOMAIN_SUPPORT /* If both IPv4 and IPv6 support are enabled, then we will need to @@ -773,7 +774,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * won't actually happen until the polling cycle completes). */ - devif_iob_send(dev, WRB_IOB(wrb), sndlen, WRB_SENT(wrb)); + devif_iob_send(dev, TCPWB_IOB(wrb), sndlen, TCPWB_SENT(wrb)); /* Remember how much data we send out now so that we know * when everything has been acknowledged. Just increment @@ -795,21 +796,21 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, } ninfo("SEND: wrb=%p nrtx=%u unacked=%u sent=%u\n", - wrb, WRB_NRTX(wrb), conn->unacked, conn->sent); + wrb, TCPWB_NRTX(wrb), conn->unacked, conn->sent); /* Increment the count of bytes sent from this write buffer */ - WRB_SENT(wrb) += sndlen; + TCPWB_SENT(wrb) += sndlen; ninfo("SEND: wrb=%p sent=%u pktlen=%u\n", - wrb, WRB_SENT(wrb), WRB_PKTLEN(wrb)); + wrb, TCPWB_SENT(wrb), TCPWB_PKTLEN(wrb)); /* Remove the write buffer from the write queue if the * last of the data has been sent from the buffer. */ - DEBUGASSERT(WRB_SENT(wrb) <= WRB_PKTLEN(wrb)); - if (WRB_SENT(wrb) >= WRB_PKTLEN(wrb)) + DEBUGASSERT(TCPWB_SENT(wrb) <= TCPWB_PKTLEN(wrb)); + if (TCPWB_SENT(wrb) >= TCPWB_PKTLEN(wrb)) { FAR struct tcp_wrbuffer_s *tmp; @@ -1060,13 +1061,25 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, /* Initialize the write buffer */ - WRB_SEQNO(wrb) = (unsigned)-1; - WRB_NRTX(wrb) = 0; - result = WRB_COPYIN(wrb, (FAR uint8_t *)buf, len); + TCPWB_SEQNO(wrb) = (unsigned)-1; + TCPWB_NRTX(wrb) = 0; + + /* Copy the user data into the write buffer. We cannot wait for + * buffer space if the socket was opened non-blocking. + */ + + if (_SS_ISNONBLOCK(psock->s_flags)) + { + result = TCPWB_TRYCOPYIN(wrb, (FAR uint8_t *)buf, len); + } + else + { + result = TCPWB_COPYIN(wrb, (FAR uint8_t *)buf, len); + } /* Dump I/O buffer chain */ - WRB_DUMP("I/O buffer chain", wrb, WRB_PKTLEN(wrb), 0); + TCPWB_DUMP("I/O buffer chain", wrb, TCPWB_PKTLEN(wrb), 0); /* psock_send_eventhandler() will send data in FIFO order from the * conn->write_q @@ -1074,7 +1087,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, sq_addlast(&wrb->wb_node, &conn->write_q); ninfo("Queued WRB=%p pktlen=%u write_q(%p,%p)\n", - wrb, WRB_PKTLEN(wrb), + wrb, TCPWB_PKTLEN(wrb), conn->write_q.head, conn->write_q.tail); /* Notify the device driver of the availability of TX data */ diff --git a/net/tcp/tcp_wrbuffer_dump.c b/net/tcp/tcp_wrbuffer_dump.c index ad92bfb904f..a27bb60253d 100644 --- a/net/tcp/tcp_wrbuffer_dump.c +++ b/net/tcp/tcp_wrbuffer_dump.c @@ -1,7 +1,7 @@ /**************************************************************************** * net/tcp/tcp_wrbuffer_dump.c * - * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2014, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -64,8 +64,8 @@ void tcp_wrbuffer_dump(FAR const char *msg, FAR struct tcp_wrbuffer_s *wrb, unsigned int len, unsigned int offset) { syslog(LOG_DEBUG, "%s: wrb=%p segno=%d sent=%d nrtx=%d\n", - msg, wrb, WRB_SEQNO(wrb), WRB_SENT(wrb), WRB_NRTX(wrb)); - iob_dump("I/O Buffer Chain", WRB_IOB(wrb), len, offset); + msg, wrb, TCPWB_SEQNO(wrb), TCPWB_SENT(wrb), TCPWB_NRTX(wrb)); + iob_dump("I/O Buffer Chain", TCPWB_IOB(wrb), len, offset); } #endif /* CONFIG_DEBUG_FEATURES */ From 0406fff8883097c7490eadc4ee56080882cea9bd Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 22 Jan 2018 14:14:32 -0600 Subject: [PATCH 25/40] net/udp: Remove some conditional logic that was true if there is only a single network device, but not true in the multi-device context. --- net/udp/udp_psock_sendto.c | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/net/udp/udp_psock_sendto.c b/net/udp/udp_psock_sendto.c index 4710fb36d68..ff362a310e4 100644 --- a/net/udp/udp_psock_sendto.c +++ b/net/udp/udp_psock_sendto.c @@ -70,36 +70,16 @@ # define NEED_IPDOMAIN_SUPPORT 1 #endif -/* Timeouts on sendto() do not make sense. Each polling cycle from the - * driver is an opportunity to send a packet. If the driver is not polling, - * then the network is not up (and there are no polling cycles to drive - * the timeout). - * - * There is a remote possibility that if there is a lot of other network - * traffic that a UDP sendto could get delayed, but I would not expect this - * generate a timeout. - */ - -#undef CONFIG_NET_SENDTO_TIMEOUT - -/* If supported, the sendto timeout function would depend on socket options - * and a system clock. - */ - -#ifndef CONFIG_NET_SOCKOPTS -# undef CONFIG_NET_SENDTO_TIMEOUT -#endif - /**************************************************************************** * Private Types ****************************************************************************/ struct sendto_s { -#if defined(CONFIG_NET_SENDTO_TIMEOUT) || defined(NEED_IPDOMAIN_SUPPORT) +#if defined(CONFIG_NET_SOCKOPTS) || defined(NEED_IPDOMAIN_SUPPORT) FAR struct socket *st_sock; /* Points to the parent socket structure */ #endif -#ifdef CONFIG_NET_SENDTO_TIMEOUT +#ifdef CONFIG_NET_SOCKOPTS systime_t st_time; /* Last send time for determining timeout */ #endif FAR struct devif_callback_s *st_cb; /* Reference to callback instance */ @@ -130,7 +110,7 @@ struct sendto_s * ****************************************************************************/ -#ifdef CONFIG_NET_SENDTO_TIMEOUT +#ifdef CONFIG_NET_SOCKOPTS static inline int send_timeout(FAR struct sendto_s *pstate) { FAR struct socket *psock; @@ -151,7 +131,7 @@ static inline int send_timeout(FAR struct sendto_s *pstate) return FALSE; } -#endif /* CONFIG_NET_SENDTO_TIMEOUT */ +#endif /* CONFIG_NET_SOCKOPTS */ /**************************************************************************** * Name: sendto_ipselect @@ -254,7 +234,7 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, * polling cycle and check again. */ -#ifdef CONFIG_NET_SENDTO_TIMEOUT +#ifdef CONFIG_NET_SOCKOPTS if (send_timeout(pstate)) { /* Yes.. report the timeout */ @@ -263,7 +243,7 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, pstate->st_sndlen = -ETIMEDOUT; } else -#endif /* CONFIG_NET_SENDTO_TIMEOUT */ +#endif /* CONFIG_NET_SOCKOPTS */ { /* No timeout. Just wait for the next polling cycle */ @@ -403,7 +383,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, state.st_buflen = len; state.st_buffer = buf; -#if defined(CONFIG_NET_SENDTO_TIMEOUT) || defined(NEED_IPDOMAIN_SUPPORT) +#if defined(CONFIG_NET_SOCKOPTS) || defined(NEED_IPDOMAIN_SUPPORT) /* Save the reference to the socket structure if it will be needed for * asynchronous processing. */ @@ -411,7 +391,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, state.st_sock = psock; #endif -#ifdef CONFIG_NET_SENDTO_TIMEOUT +#ifdef CONFIG_NET_SOCKOPTS /* Set the initial time for calculating timeouts */ state.st_time = clock_systimer(); From fef255e5be8f2956c8abb99f00aa076668336b66 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 22 Jan 2018 18:32:02 -0600 Subject: [PATCH 26/40] This commit adds an as-of-yet untested implemented of UDP write buffering. Squashed commit of the following: net/udp: Address most of the issues with UDP write buffering. There is a remaining issue with handling one network going down in a multi-network environment. None of this has been test but it is certainly ready for test. Hence, the feature is marked EXPERIMENTAL. net/udp: Some baby steps toward a corrected write buffering design. net/udp: Remove pesky write buffer macros. Eliminate trailing space at the end of lines. net/udp: A little more UDP write buffering logic. Still at least on big gaping hole in the design. net/udp: Undefined CONFIG_NET_SENDTO_TIMEOUT. net/udp: Crude, naive port of the TCP write buffering logic into UDP. This commit is certainly non-functional and is simply a starting point for the implementatin of UDP write buffering. net/udp: Rename udp/udp_psock_sendto.c udp/udp_psock_sendto_unbuffered.c. --- include/nuttx/net/net.h | 4 +- mm/iob/Kconfig | 14 +- net/Kconfig | 8 + net/inet/inet_sockif.c | 2 +- net/net_initialize.c | 4 + net/socket/socket.c | 2 +- net/tcp/Kconfig | 4 +- net/udp/Kconfig | 50 ++ net/udp/Make.defs | 19 +- net/udp/udp.h | 129 ++- net/udp/udp_conn.c | 21 +- net/udp/udp_psock_sendto_buffered.c | 821 ++++++++++++++++++ ...sendto.c => udp_psock_sendto_unbuffered.c} | 11 +- net/udp/udp_wrbuffer.c | 217 +++++ net/udp/udp_wrbuffer_dump.c | 70 ++ 15 files changed, 1354 insertions(+), 22 deletions(-) create mode 100644 net/udp/udp_psock_sendto_buffered.c rename net/udp/{udp_psock_sendto.c => udp_psock_sendto_unbuffered.c} (98%) create mode 100644 net/udp/udp_wrbuffer.c create mode 100644 net/udp/udp_wrbuffer_dump.c diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h index fb4de5c4737..9e1eec09db0 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -208,8 +208,8 @@ struct socket FAR const struct sock_intf_s *s_sockif; -#ifdef CONFIG_NET_TCP_WRITE_BUFFERS - /* Callback instance for TCP send */ +#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) || defined(CONFIG_NET_UDP_WRITE_BUFFERS) + /* Callback instance for TCP send() or UDP sendto() */ FAR struct devif_callback_s *s_sndcb; #endif diff --git a/mm/iob/Kconfig b/mm/iob/Kconfig index b64f90e3ce8..62893db0940 100644 --- a/mm/iob/Kconfig +++ b/mm/iob/Kconfig @@ -16,9 +16,9 @@ if MM_IOB config IOB_NBUFFERS int "Number of pre-allocated I/O buffers" - default 24 if (NET_TCP_WRITE_BUFFERS && !NET_TCP_READAHEAD) || (!NET_TCP_WRITE_BUFFERS && NET_TCP_READAHEAD) - default 36 if NET_TCP_WRITE_BUFFERS && NET_TCP_READAHEAD - default 8 if !NET_TCP_WRITE_BUFFERS && !NET_TCP_READAHEAD + default 24 if (NET_WRITE_BUFFERS && !NET_READAHEAD) || (!NET_WRITE_BUFFERS && NET_READAHEAD) + default 36 if NET_WRITE_BUFFERS && NET_READAHEAD + default 8 if !NET_WRITE_BUFFERS && !NET_READAHEAD ---help--- Each packet is represented by a series of small I/O buffers in a chain. This setting determines the number of preallocated I/O @@ -34,8 +34,8 @@ config IOB_BUFSIZE config IOB_NCHAINS int "Number of pre-allocated I/O buffer chain heads" - default 0 if !NET_TCP_READAHEAD && !NET_UDP_READAHEAD - default 8 if NET_TCP_READAHEAD || NET_UDP_READAHEAD + default 0 if !NET_READAHEAD && !NET_UDP_READAHEAD + default 8 if NET_READAHEAD || NET_UDP_READAHEAD ---help--- These tiny nodes are used as "containers" to support queueing of I/O buffer chains. This will limit the number of I/O transactions @@ -49,8 +49,8 @@ config IOB_NCHAINS config IOB_THROTTLE int "I/O buffer throttle value" - default 0 if !NET_TCP_WRITE_BUFFERS || !NET_TCP_READAHEAD - default 8 if NET_TCP_WRITE_BUFFERS && NET_TCP_READAHEAD + default 0 if !NET_WRITE_BUFFERS || !NET_READAHEAD + default 8 if NET_WRITE_BUFFERS && NET_READAHEAD ---help--- TCP write buffering and read-ahead buffer use the same pool of free I/O buffers. In order to prevent uncontrolled incoming TCP packets diff --git a/net/Kconfig b/net/Kconfig index 48163d26bfa..3c4f969486b 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -11,6 +11,14 @@ config ARCH_HAVE_PHY bool default n +config NET_WRITE_BUFFERS + bool + default n + +config NET_READAHEAD + bool + default n + config NET bool "Networking support" default n diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c index 761a65bb1ba..9ab4be7336e 100644 --- a/net/inet/inet_sockif.c +++ b/net/inet/inet_sockif.c @@ -1146,7 +1146,7 @@ static ssize_t inet_sendto(FAR struct socket *psock, FAR const void *buf, #if defined(CONFIG_NET_6LOWPAN) /* Try 6LoWPAN UDP packet sendto() */ - nsent = psock_6lowpan_udp_sendto(psock, buf, len, flags, to, tolen); + nsent = psock_6lowpan_udp_sendto(psock, buf, len, flags, to, minlen); #ifdef NET_UDP_HAVE_STACK if (nsent < 0) diff --git a/net/net_initialize.c b/net/net_initialize.c index 4d0105acf7f..0447f88dfcf 100644 --- a/net/net_initialize.c +++ b/net/net_initialize.c @@ -172,6 +172,10 @@ void net_setup(void) /* Initialize the UDP connection structures */ udp_initialize(); + +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS + udp_wrbuffer_initialize(); +#endif #endif #ifdef CONFIG_NET_IGMP diff --git a/net/socket/socket.c b/net/socket/socket.c index 539ef0b2160..caaed28320b 100644 --- a/net/socket/socket.c +++ b/net/socket/socket.c @@ -105,7 +105,7 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock) psock->s_domain = domain; psock->s_type = type; psock->s_conn = NULL; -#ifdef CONFIG_NET_TCP_WRITE_BUFFERS +#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) || defined(CONFIG_NET_UDP_WRITE_BUFFERS) psock->s_sndcb = NULL; #endif diff --git a/net/tcp/Kconfig b/net/tcp/Kconfig index 77cebe81fbe..c3647ae2898 100644 --- a/net/tcp/Kconfig +++ b/net/tcp/Kconfig @@ -70,6 +70,7 @@ config NET_MAX_LISTENPORTS config NET_TCP_READAHEAD bool "Enable TCP/IP read-ahead buffering" default y + select NET_READAHEAD select MM_IOB ---help--- Read-ahead buffers allows buffering of TCP/IP packets when there is no @@ -91,6 +92,7 @@ endif # NET_TCP_READAHEAD config NET_TCP_WRITE_BUFFERS bool "Enable TCP/IP write buffering" default n + select NET_WRITE_BUFFERS select MM_IOB ---help--- Write buffers allows buffering of ongoing TCP/IP packets, providing @@ -105,7 +107,7 @@ config NET_TCP_NWRBCHAINS int "Number of pre-allocated I/O buffer chain heads" default 8 ---help--- - These tiny nodes are used as "containers" to support queueing of + These tiny nodes are used as "containers" to support queuing of TCP write buffers. This setting will limit the number of TCP write operations that can be "in-flight" at any give time. So a good choice for this value would be the same as the maximum number of diff --git a/net/udp/Kconfig b/net/udp/Kconfig index ba710b8629e..16d40a72efa 100644 --- a/net/udp/Kconfig +++ b/net/udp/Kconfig @@ -44,7 +44,57 @@ config NET_BROADCAST config NET_UDP_READAHEAD bool "Enable UDP/IP read-ahead buffering" default y + select NET_READAHEAD select MM_IOB +config NET_UDP_WRITE_BUFFERS + bool "Enable UDP/IP write buffering" + default n + select NET_WRITE_BUFFERS + select MM_IOB + depends on EXPERIMENTAL + ---help--- + Write buffers allows buffering of ongoing UDP/IP packets, providing + for higher performance, streamed output. + + You might want to disable UDP/IP write buffering on a highly memory + memory constrained system where there are no performance issues. + +if NET_UDP_WRITE_BUFFERS + +config NET_UDP_NWRBCHAINS + int "Number of pre-allocated I/O buffer chain heads" + default 8 + ---help--- + These tiny nodes are used as "containers" to support queuing of + UDP write buffers. This setting will limit the number of UDP write + operations that can be "in-flight" at any give time. So a good + choice for this value would be the same as the maximum number of + UDP connections. + +config NET_UDP_WRBUFFER_DEBUG + bool "Force write buffer debug" + default n + depends on DEBUG_FEATURES + select IOB_DEBUG + ---help--- + This option will force debug output from UDP write buffer logic, + even without network debug output. This is not normally something + that would want to do but is convenient if you are debugging the + write buffer logic and do not want to get overloaded with other + network-related debug output. + +config NET_UDP_WRBUFFER_DUMP + bool "Force write buffer dump" + default n + depends on DEBUG_NET || NET_UDP_WRBUFFER_DEBUG + select IOB_DEBUG + ---help--- + Dump the contents of the write buffers. You do not want to do this + unless you really want to analyze the write buffer transfers in + detail. + +endif # NET_UDP_WRITE_BUFFERS + endif # NET_UDP && !NET_UDP_NO_STACK endmenu # UDP Networking diff --git a/net/udp/Make.defs b/net/udp/Make.defs index 4b3992911df..5c8918ea9a3 100644 --- a/net/udp/Make.defs +++ b/net/udp/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # net/udp/Make.defs # -# Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. +# Copyright (C) 2014-2015, 2018 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -40,7 +40,13 @@ ifneq ($(CONFIG_NET_UDP_NO_STACK),y) # Socket layer -NET_CSRCS += udp_psock_send.c udp_psock_sendto.c +NET_CSRCS += udp_psock_send.c + +ifeq ($(CONFIG_NET_UDP_WRITE_BUFFERS),y) +SOCK_CSRCS += udp_psock_sendto_buffered.c +else +SOCK_CSRCS += udp_psock_sendto_unbuffered.c +endif ifneq ($(CONFIG_DISABLE_POLL),y) ifeq ($(CONFIG_NET_UDP_READAHEAD),y) @@ -53,6 +59,15 @@ endif NET_CSRCS += udp_conn.c udp_devpoll.c udp_send.c udp_input.c udp_finddev.c NET_CSRCS += udp_callback.c udp_ipselect.c +# UDP write buffering + +ifeq ($(CONFIG_NET_UDP_WRITE_BUFFERS),y) +NET_CSRCS += udp_wrbuffer.c +ifeq ($(CONFIG_DEBUG_FEATURES),y) +NET_CSRCS += udp_wrbuffer_dump.c +endif +endif + # Include UDP build support DEPPATH += --dep-path udp diff --git a/net/udp/udp.h b/net/udp/udp.h index cb6ca378f5c..ee591ed0782 100644 --- a/net/udp/udp.h +++ b/net/udp/udp.h @@ -1,7 +1,7 @@ /**************************************************************************** * net/udp/udp.h * - * Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2015, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -45,6 +45,7 @@ #include #include +#include #include #ifdef CONFIG_NET_UDP_READAHEAD @@ -66,6 +67,17 @@ # define HAVE_UDP_POLL #endif +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS +/* UDP write buffer dump macros */ + +# ifdef CONFIG_DEBUG_FEATURES +# define UDPWB_DUMP(msg,wrb,len,offset) \ + udp_wrbuffer_dump(msg,wrb,len,offset) +# else +# define UDPWB_DUMP(msg,wrb,len,offset) +# endif +#endif + /* Allocate a new UDP data callback */ #define udp_callback_alloc(dev,conn) \ @@ -102,11 +114,38 @@ struct udp_conn_s struct iob_queue_s readahead; /* Read-ahead buffering */ #endif +#ifdef CONFIG_NET_TCP_WRITE_BUFFERS + /* Write buffering + * + * write_q - The queue of unsent I/O buffers. The head of this + * list may be partially sent. FIFO ordering. + */ + + sq_queue_t write_q; /* Write buffering for UDP packets */ + FAR struct net_driver_s *dev; /* Last device */ +#endif + /* Defines the list of UDP callbacks */ FAR struct devif_callback_s *list; }; +/* This structure supports UDP write buffering. It is simply a container + * for a IOB list and associated destination address. + */ + +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS +struct udp_wrbuffer_s +{ + sq_entry_t wb_node; /* Supports a singly linked list */ + union ip_addr_u wb_dest; /* Destination address */ +#ifdef CONFIG_NET_SOCKOPTS + systime_t wb_start; /* Start time for timeout calculation */ +#endif + struct iob_s *wb_iob; /* Head of the I/O buffer chain */ +}; +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -291,6 +330,92 @@ void udp_poll(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn); void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn); +/**************************************************************************** + * Name: udp_wrbuffer_initialize + * + * Description: + * Initialize the list of free write buffers + * + * Assumptions: + * Called once early initialization. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS +void udp_wrbuffer_initialize(void); +#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */ + +/**************************************************************************** + * Name: udp_wrbuffer_alloc + * + * Description: + * Allocate a UDP write buffer by taking a pre-allocated buffer from + * the free list. This function is called from UDP logic when a buffer + * of UDP data is about to sent + * + * Input parameters: + * None + * + * Assumptions: + * Called from user logic with the network locked. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS +struct udp_wrbuffer_s; + +FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void); +#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */ + +/**************************************************************************** + * Name: udp_wrbuffer_release + * + * Description: + * Release a UDP write buffer by returning the buffer to the free list. + * This function is called from user logic after it is consumed the + * buffered data. + * + * Assumptions: + * Called from network stack logic with the network stack locked + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS +void udp_wrbuffer_release(FAR struct udp_wrbuffer_s *wrb); +#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */ + +/**************************************************************************** + * Name: udp_wrbuffer_test + * + * Description: + * Check if there is room in the write buffer. Does not reserve any space. + * + * Assumptions: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS +int udp_wrbuffer_test(void); +#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */ + +/**************************************************************************** + * Name: udp_wrbuffer_dump + * + * Description: + * Dump the contents of a write buffer. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS +#ifdef CONFIG_DEBUG_FEATURES +void udp_wrbuffer_dump(FAR const char *msg, FAR struct udp_wrbuffer_s *wrb, + unsigned int len, unsigned int offset); +#else +# define udp_wrbuffer_dump(msg,wrb) +#endif +#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */ + /**************************************************************************** * Name: udp_ipv4_input * @@ -495,7 +620,7 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds); * Teardown monitoring of events on an UDP/IP socket * * Input Parameters: - * psock - The TCP/IP socket of interest + * psock - The UDP/IP socket of interest * fds - The structure describing the events to be monitored, OR NULL if * this is a request to stop monitoring events. * diff --git a/net/udp/udp_conn.c b/net/udp/udp_conn.c index 97037c444f9..61e67028f64 100644 --- a/net/udp/udp_conn.c +++ b/net/udp/udp_conn.c @@ -1,7 +1,8 @@ /**************************************************************************** * net/udp/udp_conn.c * - * Copyright (C) 2007-2009, 2011-2012, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011-2012, 2016, 2018 Gregory Nutt. All rights + * reserved. * Author: Gregory Nutt * * Large parts of this file were leveraged from uIP logic: @@ -485,6 +486,11 @@ FAR struct udp_conn_s *udp_alloc(uint8_t domain) conn->lport = 0; conn->ttl = IP_TTL; +#ifdef CONFIG_NET_TCP_WRITE_BUFFERS + /* Initialize the write buffer lists */ + + sq_init(&conn->write_q); +#endif /* Enqueue the connection into the active list */ dq_addlast(&conn->node, &g_active_udp_connections); @@ -505,6 +511,10 @@ FAR struct udp_conn_s *udp_alloc(uint8_t domain) void udp_free(FAR struct udp_conn_s *conn) { +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS + FAR struct udp_wrbuffer_s *wrbuffer; +#endif + /* The free list is protected by a semaphore (that behaves like a mutex). */ DEBUGASSERT(conn->crefs == 0); @@ -522,6 +532,15 @@ void udp_free(FAR struct udp_conn_s *conn) iob_free_queue(&conn->readahead); #endif +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS + /* Release any write buffers attached to the connection */ + + while ((wrbuffer = (struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q)) != NULL) + { + udp_wrbuffer_release(wrbuffer); + } +#endif + /* Free the connection */ dq_addlast(&conn->node, &g_free_udp_connections); diff --git a/net/udp/udp_psock_sendto_buffered.c b/net/udp/udp_psock_sendto_buffered.c new file mode 100644 index 00000000000..3f5e5305b48 --- /dev/null +++ b/net/udp/udp_psock_sendto_buffered.c @@ -0,0 +1,821 @@ +/**************************************************************************** + * net/udp/udp_send_buffered.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_NET) && defined(CONFIG_NET_UDP) && \ + defined(CONFIG_NET_UDP_WRITE_BUFFERS) + +#if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_NET_UDP_WRBUFFER_DEBUG) +/* Force debug output (from this file only) */ + +# undef CONFIG_DEBUG_NET +# define CONFIG_DEBUG_NET 1 +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "netdev/netdev.h" +#include "socket/socket.h" +#include "inet/inet.h" +#include "arp/arp.h" +#include "icmpv6/icmpv6.h" +#include "neighbor/neighbor.h" +#include "udp/udp.h" +#include "devif/devif.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* If both IPv4 and IPv6 support are both enabled, then we will need to build + * in some additional domain selection support. + */ + +#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) +# define NEED_IPDOMAIN_SUPPORT 1 +#endif + +#define UDPIPv4BUF ((struct udp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv4_HDRLEN]) +#define UDPIPv6BUF ((struct udp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv6_HDRLEN]) + +/* Debug */ + +#ifdef CONFIG_NET_UDP_WRBUFFER_DUMP +# define BUF_DUMP(msg,buf,len) lib_dumpbuffer(msg,buf,len) +#else +# define BUF_DUMP(msg,buf,len) +# undef UDPWB_DUMP +# define UDPWB_DUMP(msg,wrb,len,offset) +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline void sendto_netdev_down(FAR struct socket *psock, + FAR struct udp_conn_s *conn); + +#ifdef NEED_IPDOMAIN_SUPPORT +static inline void sendto_ipselect(FAR struct net_driver_s *dev, + FAR struct udp_conn_s *conn); +#endif +#ifdef CONFIG_NET_ETHERNET +static inline bool sendto_addrcheck(FAR struct udp_conn_s *conn, + FAR struct net_driver_s *dev); +#else +# define sendto_addrcheck(c,d) (true) +#endif +#ifdef CONFIG_NET_SOCKOPTS +static inline int sendto_timeout(FAR struct socket *psock, + FAR struct udp_conn_s *conn); +#endif +static int sendto_next_transfer(FAR struct socket *psock, + FAR struct udp_conn_s *conn); +static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, + FAR void *pvconn, FAR void *pvpriv, + uint16_t flags); +static inline void sendto_txnotify(FAR struct socket *psock, + FAR struct udp_conn_s *conn); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sendto_netdev_down + * + * Description: + * The network device is down. Free all write buffers. + * REVISIT: Should only free write buffers associated with the device + * that went down. + * + * Parameters: + * psock The socket structure + * conn The connection structure associated with the socket + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void sendto_netdev_down(FAR struct socket *psock, + FAR struct udp_conn_s *conn) +{ + FAR sq_entry_t *entry; + FAR sq_entry_t *next; + + /* Do not allow any further callbacks */ + + if (psock->s_sndcb != NULL) + { + psock->s_sndcb->flags = 0; + psock->s_sndcb->event = NULL; + } + + /* Free all queued write buffers */ + + for (entry = sq_peek(&conn->write_q); entry; entry = next) + { + next = sq_next(entry); + udp_wrbuffer_release((FAR struct udp_wrbuffer_s *)entry); + } + + /* Reset write buffering variables */ + + sq_init(&conn->write_q); +} + +/**************************************************************************** + * Name: sendto_ipselect + * + * Description: + * If both IPv4 and IPv6 support are enabled, then we will need to select + * which one to use when generating the outgoing packet. If only one + * domain is selected, then the setup is already in place and we need do + * nothing. + * + * Parameters: + * dev - The structure of the network driver that caused the event + * psock - Socket state structure + * + * Returned Value: + * None + * + * Assumptions: + * The network is locked + * + ****************************************************************************/ + +#ifdef NEED_IPDOMAIN_SUPPORT +static inline void sendto_ipselect(FAR struct net_driver_s *dev, + FAR struct udp_conn_s *conn) +{ + /* Which domain the socket support */ + + if (conn->domain == PF_INET) + { + /* Select the IPv4 domain */ + + udp_ipv4_select(dev); + } + else /* if (conn->domain == PF_INET6) */ + { + /* Select the IPv6 domain */ + + DEBUGASSERT(conn->domain == PF_INET6); + udp_ipv6_select(dev); + } +} +#endif + +/**************************************************************************** + * Name: sendto_addrcheck + * + * Description: + * Check if the destination IP address is in the IPv4 ARP or IPv6 Neighbor + * tables. If not, then the send won't actually make it out... it will be + * replaced with an ARP request (IPv4) or a Neighbor Solicitation (IPv6). + * + * NOTE 1: This could be an expensive check if there are a lot of + * entries in the ARP or Neighbor tables. + * + * NOTE 2: If we are actually harvesting IP addresses on incoming IP + * packets, then this check should not be necessary; the MAC mapping + * should already be in the ARP table in many cases (IPv4 only). + * + * NOTE 3: If CONFIG_NET_ARP_SEND then we can be assured that the IP + * address mapping is already in the ARP table. + * + * Parameters: + * conn - The UDP connection structure + * dev - Polling network device + * + * Returned Value: + * true - The Ethernet MAC address is in the ARP or Neighbor table (OR + * the network device is not Ethernet). + * + * Assumptions: + * The network is locked + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ETHERNET +static inline bool sendto_addrcheck(FAR struct udp_conn_s *conn, + FAR struct net_driver_s *dev) +{ + /* REVISIT: Could the MAC address not also be in a routing table? */ + + if (dev->d_lltype != NET_LL_ETHERNET) + { + return true; + } + +#ifdef CONFIG_NET_IPv4 +#ifdef CONFIG_NET_IPv6 + if (conn->domain == PF_INET) +#endif + { +#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND) + return (arp_find(conn->u.ipv4.raddr) != NULL); +#else + return true; +#endif + } +#endif /* CONFIG_NET_IPv4 */ + +#ifdef CONFIG_NET_IPv6 +#ifdef CONFIG_NET_IPv4 + else +#endif + { +#if !defined(CONFIG_NET_ICMPv6_NEIGHBOR) + return (neighbor_findentry(conn->u.ipv6.raddr) != NULL); +#else + return true; +#endif + } +#endif /* CONFIG_NET_IPv6 */ +} +#endif /* CONFIG_NET_ETHERNET */ + +/**************************************************************************** + * Name: sendto_timeout + * + * Description: + * Check for send timeout. + * + * Parameters: + * pstate - sendto state structure + * + * Returned Value: + * TRUE:timeout FALSE:no timeout + * + * Assumptions: + * The network is locked + * + ****************************************************************************/ + +#ifdef CONFIG_NET_SOCKOPTS +static inline int sendto_timeout(FAR struct socket *psock, + FAR struct udp_conn_s *conn) +{ + FAR struct udp_wrbuffer_s *wrb; + + /* Peek at the head of the write queue (without altering the write queue). */ + + wrb = (FAR struct udp_wrbuffer_s *)sq_peek(&conn->write_q); + if (wrb != NULL) + { + /* Check for a timeout configured via setsockopts(SO_SNDTIMEO). + * If none... we well let the send wait forever. + */ + + if (psock->s_sndtimeo != 0) + { + /* Check if the configured timeout has elapsed */ + + return net_timeo(wrb->wb_start, psock->s_sndtimeo); + } + } + + /* No timeout */ + + return FALSE; +} +#endif /* CONFIG_NET_SOCKOPTS */ + +/**************************************************************************** + * Name: sendto_next_transfer + * + * Description: + * Setup for the next packet transfer + * + * Parameters: + * psock - Socket state structure + * conn - The UDP connection structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int sendto_next_transfer(FAR struct socket *psock, + FAR struct udp_conn_s *conn) +{ + FAR struct udp_wrbuffer_s *wrb; + FAR struct net_driver_s *dev; + int ret; + + /* Set the UDP "connection" to the destination address of the write buffer + * at the head of the queue. + */ + + wrb = (FAR struct udp_wrbuffer_s *)sq_peek(&conn->write_q); + DEBUGASSERT(wrb != NULL); + + ret = udp_connect(conn, (FAR const struct sockaddr *)wrb->wb_iob->io_data); + if (ret < 0) + { + nerr("ERROR: udp_connect failed: %d\n", ret); + return ret; + } + + /* Get the device that will handle the remote packet transfers. This + * should never be NULL. + */ + + dev = udp_find_raddr_device(conn); + if (dev == NULL) + { + nerr("ERROR: udp_find_raddr_device failed\n"); + return -ENETUNREACH; + } + + /* If this is not the same device that we used in the last call to + * udp_callback_alloc(), then we need to release and reallocate the old + * callback instance. + */ + + if (psock->s_sndcb != NULL && conn->dev != dev) + { + udp_callback_free(conn->dev, conn, psock->s_sndcb); + psock->s_sndcb = NULL; + } + + /* Allocate resources to receive a callback from this device if the + * callback is not already in place. + */ + + if (psock->s_sndcb == NULL) + { + psock->s_sndcb = udp_callback_alloc(dev, conn); + } + + /* Test if the callback has been allocated */ + + if (psock->s_sndcb == NULL) + { + /* A buffer allocation error occurred */ + + nerr("ERROR: Failed to allocate callback\n"); + return -ENOMEM; + } + + conn->dev = dev; + + /* Set up the callback in the connection */ + + psock->s_sndcb->flags = (UDP_POLL | NETDEV_DOWN); + psock->s_sndcb->priv = (FAR void *)psock; + psock->s_sndcb->event = sendto_eventhandler; + return OK; +} + +/**************************************************************************** + * Name: sendto_eventhandler + * + * Description: + * This function is called to perform the actual send operation when + * polled by the lower, device interfacing layer. + * + * Parameters: + * dev The structure of the network driver that caused the event + * conn The connection structure associated with the socket + * flags Set of events describing why the callback was invoked + * + * Returned Value: + * None + * + * Assumptions: + * The network is locked + * + ****************************************************************************/ + +static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, + FAR void *pvconn, FAR void *pvpriv, + uint16_t flags) +{ + FAR struct udp_conn_s *conn = (FAR struct udp_conn_s *)pvconn; + FAR struct socket *psock = (FAR struct socket *)pvpriv; + int ret; + + ninfo("flags: %04x\n", flags); + + /* Check if the network device has gone down */ + + if ((flags & NETDEV_DOWN) != 0) + { + ninfo("Device down: %04x\n", flags); + + /* Free write buffers and terminate polling */ + + sendto_netdev_down(psock, conn); + return flags; + } + + /* Check for a normal polling cycle and if the outgoing packet is + * available. It would not be available if it has been claimed by a send + * event serving a different thread -OR- if the output buffer currently + * contains unprocessed incoming data. In these cases we will just have + * to wait for the next polling cycle. + * + * And, of course, we can do nothing if we have no data in the write + * buffers to send. + */ + + if (dev->d_sndlen <= 0 && (flags & UDP_NEWDATA) != 0 && + (flags & UDP_POLL) != 0 && !sq_empty(&conn->write_q)) + { + /* Check if the destination IP address is in the ARP or Neighbor + * table. If not, then the send won't actually make it out... it + * will be replaced with an ARP request or Neighbor Solicitation. + */ + + if (sendto_addrcheck(conn, dev)) + { + FAR struct udp_wrbuffer_s *wrb; + FAR struct udp_wrbuffer_s *tmp; + size_t sndlen; + + /* Peek at the head of the write queue (but don't remove anything + * from the write queue yet). We know from the above test that + * the write_q is not empty. + */ + + wrb = (FAR struct udp_wrbuffer_s *)sq_peek(&conn->write_q); + DEBUGASSERT(wrb != NULL); + + /* Get the amount of data that we can send in the next packet. + * We will send either the remaining data in the buffer I/O + * buffer chain, or as much as will fit given the MSS and current + * window size. + */ + + sndlen = wrb->wb_iob->io_pktlen; + ninfo("wrb=%p sndlen=%u\n", wrb, sndlen); + +#ifdef NEED_IPDOMAIN_SUPPORT + /* If both IPv4 and IPv6 support are enabled, then we will need to + * select which one to use when generating the outgoing packet. + * If only one domain is selected, then the setup is already in + * place and we need do nothing. + */ + + sendto_ipselect(dev, conn); +#endif + /* Then set-up to send that amount of data with the offset + * corresponding to the size of the IP-dependent address structure. + */ + + devif_iob_send(dev, wrb->wb_iob, sndlen, 0); + + /* Remove and free the write buffer from the head of the write + * buffer queue. + */ + + do + { + tmp = (FAR struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q); + DEBUGASSERT(tmp == wrb); + + udp_wrbuffer_release(tmp); + + /* Check if the write queue became empty */ + + if (sq_empty(&conn->write_q)) + { + /* Yes.. stifle any further callbacks until more write + * data is enqueued. + */ + + psock->s_sndcb->flags = 0; + psock->s_sndcb->priv = NULL; + psock->s_sndcb->event = NULL; + ret = OK; + } + else + { + /* Set up for the next packet transfer by setting the + * connection address to the address of the next packet + * now at the header of of the write buffer queue. + */ + + ret = sendto_next_transfer(psock, conn); + } + } + while (ret < 0); + + /* Only one data can be sent by low level driver at once, + * tell the caller stop polling the other connections. + */ + + flags &= ~UDP_POLL; + } + } + +#ifdef CONFIG_NET_SOCKOPTS + /* We cannot send the data now. Check for a timeout. */ + + else if (sendto_timeout(psock, conn)) + { + FAR struct udp_wrbuffer_s *wrb; + + do + { + /* Remove and free the write buffer from the head of the write + * buffer queue. Here we know that the write queue is not empty + * because the entry at the head of the queue just timed out! + */ + + wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q); + DEBUGASSERT(wrb != NULL); + + udp_wrbuffer_release(wrb); + + /* Set up for the next packet transfer by setting the connection + * address to the address of the next packet now at the header of the + * write buffer queue. + */ + + ret = sendto_next_transfer(psock, conn); + } + while (ret < 0); + } +#endif /* CONFIG_NET_SOCKOPTS */ + + /* Continue waiting */ + + return flags; +} + +/**************************************************************************** + * Name: sendto_txnotify + * + * Description: + * Notify the appropriate device driver that we are have data ready to + * be send (UDP) + * + * Parameters: + * psock - Socket state structure + * conn - The UDP connection structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void sendto_txnotify(FAR struct socket *psock, + FAR struct udp_conn_s *conn) +{ +#ifdef CONFIG_NET_IPv4 +#ifdef CONFIG_NET_IPv6 + /* If both IPv4 and IPv6 support are enabled, then we will need to select + * the device driver using the appropriate IP domain. + */ + + if (psock->s_domain == PF_INET) +#endif + { + /* Notify the device driver that send data is available */ + + netdev_ipv4_txnotify(conn->u.ipv4.laddr, conn->u.ipv4.raddr); + } +#endif /* CONFIG_NET_IPv4 */ + +#ifdef CONFIG_NET_IPv6 +#ifdef CONFIG_NET_IPv4 + else /* if (psock->s_domain == PF_INET6) */ +#endif /* CONFIG_NET_IPv4 */ + { + /* Notify the device driver that send data is available */ + + DEBUGASSERT(psock->s_domain == PF_INET6); + netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr); + } +#endif /* CONFIG_NET_IPv6 */ +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: psock_udp_sendto + * + * Description: + * This function implements the UDP-specific logic of the standard + * sendto() socket operation. + * + * Input Parameters: + * psock A pointer to a NuttX-specific, internal socket structure + * buf Data to send + * len Length of data to send + * flags Send flags + * to Address of recipient + * tolen The length of the address structure + * + * NOTE: All input parameters were verified by sendto() before this + * function was called. + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * a negated errno value is returned. See the description in + * net/socket/sendto.c for the list of appropriate return value. + * + ****************************************************************************/ + +ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags, FAR const struct sockaddr *to, + socklen_t tolen) +{ + FAR struct udp_conn_s *conn; + FAR struct udp_wrbuffer_s *wrb; + int ret = OK; + + /* Make sure that we have the IP address mapping */ + + conn = (FAR struct udp_conn_s *)psock->s_conn; + DEBUGASSERT(conn); + +#if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR) +#ifdef CONFIG_NET_ARP_SEND +#ifdef CONFIG_NET_ICMPv6_NEIGHBOR + if (psock->s_domain == PF_INET) +#endif + { + /* Make sure that the IP address mapping is in the ARP table */ + + ret = arp_send(conn->u.ipv4.raddr); + } +#endif /* CONFIG_NET_ARP_SEND */ + +#ifdef CONFIG_NET_ICMPv6_NEIGHBOR +#ifdef CONFIG_NET_ARP_SEND + else +#endif + { + /* Make sure that the IP address mapping is in the Neighbor Table */ + + ret = icmpv6_neighbor(conn->u.ipv6.raddr); + } +#endif /* CONFIG_NET_ICMPv6_NEIGHBOR */ + + /* Did we successfully get the address mapping? */ + + if (ret < 0) + { + nerr("ERROR: Not reachable\n"); + return -ENETUNREACH; + } +#endif /* CONFIG_NET_ARP_SEND || CONFIG_NET_ICMPv6_NEIGHBOR */ + + /* Dump the incoming buffer */ + + BUF_DUMP("psock_udp_send", buf, len); + + /* Set the socket state to sending */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); + + if (len > 0) + { + /* Allocate a write buffer. Careful, the network will be momentarily + * unlocked here. + */ + + net_lock(); + wrb = udp_wrbuffer_alloc(); + if (wrb == NULL) + { + /* A buffer allocation error occurred */ + + nerr("ERROR: Failed to allocate write buffer\n"); + ret = -ENOMEM; + goto errout_with_lock; + } + + /* Initialize the write buffer */ + + memcpy(&wrb->wb_dest, to, tolen); + wrb->wb_start = clock_systimer(); + + /* Copy the user data into the write buffer. We cannot wait for + * buffer space if the socket was opened non-blocking. + */ + + if (_SS_ISNONBLOCK(psock->s_flags)) + { + ret = iob_trycopyin(wrb->wb_iob, (FAR uint8_t *)buf, len, 0, false); + } + else + { + ret = iob_copyin(wrb->wb_iob, (FAR uint8_t *)buf, len, 0, false); + } + + if (ret < 0) + { + goto errout_with_wrb; + } + + /* Dump I/O buffer chain */ + + UDPWB_DUMP("I/O buffer chain", wrb, wrb->wb_iob->io_pktlen, 0); + + /* sendto_eventhandler() will send data in FIFO order from the + * conn->write_q + */ + + sq_addlast(&wrb->wb_node, &conn->write_q); + ninfo("Queued WRB=%p pktlen=%u write_q(%p,%p)\n", + wrb, wrb->wb_iob->io_pktlen, + conn->write_q.head, conn->write_q.tail); + + /* Set up for the next packet transfer by setting the connection + * address to the address of the next packet now at the header of the + * write buffer queue. + */ + + ret = sendto_next_transfer(psock, conn); + if (ret < 0) + { + /* REVISIT: An error here is not recoverable */ + + goto errout_with_lock; + } + + /* Notify the device driver of the availability of TX data */ + + sendto_txnotify(psock, conn); + net_unlock(); + } + + /* Set the socket state to idle */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); + + /* Return the number of bytes that will be sent */ + + return len; + +errout_with_wrb: + udp_wrbuffer_release(wrb); + +errout_with_lock: + net_unlock(); + return ret; +} + +#endif /* CONFIG_NET && CONFIG_NET_UDP && CONFIG_NET_UDP_WRITE_BUFFERS */ diff --git a/net/udp/udp_psock_sendto.c b/net/udp/udp_psock_sendto_unbuffered.c similarity index 98% rename from net/udp/udp_psock_sendto.c rename to net/udp/udp_psock_sendto_unbuffered.c index ff362a310e4..809ee2ce9e0 100644 --- a/net/udp/udp_psock_sendto.c +++ b/net/udp/udp_psock_sendto_unbuffered.c @@ -1,7 +1,8 @@ /**************************************************************************** - * net/udp/udp_psock_sendto.c + * net/udp/udp_psock_sendto_unbuffered.c * - * Copyright (C) 2007-2009, 2011-2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011-2016, 2018 Gregory Nutt. All rights + * reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -94,7 +95,7 @@ struct sendto_s ****************************************************************************/ /**************************************************************************** - * Name: send_timeout + * Name: sendto_timeout * * Description: * Check for send timeout. @@ -111,7 +112,7 @@ struct sendto_s ****************************************************************************/ #ifdef CONFIG_NET_SOCKOPTS -static inline int send_timeout(FAR struct sendto_s *pstate) +static inline int sendto_timeout(FAR struct sendto_s *pstate) { FAR struct socket *psock; @@ -235,7 +236,7 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, */ #ifdef CONFIG_NET_SOCKOPTS - if (send_timeout(pstate)) + if (sendto_timeout(pstate)) { /* Yes.. report the timeout */ diff --git a/net/udp/udp_wrbuffer.c b/net/udp/udp_wrbuffer.c new file mode 100644 index 00000000000..ae8fafd7ffb --- /dev/null +++ b/net/udp/udp_wrbuffer.c @@ -0,0 +1,217 @@ +/**************************************************************************** + * net/udp/udp_wrbuffer.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#if defined(CONFIG_NET) && defined(CONFIG_NET_UDP) && defined(CONFIG_NET_UDP_WRITE_BUFFERS) + +#if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_NET_UDP_WRBUFFER_DEBUG) +/* Force debug output (from this file only) */ + +# undef CONFIG_DEBUG_NET +# define CONFIG_DEBUG_NET 1 +#endif + +#include +#include +#include +#include + +#include +#include +#include + +#include "udp/udp.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Package all globals used by this logic into a structure */ + +struct wrbuffer_s +{ + /* The semaphore to protect the buffers */ + + sem_t sem; + + /* This is the list of available write buffers */ + + sq_queue_t freebuffers; + + /* These are the pre-allocated write buffers */ + + struct udp_wrbuffer_s buffers[CONFIG_NET_UDP_NWRBCHAINS]; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This is the state of the global write buffer resource */ + +static struct wrbuffer_s g_wrbuffer; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: udp_wrbuffer_initialize + * + * Description: + * Initialize the list of free write buffers + * + * Assumptions: + * Called once early initialization. + * + ****************************************************************************/ + +void udp_wrbuffer_initialize(void) +{ + int i; + + sq_init(&g_wrbuffer.freebuffers); + + for (i = 0; i < CONFIG_NET_UDP_NWRBCHAINS; i++) + { + sq_addfirst(&g_wrbuffer.buffers[i].wb_node, &g_wrbuffer.freebuffers); + } + + nxsem_init(&g_wrbuffer.sem, 0, CONFIG_NET_UDP_NWRBCHAINS); +} + +/**************************************************************************** + * Name: udp_wrbuffer_alloc + * + * Description: + * Allocate a UDP write buffer by taking a pre-allocated buffer from + * the free list. This function is called from UDP logic when a buffer + * of UDP data is about to sent + * + * Input parameters: + * None + * + * Assumptions: + * Called from user logic with the network locked. + * + ****************************************************************************/ + +FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void) +{ + FAR struct udp_wrbuffer_s *wrb; + + /* We need to allocate two things: (1) A write buffer structure and (2) + * at least one I/O buffer to start the chain. + * + * Allocate the write buffer structure first then the IOBG. In order to + * avoid deadlocks, we will need to free the IOB first, then the write + * buffer + */ + + DEBUGVERIFY(net_lockedwait(&g_wrbuffer.sem)); /* TODO: Handle EINTR. */ + + /* Now, we are guaranteed to have a write buffer structure reserved + * for us in the free list. + */ + + wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); + DEBUGASSERT(wrb); + memset(wrb, 0, sizeof(struct udp_wrbuffer_s)); + + /* Now get the first I/O buffer for the write buffer structure */ + + wrb->wb_iob = iob_alloc(false); + if (!wrb->wb_iob) + { + nerr("ERROR: Failed to allocate I/O buffer\n"); + udp_wrbuffer_release(wrb); + return NULL; + } + + return wrb; +} + +/**************************************************************************** + * Name: udp_wrbuffer_release + * + * Description: + * Release a UDP write buffer by returning the buffer to the free list. + * This function is called from user logic after it is consumed the + * buffered data. + * + * Assumptions: + * This function must be called with the network locked. + * + ****************************************************************************/ + +void udp_wrbuffer_release(FAR struct udp_wrbuffer_s *wrb) +{ + DEBUGASSERT(wrb && wrb->wb_iob); + + /* To avoid deadlocks, we must following this ordering: Release the I/O + * buffer chain first, then the write buffer structure. + */ + + iob_free_chain(wrb->wb_iob); + + /* Then free the write buffer structure */ + + sq_addlast(&wrb->wb_node, &g_wrbuffer.freebuffers); + nxsem_post(&g_wrbuffer.sem); +} + +/**************************************************************************** + * Name: udp_wrbuffer_test + * + * Description: + * Check if there is room in the write buffer. Does not reserve any space. + * + * Assumptions: + * None. + * + ****************************************************************************/ + +int udp_wrbuffer_test(void) +{ + int val = 0; + nxsem_getvalue(&g_wrbuffer.sem, &val); + return val > 0 ? OK : ERROR; +} + +#endif /* CONFIG_NET && CONFIG_NET_UDP && CONFIG_NET_UDP_WRITE_BUFFERS */ diff --git a/net/udp/udp_wrbuffer_dump.c b/net/udp/udp_wrbuffer_dump.c new file mode 100644 index 00000000000..e3e8df1f59d --- /dev/null +++ b/net/udp/udp_wrbuffer_dump.c @@ -0,0 +1,70 @@ +/**************************************************************************** + * net/udp/udp_wrbuffer_dump.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "udp/udp.h" + +#ifdef CONFIG_DEBUG_FEATURES + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: udp_wrbuffer_dump + * + * Description: + * Dump the contents of a write buffer + * + ****************************************************************************/ + +void udp_wrbuffer_dump(FAR const char *msg, FAR struct udp_wrbuffer_s *wrb, + unsigned int len, unsigned int offset) +{ + syslog(LOG_DEBUG, "%s: wrb=%p pktlen=%d\n", msg, wrb, wrb->wb_iob->io_pktlen); + iob_dump("I/O Buffer Chain", wrb->wb_iob, len, offset); +} + +#endif /* CONFIG_DEBUG_FEATURES */ From fa3ad468976c2c393355e0957a049ef686ed14fe Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 22 Jan 2018 18:46:58 -0600 Subject: [PATCH 27/40] net/udp: In sendto(), return EHOSTUNREACH if if the network is down. --- net/udp/udp_psock_sendto_buffered.c | 8 ++++++++ net/udp/udp_psock_sendto_unbuffered.c | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/net/udp/udp_psock_sendto_buffered.c b/net/udp/udp_psock_sendto_buffered.c index 3f5e5305b48..b9a8a891893 100644 --- a/net/udp/udp_psock_sendto_buffered.c +++ b/net/udp/udp_psock_sendto_buffered.c @@ -384,6 +384,14 @@ static int sendto_next_transfer(FAR struct socket *psock, return -ENETUNREACH; } + /* Make sure that the device is in the UP state */ + + if ((dev->d_flags & IFF_UP) == 0) + { + nwarn("WARNING: device is DOWN\n"); + return -EHOSTUNREACH; + } + /* If this is not the same device that we used in the last call to * udp_callback_alloc(), then we need to release and reallocate the old * callback instance. diff --git a/net/udp/udp_psock_sendto_unbuffered.c b/net/udp/udp_psock_sendto_unbuffered.c index 809ee2ce9e0..7024d12baf0 100644 --- a/net/udp/udp_psock_sendto_unbuffered.c +++ b/net/udp/udp_psock_sendto_unbuffered.c @@ -424,6 +424,15 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, goto errout_with_lock; } + /* Make sure that the device is in the UP state */ + + if ((dev->d_flags & IFF_UP) == 0) + { + nwarn("WARNING: device is DOWN\n"); + ret = -EHOSTUNREACH; + goto errout_with_lock; + } + /* Set up the callback in the connection */ state.st_cb = udp_callback_alloc(dev, conn); From 2d4fa19a54e9a84744d71345b01ccb0e8c1af640 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 22 Jan 2018 19:27:05 -0600 Subject: [PATCH 28/40] net/udp: Resolves final design issues with UDP write buffering. 100% code complete but also 100% untested. --- net/udp/udp_psock_sendto_buffered.c | 150 +++++++++++----------------- 1 file changed, 58 insertions(+), 92 deletions(-) diff --git a/net/udp/udp_psock_sendto_buffered.c b/net/udp/udp_psock_sendto_buffered.c index b9a8a891893..b084837b6e2 100644 --- a/net/udp/udp_psock_sendto_buffered.c +++ b/net/udp/udp_psock_sendto_buffered.c @@ -105,9 +105,6 @@ * Private Function Prototypes ****************************************************************************/ -static inline void sendto_netdev_down(FAR struct socket *psock, - FAR struct udp_conn_s *conn); - #ifdef NEED_IPDOMAIN_SUPPORT static inline void sendto_ipselect(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn); @@ -135,47 +132,64 @@ static inline void sendto_txnotify(FAR struct socket *psock, ****************************************************************************/ /**************************************************************************** - * Name: sendto_netdev_down + * Name: sendto_writebuffer_release * * Description: - * The network device is down. Free all write buffers. - * REVISIT: Should only free write buffers associated with the device - * that went down. + * Release the write buffer at the head of the write buffer queue. * * Parameters: - * psock The socket structure - * conn The connection structure associated with the socket + * dev - The structure of the network driver that caused the event + * psock - Socket state structure * * Returned Value: * None * + * Assumptions: + * The network is locked + * ****************************************************************************/ -static inline void sendto_netdev_down(FAR struct socket *psock, - FAR struct udp_conn_s *conn) +static void sendto_writebuffer_release(FAR struct socket *psock, + FAR struct udp_conn_s *conn) { - FAR sq_entry_t *entry; - FAR sq_entry_t *next; + FAR struct udp_wrbuffer_s *wrb; + int ret = OK; - /* Do not allow any further callbacks */ - - if (psock->s_sndcb != NULL) + do { - psock->s_sndcb->flags = 0; - psock->s_sndcb->event = NULL; + /* Check if the write queue became empty */ + + if (sq_empty(&conn->write_q)) + { + /* Yes.. stifle any further callbacks until more write data is + * enqueued. + */ + + psock->s_sndcb->flags = 0; + psock->s_sndcb->priv = NULL; + psock->s_sndcb->event = NULL; + wrb = NULL; + } + else + { + /* Remove the write buffer from the head of the write buffer queue + * and release it. + */ + + wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q); + DEBUGASSERT(wrb != NULL); + + udp_wrbuffer_release(wrb); + + /* Set up for the next packet transfer by setting the connection + * address to the address of the next packet now at the header of + * the write buffer queue. + */ + + ret = sendto_next_transfer(psock, conn); + } } - - /* Free all queued write buffers */ - - for (entry = sq_peek(&conn->write_q); entry; entry = next) - { - next = sq_next(entry); - udp_wrbuffer_release((FAR struct udp_wrbuffer_s *)entry); - } - - /* Reset write buffering variables */ - - sq_init(&conn->write_q); + while (wrb != NULL && ret < 0); } /**************************************************************************** @@ -254,7 +268,7 @@ static inline void sendto_ipselect(FAR struct net_driver_s *dev, #ifdef CONFIG_NET_ETHERNET static inline bool sendto_addrcheck(FAR struct udp_conn_s *conn, - FAR struct net_driver_s *dev) + FAR struct net_driver_s *dev) { /* REVISIT: Could the MAC address not also be in a routing table? */ @@ -458,7 +472,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, { FAR struct udp_conn_s *conn = (FAR struct udp_conn_s *)pvconn; FAR struct socket *psock = (FAR struct socket *)pvpriv; - int ret; ninfo("flags: %04x\n", flags); @@ -468,9 +481,11 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, { ninfo("Device down: %04x\n", flags); - /* Free write buffers and terminate polling */ + /* Free the write buffer at the head of the queue and attempt to setup + * the next transfer. + */ - sendto_netdev_down(psock, conn); + sendto_writebuffer_release(psock, conn); return flags; } @@ -495,7 +510,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, if (sendto_addrcheck(conn, dev)) { FAR struct udp_wrbuffer_s *wrb; - FAR struct udp_wrbuffer_s *tmp; size_t sndlen; /* Peek at the head of the write queue (but don't remove anything @@ -530,41 +544,11 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, devif_iob_send(dev, wrb->wb_iob, sndlen, 0); - /* Remove and free the write buffer from the head of the write - * buffer queue. + /* Free the write buffer at the head of the queue and attempt to + * setup the next transfer. */ - do - { - tmp = (FAR struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q); - DEBUGASSERT(tmp == wrb); - - udp_wrbuffer_release(tmp); - - /* Check if the write queue became empty */ - - if (sq_empty(&conn->write_q)) - { - /* Yes.. stifle any further callbacks until more write - * data is enqueued. - */ - - psock->s_sndcb->flags = 0; - psock->s_sndcb->priv = NULL; - psock->s_sndcb->event = NULL; - ret = OK; - } - else - { - /* Set up for the next packet transfer by setting the - * connection address to the address of the next packet - * now at the header of of the write buffer queue. - */ - - ret = sendto_next_transfer(psock, conn); - } - } - while (ret < 0); + sendto_writebuffer_release(psock, conn); /* Only one data can be sent by low level driver at once, * tell the caller stop polling the other connections. @@ -579,28 +563,11 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, else if (sendto_timeout(psock, conn)) { - FAR struct udp_wrbuffer_s *wrb; + /* Free the write buffer at the head of the queue and attempt to setup + * the next transfer. + */ - do - { - /* Remove and free the write buffer from the head of the write - * buffer queue. Here we know that the write queue is not empty - * because the entry at the head of the queue just timed out! - */ - - wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q); - DEBUGASSERT(wrb != NULL); - - udp_wrbuffer_release(wrb); - - /* Set up for the next packet transfer by setting the connection - * address to the address of the next packet now at the header of the - * write buffer queue. - */ - - ret = sendto_next_transfer(psock, conn); - } - while (ret < 0); + sendto_writebuffer_release(psock, conn); } #endif /* CONFIG_NET_SOCKOPTS */ @@ -799,9 +766,8 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, ret = sendto_next_transfer(psock, conn); if (ret < 0) { - /* REVISIT: An error here is not recoverable */ - - goto errout_with_lock; + (void)sq_remlast(&conn->write_q); + goto errout_with_wrb; } /* Notify the device driver of the availability of TX data */ From 289e4dde06e1dee1e6e2250a2cd34c06c7aaf814 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 22 Jan 2018 19:33:14 -0600 Subject: [PATCH 29/40] net/udp and tcp: Yet another (cosmetic) change to UDP and TCP write buffer macro naming. --- net/tcp/tcp.h | 22 +++--- net/tcp/tcp_send_buffered.c | 104 ++++++++++++++-------------- net/tcp/tcp_wrbuffer_dump.c | 4 +- net/udp/udp.h | 4 +- net/udp/udp_psock_sendto_buffered.c | 6 +- 5 files changed, 70 insertions(+), 70 deletions(-) diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index bf8948da73a..bfd402c00a1 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -77,25 +77,25 @@ #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* TCP write buffer access macros */ -# define TCPWB_SEQNO(wrb) ((wrb)->wb_seqno) -# define TCPWB_PKTLEN(wrb) ((wrb)->wb_iob->io_pktlen) -# define TCPWB_SENT(wrb) ((wrb)->wb_sent) -# define TCPWB_NRTX(wrb) ((wrb)->wb_nrtx) -# define TCPWB_IOB(wrb) ((wrb)->wb_iob) -# define TCPWB_COPYOUT(wrb,dest,n) (iob_copyout(dest,(wrb)->wb_iob,(n),0)) -# define TCPWB_COPYIN(wrb,src,n) \ +# define TCP_WBSEQNO(wrb) ((wrb)->wb_seqno) +# define TCP_WBPKTLEN(wrb) ((wrb)->wb_iob->io_pktlen) +# define TCP_WBSENT(wrb) ((wrb)->wb_sent) +# define TCP_WBNRTX(wrb) ((wrb)->wb_nrtx) +# define TCP_WBIOB(wrb) ((wrb)->wb_iob) +# define TCP_WBCOPYOUT(wrb,dest,n) (iob_copyout(dest,(wrb)->wb_iob,(n),0)) +# define TCP_WBCOPYIN(wrb,src,n) \ (iob_copyin((wrb)->wb_iob,src,(n),0,false)) -# define TCPWB_TRYCOPYIN(wrb,src,n) \ +# define TCP_WBTRYCOPYIN(wrb,src,n) \ (iob_trycopyin((wrb)->wb_iob,src,(n),0,false)) -# define TCPWB_TRIM(wrb,n) \ +# define TCP_WBTRIM(wrb,n) \ do { (wrb)->wb_iob = iob_trimhead((wrb)->wb_iob,(n)); } while (0) #ifdef CONFIG_DEBUG_FEATURES -# define TCPWB_DUMP(msg,wrb,len,offset) \ +# define TCP_WBDUMP(msg,wrb,len,offset) \ tcp_wrbuffer_dump(msg,wrb,len,offset) # else -# define TCPWB_DUMP(msg,wrb,len,offset) +# define TCP_WBDUMP(msg,wrb,len,offset) # endif #endif diff --git a/net/tcp/tcp_send_buffered.c b/net/tcp/tcp_send_buffered.c index 5abb417e701..b8463b0643f 100644 --- a/net/tcp/tcp_send_buffered.c +++ b/net/tcp/tcp_send_buffered.c @@ -98,8 +98,8 @@ # define BUF_DUMP(msg,buf,len) lib_dumpbuffer(msg,buf,len) #else # define BUF_DUMP(msg,buf,len) -# undef TCPWB_DUMP -# define TCPWB_DUMP(msg,wrb,len,offset) +# undef TCP_WBDUMP +# define TCP_WBDUMP(msg,wrb,len,offset) #endif /**************************************************************************** @@ -135,7 +135,7 @@ static void psock_insert_segment(FAR struct tcp_wrbuffer_s *wrb, for (itr = sq_peek(q); itr; itr = sq_next(itr)) { FAR struct tcp_wrbuffer_s *wrb0 = (FAR struct tcp_wrbuffer_s *)itr; - if (TCPWB_SEQNO(wrb0) < TCPWB_SEQNO(wrb)) + if (TCP_WBSEQNO(wrb0) < TCP_WBSEQNO(wrb)) { insert = itr; } @@ -417,13 +417,13 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * the write buffer has been ACKed. */ - if (ackno > TCPWB_SEQNO(wrb)) + if (ackno > TCP_WBSEQNO(wrb)) { /* Get the sequence number at the end of the data */ - lastseq = TCPWB_SEQNO(wrb) + TCPWB_PKTLEN(wrb); + lastseq = TCP_WBSEQNO(wrb) + TCP_WBPKTLEN(wrb); ninfo("ACK: wrb=%p seqno=%u lastseq=%u pktlen=%u ackno=%u\n", - wrb, TCPWB_SEQNO(wrb), lastseq, TCPWB_PKTLEN(wrb), + wrb, TCP_WBSEQNO(wrb), lastseq, TCP_WBPKTLEN(wrb), ackno); /* Has the entire buffer been ACKed? */ @@ -450,24 +450,24 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * buffers in the chain. */ - trimlen = ackno - TCPWB_SEQNO(wrb); - if (trimlen > TCPWB_SENT(wrb)) + trimlen = ackno - TCP_WBSEQNO(wrb); + if (trimlen > TCP_WBSENT(wrb)) { /* More data has been ACKed then we have sent? */ - trimlen = TCPWB_SENT(wrb); + trimlen = TCP_WBSENT(wrb); } ninfo("ACK: wrb=%p trim %u bytes\n", wrb, trimlen); - TCPWB_TRIM(wrb, trimlen); - TCPWB_SEQNO(wrb) = ackno; - TCPWB_SENT(wrb) -= trimlen; + TCP_WBTRIM(wrb, trimlen); + TCP_WBSEQNO(wrb) = ackno; + TCP_WBSENT(wrb) -= trimlen; /* Set the new sequence number for what remains */ ninfo("ACK: wrb=%p seqno=%u pktlen=%u\n", - wrb, TCPWB_SEQNO(wrb), TCPWB_PKTLEN(wrb)); + wrb, TCP_WBSEQNO(wrb), TCP_WBPKTLEN(wrb)); } } } @@ -478,31 +478,31 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, */ wrb = (FAR struct tcp_wrbuffer_s *)sq_peek(&conn->write_q); - if (wrb && TCPWB_SENT(wrb) > 0 && ackno > TCPWB_SEQNO(wrb)) + if (wrb && TCP_WBSENT(wrb) > 0 && ackno > TCP_WBSEQNO(wrb)) { uint32_t nacked; /* Number of bytes that were ACKed */ - nacked = ackno - TCPWB_SEQNO(wrb); - if (nacked > TCPWB_SENT(wrb)) + nacked = ackno - TCP_WBSEQNO(wrb); + if (nacked > TCP_WBSENT(wrb)) { /* More data has been ACKed then we have sent? ASSERT? */ - nacked = TCPWB_SENT(wrb); + nacked = TCP_WBSENT(wrb); } ninfo("ACK: wrb=%p seqno=%u nacked=%u sent=%u ackno=%u\n", - wrb, TCPWB_SEQNO(wrb), nacked, TCPWB_SENT(wrb), ackno); + wrb, TCP_WBSEQNO(wrb), nacked, TCP_WBSENT(wrb), ackno); /* Trim the ACKed bytes from the beginning of the write buffer. */ - TCPWB_TRIM(wrb, nacked); - TCPWB_SEQNO(wrb) = ackno; - TCPWB_SENT(wrb) -= nacked; + TCP_WBTRIM(wrb, nacked); + TCP_WBSEQNO(wrb) = ackno; + TCP_WBSENT(wrb) -= nacked; ninfo("ACK: wrb=%p seqno=%u pktlen=%u sent=%u\n", - wrb, TCPWB_SEQNO(wrb), TCPWB_PKTLEN(wrb), TCPWB_SENT(wrb)); + wrb, TCP_WBSEQNO(wrb), TCP_WBPKTLEN(wrb), TCP_WBSENT(wrb)); } } @@ -544,16 +544,16 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, */ wrb = (FAR struct tcp_wrbuffer_s *)sq_peek(&conn->write_q); - ninfo("REXMIT: wrb=%p sent=%u\n", wrb, wrb ? TCPWB_SENT(wrb) : 0); + ninfo("REXMIT: wrb=%p sent=%u\n", wrb, wrb ? TCP_WBSENT(wrb) : 0); - if (wrb != NULL && TCPWB_SENT(wrb) > 0) + if (wrb != NULL && TCP_WBSENT(wrb) > 0) { FAR struct tcp_wrbuffer_s *tmp; uint16_t sent; /* Yes.. Reset the number of bytes sent sent from the write buffer */ - sent = TCPWB_SENT(wrb); + sent = TCP_WBSENT(wrb); if (conn->unacked > sent) { conn->unacked -= sent; @@ -572,16 +572,16 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, conn->sent = 0; } - TCPWB_SENT(wrb) = 0; + TCP_WBSENT(wrb) = 0; ninfo("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n", - wrb, TCPWB_SENT(wrb), conn->unacked, conn->sent); + wrb, TCP_WBSENT(wrb), conn->unacked, conn->sent); /* Increment the retransmit count on this write buffer. */ - if (++TCPWB_NRTX(wrb) >= TCP_MAXRTX) + if (++TCP_WBNRTX(wrb) >= TCP_MAXRTX) { nwarn("WARNING: Expiring wrb=%p nrtx=%u\n", - wrb, TCPWB_NRTX(wrb)); + wrb, TCP_WBNRTX(wrb)); /* The maximum retry count as been exhausted. Remove the write * buffer at the head of the queue. @@ -619,7 +619,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, /* Reset the number of bytes sent sent from the write buffer */ - sent = TCPWB_SENT(wrb); + sent = TCP_WBSENT(wrb); if (conn->unacked > sent) { conn->unacked -= sent; @@ -638,16 +638,16 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, conn->sent = 0; } - TCPWB_SENT(wrb) = 0; + TCP_WBSENT(wrb) = 0; ninfo("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n", - wrb, TCPWB_SENT(wrb), conn->unacked, conn->sent); + wrb, TCP_WBSENT(wrb), conn->unacked, conn->sent); /* Free any write buffers that have exceed the retry count */ - if (++TCPWB_NRTX(wrb) >= TCP_MAXRTX) + if (++TCP_WBNRTX(wrb) >= TCP_MAXRTX) { nwarn("WARNING: Expiring wrb=%p nrtx=%u\n", - wrb, TCPWB_NRTX(wrb)); + wrb, TCP_WBNRTX(wrb)); /* Return the write buffer to the free list */ @@ -672,7 +672,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * is pulled from the write_q again. */ - ninfo("REXMIT: Moving wrb=%p nrtx=%u\n", wrb, TCPWB_NRTX(wrb)); + ninfo("REXMIT: Moving wrb=%p nrtx=%u\n", wrb, TCP_WBNRTX(wrb)); psock_insert_segment(wrb, &conn->write_q); } @@ -727,7 +727,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * window size. */ - sndlen = TCPWB_PKTLEN(wrb) - TCPWB_SENT(wrb); + sndlen = TCP_WBPKTLEN(wrb) - TCP_WBSENT(wrb); if (sndlen > conn->mss) { sndlen = conn->mss; @@ -739,16 +739,16 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, } ninfo("SEND: wrb=%p pktlen=%u sent=%u sndlen=%u\n", - wrb, TCPWB_PKTLEN(wrb), TCPWB_SENT(wrb), sndlen); + wrb, TCP_WBPKTLEN(wrb), TCP_WBSENT(wrb), sndlen); /* Set the sequence number for this segment. If we are * retransmitting, then the sequence number will already * be set for this write buffer. */ - if (TCPWB_SEQNO(wrb) == (unsigned)-1) + if (TCP_WBSEQNO(wrb) == (unsigned)-1) { - TCPWB_SEQNO(wrb) = conn->isn + conn->sent; + TCP_WBSEQNO(wrb) = conn->isn + conn->sent; } /* The TCP stack updates sndseq on receipt of ACK *before* @@ -758,7 +758,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * before the packet is sent. */ - tcp_setsequence(conn->sndseq, TCPWB_SEQNO(wrb) + TCPWB_SENT(wrb)); + tcp_setsequence(conn->sndseq, TCP_WBSEQNO(wrb) + TCP_WBSENT(wrb)); #ifdef NEED_IPDOMAIN_SUPPORT /* If both IPv4 and IPv6 support are enabled, then we will need to @@ -774,7 +774,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, * won't actually happen until the polling cycle completes). */ - devif_iob_send(dev, TCPWB_IOB(wrb), sndlen, TCPWB_SENT(wrb)); + devif_iob_send(dev, TCP_WBIOB(wrb), sndlen, TCP_WBSENT(wrb)); /* Remember how much data we send out now so that we know * when everything has been acknowledged. Just increment @@ -796,21 +796,21 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, } ninfo("SEND: wrb=%p nrtx=%u unacked=%u sent=%u\n", - wrb, TCPWB_NRTX(wrb), conn->unacked, conn->sent); + wrb, TCP_WBNRTX(wrb), conn->unacked, conn->sent); /* Increment the count of bytes sent from this write buffer */ - TCPWB_SENT(wrb) += sndlen; + TCP_WBSENT(wrb) += sndlen; ninfo("SEND: wrb=%p sent=%u pktlen=%u\n", - wrb, TCPWB_SENT(wrb), TCPWB_PKTLEN(wrb)); + wrb, TCP_WBSENT(wrb), TCP_WBPKTLEN(wrb)); /* Remove the write buffer from the write queue if the * last of the data has been sent from the buffer. */ - DEBUGASSERT(TCPWB_SENT(wrb) <= TCPWB_PKTLEN(wrb)); - if (TCPWB_SENT(wrb) >= TCPWB_PKTLEN(wrb)) + DEBUGASSERT(TCP_WBSENT(wrb) <= TCP_WBPKTLEN(wrb)); + if (TCP_WBSENT(wrb) >= TCP_WBPKTLEN(wrb)) { FAR struct tcp_wrbuffer_s *tmp; @@ -1061,8 +1061,8 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, /* Initialize the write buffer */ - TCPWB_SEQNO(wrb) = (unsigned)-1; - TCPWB_NRTX(wrb) = 0; + TCP_WBSEQNO(wrb) = (unsigned)-1; + TCP_WBNRTX(wrb) = 0; /* Copy the user data into the write buffer. We cannot wait for * buffer space if the socket was opened non-blocking. @@ -1070,16 +1070,16 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, if (_SS_ISNONBLOCK(psock->s_flags)) { - result = TCPWB_TRYCOPYIN(wrb, (FAR uint8_t *)buf, len); + result = TCP_WBTRYCOPYIN(wrb, (FAR uint8_t *)buf, len); } else { - result = TCPWB_COPYIN(wrb, (FAR uint8_t *)buf, len); + result = TCP_WBCOPYIN(wrb, (FAR uint8_t *)buf, len); } /* Dump I/O buffer chain */ - TCPWB_DUMP("I/O buffer chain", wrb, TCPWB_PKTLEN(wrb), 0); + TCP_WBDUMP("I/O buffer chain", wrb, TCP_WBPKTLEN(wrb), 0); /* psock_send_eventhandler() will send data in FIFO order from the * conn->write_q @@ -1087,7 +1087,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, sq_addlast(&wrb->wb_node, &conn->write_q); ninfo("Queued WRB=%p pktlen=%u write_q(%p,%p)\n", - wrb, TCPWB_PKTLEN(wrb), + wrb, TCP_WBPKTLEN(wrb), conn->write_q.head, conn->write_q.tail); /* Notify the device driver of the availability of TX data */ diff --git a/net/tcp/tcp_wrbuffer_dump.c b/net/tcp/tcp_wrbuffer_dump.c index a27bb60253d..1af76573952 100644 --- a/net/tcp/tcp_wrbuffer_dump.c +++ b/net/tcp/tcp_wrbuffer_dump.c @@ -64,8 +64,8 @@ void tcp_wrbuffer_dump(FAR const char *msg, FAR struct tcp_wrbuffer_s *wrb, unsigned int len, unsigned int offset) { syslog(LOG_DEBUG, "%s: wrb=%p segno=%d sent=%d nrtx=%d\n", - msg, wrb, TCPWB_SEQNO(wrb), TCPWB_SENT(wrb), TCPWB_NRTX(wrb)); - iob_dump("I/O Buffer Chain", TCPWB_IOB(wrb), len, offset); + msg, wrb, TCP_WBSEQNO(wrb), TCP_WBSENT(wrb), TCP_WBNRTX(wrb)); + iob_dump("I/O Buffer Chain", TCP_WBIOB(wrb), len, offset); } #endif /* CONFIG_DEBUG_FEATURES */ diff --git a/net/udp/udp.h b/net/udp/udp.h index ee591ed0782..f670f7bbfb9 100644 --- a/net/udp/udp.h +++ b/net/udp/udp.h @@ -71,10 +71,10 @@ /* UDP write buffer dump macros */ # ifdef CONFIG_DEBUG_FEATURES -# define UDPWB_DUMP(msg,wrb,len,offset) \ +# define UDP_WBDUMP(msg,wrb,len,offset) \ udp_wrbuffer_dump(msg,wrb,len,offset) # else -# define UDPWB_DUMP(msg,wrb,len,offset) +# define UDP_WBDUMP(msg,wrb,len,offset) # endif #endif diff --git a/net/udp/udp_psock_sendto_buffered.c b/net/udp/udp_psock_sendto_buffered.c index b084837b6e2..29308e12747 100644 --- a/net/udp/udp_psock_sendto_buffered.c +++ b/net/udp/udp_psock_sendto_buffered.c @@ -97,8 +97,8 @@ # define BUF_DUMP(msg,buf,len) lib_dumpbuffer(msg,buf,len) #else # define BUF_DUMP(msg,buf,len) -# undef UDPWB_DUMP -# define UDPWB_DUMP(msg,wrb,len,offset) +# undef UDP_WBDUMP +# define UDP_WBDUMP(msg,wrb,len,offset) #endif /**************************************************************************** @@ -747,7 +747,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, /* Dump I/O buffer chain */ - UDPWB_DUMP("I/O buffer chain", wrb, wrb->wb_iob->io_pktlen, 0); + UDP_WBDUMP("I/O buffer chain", wrb, wrb->wb_iob->io_pktlen, 0); /* sendto_eventhandler() will send data in FIFO order from the * conn->write_q From f2017bded845c25ed880014873ab018cb1848a0e Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 23 Jan 2018 07:32:17 -0600 Subject: [PATCH 30/40] net/udp: UDP write buffering is basically functional but needs a lot more verification. --- net/udp/Kconfig | 1 - net/udp/udp.h | 9 ++-- net/udp/udp_psock_sendto_buffered.c | 75 ++++++++--------------------- 3 files changed, 24 insertions(+), 61 deletions(-) diff --git a/net/udp/Kconfig b/net/udp/Kconfig index 16d40a72efa..7deccfc4caa 100644 --- a/net/udp/Kconfig +++ b/net/udp/Kconfig @@ -52,7 +52,6 @@ config NET_UDP_WRITE_BUFFERS default n select NET_WRITE_BUFFERS select MM_IOB - depends on EXPERIMENTAL ---help--- Write buffers allows buffering of ongoing UDP/IP packets, providing for higher performance, streamed output. diff --git a/net/udp/udp.h b/net/udp/udp.h index f670f7bbfb9..24be51dc21e 100644 --- a/net/udp/udp.h +++ b/net/udp/udp.h @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -137,12 +138,12 @@ struct udp_conn_s #ifdef CONFIG_NET_UDP_WRITE_BUFFERS struct udp_wrbuffer_s { - sq_entry_t wb_node; /* Supports a singly linked list */ - union ip_addr_u wb_dest; /* Destination address */ + sq_entry_t wb_node; /* Supports a singly linked list */ + struct sockaddr_storage wb_dest; /* Destination address */ #ifdef CONFIG_NET_SOCKOPTS - systime_t wb_start; /* Start time for timeout calculation */ + systime_t wb_start; /* Start time for timeout calculation */ #endif - struct iob_s *wb_iob; /* Head of the I/O buffer chain */ + struct iob_s *wb_iob; /* Head of the I/O buffer chain */ }; #endif diff --git a/net/udp/udp_psock_sendto_buffered.c b/net/udp/udp_psock_sendto_buffered.c index 29308e12747..9f8716d3552 100644 --- a/net/udp/udp_psock_sendto_buffered.c +++ b/net/udp/udp_psock_sendto_buffered.c @@ -124,8 +124,6 @@ static int sendto_next_transfer(FAR struct socket *psock, static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint16_t flags); -static inline void sendto_txnotify(FAR struct socket *psock, - FAR struct udp_conn_s *conn); /**************************************************************************** * Private Functions @@ -378,9 +376,13 @@ static int sendto_next_transfer(FAR struct socket *psock, */ wrb = (FAR struct udp_wrbuffer_s *)sq_peek(&conn->write_q); - DEBUGASSERT(wrb != NULL); + if (wrb == NULL) + { + ninfo("Write buffer queue is empty\n"); + return -ENOENT; + } - ret = udp_connect(conn, (FAR const struct sockaddr *)wrb->wb_iob->io_data); + ret = udp_connect(conn, (FAR const struct sockaddr *)&wrb->wb_dest); if (ret < 0) { nerr("ERROR: udp_connect failed: %d\n", ret); @@ -443,6 +445,10 @@ static int sendto_next_transfer(FAR struct socket *psock, psock->s_sndcb->flags = (UDP_POLL | NETDEV_DOWN); psock->s_sndcb->priv = (FAR void *)psock; psock->s_sndcb->event = sendto_eventhandler; + + /* Notify the device driver of the availability of TX data */ + + netdev_txnotify_dev(dev); return OK; } @@ -499,7 +505,7 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, * buffers to send. */ - if (dev->d_sndlen <= 0 && (flags & UDP_NEWDATA) != 0 && + if (dev->d_sndlen <= 0 && (flags & UDP_NEWDATA) == 0 && (flags & UDP_POLL) != 0 && !sq_empty(&conn->write_q)) { /* Check if the destination IP address is in the ARP or Neighbor @@ -576,53 +582,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, return flags; } -/**************************************************************************** - * Name: sendto_txnotify - * - * Description: - * Notify the appropriate device driver that we are have data ready to - * be send (UDP) - * - * Parameters: - * psock - Socket state structure - * conn - The UDP connection structure - * - * Returned Value: - * None - * - ****************************************************************************/ - -static inline void sendto_txnotify(FAR struct socket *psock, - FAR struct udp_conn_s *conn) -{ -#ifdef CONFIG_NET_IPv4 -#ifdef CONFIG_NET_IPv6 - /* If both IPv4 and IPv6 support are enabled, then we will need to select - * the device driver using the appropriate IP domain. - */ - - if (psock->s_domain == PF_INET) -#endif - { - /* Notify the device driver that send data is available */ - - netdev_ipv4_txnotify(conn->u.ipv4.laddr, conn->u.ipv4.raddr); - } -#endif /* CONFIG_NET_IPv4 */ - -#ifdef CONFIG_NET_IPv6 -#ifdef CONFIG_NET_IPv4 - else /* if (psock->s_domain == PF_INET6) */ -#endif /* CONFIG_NET_IPv4 */ - { - /* Notify the device driver that send data is available */ - - DEBUGASSERT(psock->s_domain == PF_INET6); - netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr); - } -#endif /* CONFIG_NET_IPv6 */ -} - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -750,7 +709,14 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, UDP_WBDUMP("I/O buffer chain", wrb, wrb->wb_iob->io_pktlen, 0); /* sendto_eventhandler() will send data in FIFO order from the - * conn->write_q + * conn->write_q. + * + * REVISIT: Why FIFO order? Because it is easy. In a real world + * environment where there are multiple network devices this might + * be inefficient because we could be sending data to different + * device out-of-queued-order to optimize performance. Sending + * data to different networks from a single UDP socket is probably + * not a very common use case, however. */ sq_addlast(&wrb->wb_node, &conn->write_q); @@ -770,9 +736,6 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, goto errout_with_wrb; } - /* Notify the device driver of the availability of TX data */ - - sendto_txnotify(psock, conn); net_unlock(); } From 82cb799bb6d0a06f2181f4dc63ab95a4859eab8b Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 23 Jan 2018 11:54:03 -0600 Subject: [PATCH 31/40] net/udp: Fix memory leak with UDP + write buffer is closed. Also update TODO and comments and refresh a configuration. --- TODO | 30 +++++++++------------ configs/viewtool-stm32f107/README.txt | 6 ----- configs/viewtool-stm32f107/netnsh/defconfig | 14 +++++++--- net/inet/inet_close.c | 18 +++++++++++-- net/tcp/tcp_netpoll.c | 6 ++++- net/udp/udp_netpoll.c | 6 ++++- 6 files changed, 49 insertions(+), 31 deletions(-) diff --git a/TODO b/TODO index dd4dca76ac2..b5ab5f89dae 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -NuttX TODO List (Last updated January 21, 2018) +NuttX TODO List (Last updated January 23, 2018) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with @@ -19,7 +19,7 @@ nuttx/: (8) Kernel/Protected Build (3) C++ Support (6) Binary loaders (binfmt/) - (17) Network (net/, drivers/net) + (16) Network (net/, drivers/net) (4) USB (drivers/usbdev, drivers/usbhost) (0) Other drivers (drivers/) (12) Libraries (libc/, libm/) @@ -1075,23 +1075,19 @@ o Network (net/, drivers/net) Title: POLL/SELECT ON TCP/UDP SOCKETS NEEDS READ-AHEAD Description: poll()/select() only works for availability of buffered TCP/UDP read data (when read-ahead is enabled). The way writing is - handled in the network layer, all sockets must wait when send and - cannot be notified when they can send without waiting. + handled in the network layer, either (1) If CONFIG_UDP/TCP_WRITE_BUFFERS=y + then we never have to wait to send; otherwise, we always have + to wait to send. So it is impossible to notify the caller + when it can send without waiting. + + An exception "never having to wait" is the case where we are + out of memory for use in write buffering. In that case, the + blocking send()/sendto() would have to wait for the memory + to become available. Status: Open, probably will not be fixed. Priority: Medium... this does effect porting of applications that expect different behavior from poll()/select() - Title: SOCKETS DO NOT ALWAYS SUPPORT O_NONBLOCK - Description: sockets do not support all modes for O_NONBLOCK. Sockets - support nonblocking operations only (1) for TCP/IP non- - blocking read operations when read-ahead buffering is - enabled, (2) TCP/IP accept() operations when TCP/IP - connection backlog is enabled, (2) UDP/IP read() operations - when UDP read-ahead is enabled, and (3) non-blocking - operations on Unix domain sockets. - Status: Open - Priority: Low. - Title: INTERFACES TO LEAVE/JOIN IGMP MULTICAST GROUP Description: The interfaces used to leave/join IGMP multicast groups is non-standard. RFC3678 (IGMPv3) suggests ioctl() commands to do this (SIOCSIPMSFILTER) but @@ -1124,8 +1120,8 @@ o Network (net/, drivers/net) however. Others support the address filtering interfaces but have never been verifed: - C5471, LM3S, ez80, DM0x90 NIC, PIC: Do not support address - filtering. + C5471, LM3S, ez80, DM0x90 NIC, PIC, LPC54: Do not support + address filtering. Kinetis, LPC17xx, LPC43xx: Untested address filter support Status: Open diff --git a/configs/viewtool-stm32f107/README.txt b/configs/viewtool-stm32f107/README.txt index 3bb13a31662..42faf94f79d 100644 --- a/configs/viewtool-stm32f107/README.txt +++ b/configs/viewtool-stm32f107/README.txt @@ -630,12 +630,6 @@ Configurations 6. USB support is disabled by default. See the section above entitled, "USB Interface" - STATUS. The first time I build the configuration, I get some undefined - external references. No idea why. Simply cleaning the apps/ directory - and rebuilding fixes the problem: - - make apps_clean all - nsh: This configuration directory provide the basic NuttShell (NSH). diff --git a/configs/viewtool-stm32f107/netnsh/defconfig b/configs/viewtool-stm32f107/netnsh/defconfig index 131d3b620b1..72a2921d02a 100644 --- a/configs/viewtool-stm32f107/netnsh/defconfig +++ b/configs/viewtool-stm32f107/netnsh/defconfig @@ -1,5 +1,4 @@ # CONFIG_NSH_ARGCAT is not set -# CONFIG_NSH_CMDOPT_DF_H is not set # CONFIG_NSH_CMDOPT_HEXDUMP is not set # CONFIG_NSH_CMDPARMS is not set CONFIG_ARCH_BOARD_VIEWTOOL_STM32F107=y @@ -23,9 +22,15 @@ CONFIG_NET_ARP_SEND=y CONFIG_NET_BROADCAST=y CONFIG_NET_ETH_MTU=650 CONFIG_NET_ETH_TCP_RECVWNDO=624 +CONFIG_NET_HOSTNAME="Viewtool-STM32F107" CONFIG_NET_ICMP_SOCKET=y CONFIG_NET_ICMP=y +CONFIG_NET_ICMPv6_NEIGHBOR=y +CONFIG_NET_ICMPv6_SOCKET=y +CONFIG_NET_ICMPv6=y +CONFIG_NET_IPv6=y CONFIG_NET_MAX_LISTENPORTS=40 +CONFIG_NET_ROUTE=y CONFIG_NET_SOCKOPTS=y CONFIG_NET_TCP_CONNS=40 CONFIG_NET_TCP_WRITE_BUFFERS=y @@ -56,9 +61,9 @@ CONFIG_SCHED_HPWORK=y CONFIG_SCHED_HPWORKPRIORITY=192 CONFIG_SCHED_HPWORKSTACKSIZE=1024 CONFIG_SDCLONE_DISABLE=y -CONFIG_START_DAY=21 -CONFIG_START_MONTH=9 -CONFIG_START_YEAR=2009 +CONFIG_START_DAY=23 +CONFIG_START_MONTH=1 +CONFIG_START_YEAR=2018 CONFIG_STM32_ETHMAC=y CONFIG_STM32_JTAG_FULL_ENABLE=y CONFIG_STM32_PHYSR_100MBPS=0x0000 @@ -70,6 +75,7 @@ CONFIG_STM32_PWR=y CONFIG_STM32_RMII_EXTCLK=y CONFIG_STM32_USART1=y CONFIG_SYSTEM_PING=y +CONFIG_SYSTEM_PING6=y CONFIG_TASK_NAME_SIZE=0 CONFIG_USART1_SERIAL_CONSOLE=y CONFIG_USER_ENTRYPOINT="nsh_main" diff --git a/net/inet/inet_close.c b/net/inet/inet_close.c index a36089e5417..14c463c628b 100644 --- a/net/inet/inet_close.c +++ b/net/inet/inet_close.c @@ -345,7 +345,7 @@ static inline int tcp_close_disconnect(FAR struct socket *psock) #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* If we have a semi-permanent write buffer callback in place, then - * is needs to be be nullifed. + * is needs to be be nullified. * * Commit f1ef2c6cdeb032eaa1833cc534a63b50c5058270: * "When a socket is closed, it should make sure that any pending write @@ -357,6 +357,9 @@ static inline int tcp_close_disconnect(FAR struct socket *psock) * data. However, to be able to actually send any new data, the send * callback must be left. The callback should be freed later when the * socket is actually destroyed." + * + * REVISIT: Where and how exactly is s_sndcb ever freed? Is there a + * memory leak here? */ psock->s_sndcb = NULL; @@ -548,7 +551,18 @@ int inet_close(FAR struct socket *psock) if (conn->crefs <= 1) { - /* Yes... free the connection structure */ + /* Yes... */ + +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS + /* Free any semi-permanent write buffer callback in place. */ + + if (psock->s_sndcb != NULL) + { + udp_callback_free(conn->dev, conn, psock->s_sndcb); + psock->s_sndcb = NULL; + } +#endif + /* And free the connection structure */ conn->crefs = 0; udp_free(psock->s_conn); diff --git a/net/tcp/tcp_netpoll.c b/net/tcp/tcp_netpoll.c index 615fb84b565..3979cf7c8dd 100644 --- a/net/tcp/tcp_netpoll.c +++ b/net/tcp/tcp_netpoll.c @@ -112,7 +112,11 @@ static uint16_t tcp_poll_eventhandler(FAR struct net_driver_s *dev, eventset |= POLLIN & info->fds->events; } - /* A poll is a sign that we are free to send data. */ + /* A poll is a sign that we are free to send data. + * REVISIT: This is bogus: If CONFIG_TCP_WRITE_BUFFERS=y then + * we never have to wait to send; otherwise, we always have to + * wait to send. Receiving a poll is irrelevant. + */ if ((flags & TCP_POLL) != 0) { diff --git a/net/udp/udp_netpoll.c b/net/udp/udp_netpoll.c index 0145c3303ea..1479a00b96d 100644 --- a/net/udp/udp_netpoll.c +++ b/net/udp/udp_netpoll.c @@ -111,7 +111,11 @@ static uint16_t udp_poll_eventhandler(FAR struct net_driver_s *dev, eventset |= (POLLIN & info->fds->events); } - /* poll is a sign that we are free to send data. */ + /* A poll is a sign that we are free to send data. + * REVISIT: This is bogus: If CONFIG_UDP_WRITE_BUFFERS=y then + * we never have to wait to send; otherwise, we always have to + * wait to send. Receiving a poll is irrelevant. + */ if ((flags & UDP_POLL) != 0) { From 5e49e9e93793e5b0d6ecca15be2d1aaf0c94a3cc Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 24 Jan 2018 06:50:20 -0600 Subject: [PATCH 32/40] Update some comments. --- net/inet/inet_sockif.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c index 9ab4be7336e..d9c56ad76d8 100644 --- a/net/inet/inet_sockif.c +++ b/net/inet/inet_sockif.c @@ -286,6 +286,10 @@ static sockcaps_t inet_sockcaps(FAR struct socket *psock) { #ifdef NET_TCP_HAVE_STACK case SOCK_STREAM: + /* REVISIT: Non-blocking recv() depends on CONFIG_NET_TCP_READAHEAD, + * but non-blocking send() depends on CONFIG_NET_TCP_WRITE_BUFFERS. + */ + #ifdef CONFIG_NET_TCP_READAHEAD return SOCKCAP_NONBLOCKING; #else @@ -295,6 +299,10 @@ static sockcaps_t inet_sockcaps(FAR struct socket *psock) #ifdef NET_UDP_HAVE_STACK case SOCK_DGRAM: + /* REVISIT: Non-blocking recvfrom() depends on CONFIG_NET_UDP_READAHEAD, + * but non-blocking sendto() depends on CONFIG_NET_UDP_WRITE_BUFFERS. + */ + #ifdef CONFIG_NET_UDP_READAHEAD return SOCKCAP_NONBLOCKING; #else From a7834bcb7b82aa3bafd1585b2adf00b2e8f6c292 Mon Sep 17 00:00:00 2001 From: Alexander Oryshchenko Date: Wed, 24 Jan 2018 06:51:34 -0600 Subject: [PATCH 33/40] drivers/mtd/at24xx.c: Correct page size for AT24C02 part. --- drivers/mtd/at24xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/at24xx.c b/drivers/mtd/at24xx.c index f08cec9d618..a09b948db2c 100644 --- a/drivers/mtd/at24xx.c +++ b/drivers/mtd/at24xx.c @@ -86,9 +86,9 @@ /* Get the part configuration based on the size configuration */ -#if CONFIG_AT24XX_SIZE == 2 /* AT24C02: 2Kbits = 256; 16 * 16 = 256 */ -# define AT24XX_NPAGES 16 -# define AT24XX_PAGESIZE 16 +#if CONFIG_AT24XX_SIZE == 2 /* AT24C02: 2Kbits = 256; 32 * 8 = 256 */ +# define AT24XX_NPAGES 32 +# define AT24XX_PAGESIZE 8 # define AT24XX_ADDRSIZE 1 #elif CONFIG_AT24XX_SIZE == 4 /* AT24C04: 4Kbits = 512B; 32 * 16 = 512 */ # define AT24XX_NPAGES 32 From dd4fc9f5c3578ba829a8465dca2f8557365662f4 Mon Sep 17 00:00:00 2001 From: Alexander Oryshchenko Date: Wed, 24 Jan 2018 06:55:14 -0600 Subject: [PATCH 34/40] arch/arm/src/stm32: Make STM32 usable with an external RTC. drivers/timers/ds3231.c: Correct some debug statments. --- arch/arm/src/stm32/stm32_irq.c | 2 +- arch/arm/src/stm32/stm32f40xxx_rtcc.c | 5 +++-- drivers/timers/ds3231.c | 12 ++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/arm/src/stm32/stm32_irq.c b/arch/arm/src/stm32/stm32_irq.c index 98adf74f36c..402351aafa2 100644 --- a/arch/arm/src/stm32/stm32_irq.c +++ b/arch/arm/src/stm32/stm32_irq.c @@ -387,7 +387,7 @@ void up_irqinitialize(void) up_enable_irq(STM32_IRQ_MEMFAULT); #endif -#ifdef CONFIG_RTC +#if defined(CONFIG_RTC) && !defined(CONFIG_RTC_EXTERNAL) /* RTC was initialized earlier but IRQs weren't ready at that time */ stm32_rtc_irqinitialize(); diff --git a/arch/arm/src/stm32/stm32f40xxx_rtcc.c b/arch/arm/src/stm32/stm32f40xxx_rtcc.c index 8657d6e1667..460a3872d87 100644 --- a/arch/arm/src/stm32/stm32f40xxx_rtcc.c +++ b/arch/arm/src/stm32/stm32f40xxx_rtcc.c @@ -58,7 +58,7 @@ #include -#ifdef CONFIG_RTC +#if defined(CONFIG_RTC) && !defined(CONFIG_RTC_EXTERNAL) /**************************************************************************** * Pre-processor Definitions @@ -1659,4 +1659,5 @@ int stm32_rtc_rdalarm(FAR struct alm_rdalarm_s *alminfo) } #endif -#endif /* CONFIG_RTC */ +#endif /* CONFIG_RTC && !CONFIG_RTC_EXTERNAL */ + diff --git a/drivers/timers/ds3231.c b/drivers/timers/ds3231.c index 4f1e2a1c9f5..113fb977433 100644 --- a/drivers/timers/ds3231.c +++ b/drivers/timers/ds3231.c @@ -321,7 +321,7 @@ int up_rtc_getdatetime(FAR struct tm *tp) ret = I2C_TRANSFER(g_ds3231.i2c, msg, 4); if (ret < 0) { - rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret) + rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret); return ret; } } @@ -415,7 +415,7 @@ int up_rtc_settime(FAR const struct timespec *tp) return -EAGAIN; } - rtc_dumptime(tp, "Setting time"); + rtcinfo("Setting time tp=(%d,%d)\n", (int)tp->tv_sec, (int)tp->tv_nsec); /* Get the broken out time */ @@ -430,18 +430,18 @@ int up_rtc_settime(FAR const struct timespec *tp) #ifdef CONFIG_LIBC_LOCALTIME if (localtime_r(&newtime, &newtm) == NULL) { - rtcerr("ERROR: localtime_r failed\n") + rtcerr("ERROR: localtime_r failed\n"); return -EINVAL; } #else if (gmtime_r(&newtime, &newtm) == NULL) { - rtcerr("ERROR: gmtime_r failed\n") + rtcerr("ERROR: gmtime_r failed\n"); return -EINVAL; } #endif - rtc_dumptime(&tm, "New time"); + rtc_dumptime(&newtm, "New time"); /* Construct the message */ /* Write starting with the seconds regiser */ @@ -536,7 +536,7 @@ int up_rtc_settime(FAR const struct timespec *tp) ret = I2C_TRANSFER(g_ds3231.i2c, msg, 3); if (ret < 0) { - rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret) + rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret); return ret; } } From a7e56359a4af0ddd00511fd9b98720c7fc027b3e Mon Sep 17 00:00:00 2001 From: Alexander Oryshchenko Date: Wed, 24 Jan 2018 06:57:17 -0600 Subject: [PATCH 35/40] arch/arm/src/stm32/stm32_spi.c: Removed unnecessary (and incorrect) speed limitation --- arch/arm/src/stm32/stm32_spi.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/arm/src/stm32/stm32_spi.c b/arch/arm/src/stm32/stm32_spi.c index 71f6dbfb3a5..1be51d49c2f 100644 --- a/arch/arm/src/stm32/stm32_spi.c +++ b/arch/arm/src/stm32/stm32_spi.c @@ -1122,13 +1122,6 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) uint16_t setbits; uint32_t actual; - /* Limit to max possible (if STM32_SPI_CLK_MAX is defined in board.h) */ - - if (frequency > STM32_SPI_CLK_MAX) - { - frequency = STM32_SPI_CLK_MAX; - } - /* Has the frequency changed? */ if (frequency != priv->frequency) From d1cfcabb1f9e6cc1aa8fb7718dfcb9962d1780e7 Mon Sep 17 00:00:00 2001 From: Alexander Oryshchenko Date: Wed, 24 Jan 2018 06:58:47 -0600 Subject: [PATCH 36/40] arch/arm/src/stm32/stm32f40xxx_i2c.c: Correct some recent changes to STM32F4 I2C that broke poll mode of operation. --- arch/arm/src/stm32/stm32f40xxx_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/src/stm32/stm32f40xxx_i2c.c b/arch/arm/src/stm32/stm32f40xxx_i2c.c index 86de66e7f56..9317b3608c0 100644 --- a/arch/arm/src/stm32/stm32f40xxx_i2c.c +++ b/arch/arm/src/stm32/stm32f40xxx_i2c.c @@ -1273,7 +1273,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv) if (priv->dcnt == -1 && priv->msgc != 0 && (status & I2C_SR1_SB) == 0) { -#ifdef CONFIG_STM32_I2C_DMA +#if defined(CONFIG_STM32_I2C_DMA) || defined(CONFIG_I2C_POLLED) return OK; #else priv->status |= I2C_SR1_TIMEOUT; @@ -2049,7 +2049,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv) /* Clear interrupt flags */ -#ifndef CONFIG_STM32_I2C_DMA +#if !defined(CONFIG_STM32_I2C_DMA) && !defined(CONFIG_I2C_POLLED) state_error: #endif stm32_i2c_putreg(priv, STM32_I2C_SR1_OFFSET, 0); From cafb5272629b093a56860d6e6f03cfc2a97e87a7 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 24 Jan 2018 08:52:40 -0600 Subject: [PATCH 37/40] configs/flipnclick-sam3x: Using JTAG (vs. Bossac) I was finally able to load code and verify the basic NSH configuration. Updated READMEs. Also switched to USART0 (vs UART0) for the serial console because I was not getting bi-directional communication on the VCOM. --- configs/arduino-due/README.txt | 6 +++ configs/flipnclick-sam3x/README.txt | 70 +++++++++++++++++--------- configs/flipnclick-sam3x/nsh/defconfig | 4 +- configs/freedom-k64f/README.txt | 2 +- configs/freedom-k66f/README.txt | 5 +- 5 files changed, 59 insertions(+), 28 deletions(-) diff --git a/configs/arduino-due/README.txt b/configs/arduino-due/README.txt index bb6d7f08aa8..0de6bcb4d22 100644 --- a/configs/arduino-due/README.txt +++ b/configs/arduino-due/README.txt @@ -330,6 +330,12 @@ Serial Consoles Loading Code ============ + [NOTE: I believe that there have been significant changes to the more + recent tool environment such that Bossac may no longer be usable. I + don't know that for certain and perhaps someone with more knowledge of + the tools than I could make this work. See the Flip'n'Clip SAM3X README + file for additional information.] + Installing the Arduino USB Driver under Windows: ------------------------------------------------ diff --git a/configs/flipnclick-sam3x/README.txt b/configs/flipnclick-sam3x/README.txt index 6cbf47b5697..8ab7a159a8f 100644 --- a/configs/flipnclick-sam3x/README.txt +++ b/configs/flipnclick-sam3x/README.txt @@ -22,23 +22,11 @@ STATUS ====== 2018-01-07: Created the configuration. At present it does not work; I - believe because of tool-related issues. I do the following: - - a) Open TeraTerm, select COM7 at 1200 baud, type a few ENTERs, and - close teraterm. - - b) Execute the following command which claims to have successfully - written to FLASH. - - bossac.exe --info --debug --port COM7 --usb-port=0 --erase --write --verify -b nuttx.bin -R - - But the code does not boot. There is no indication of life. - - c) Repeat a) then - - bossac.exe --info --debug --port COM7 --usb-port=0 --verify -b nuttx.bin - - And it says that the content of the FLASH is not good. + believe because of tool-related issues. See discussion under "Loading + Code" below. + 2018-01-24: I ordered a JTAG connector and soldered that to the Flip'n'Click + and I am now successfully able to load code. The NSH configuration appears + to be fully functional. Buttons and LEDs ================ @@ -99,10 +87,11 @@ Serial Consoles serial chip connected to the first of the MCU (RX0 and TX0 on PA8 and PA9, respectively). The output from that port is visible using the Arduino tool. - Any of UART and USART0-3 may be used as a serial console. By default, - UART0 is used as the serial console in all configurations. But that is - easily changed by modifying the configuration as described under - "Configurations" below. + [NOTE: My experience so far: I get serial output on the virtual COM port + via the UART, but I receive no serial input for keyboard data entered in + the PC serial terminal. I have not investigated this problem. It may + be something as simple as the Rx pin configuration. Instead, I just + switched to USART0.] Other convenient U[S]ARTs that may be used as the Serial console include: @@ -125,9 +114,22 @@ Serial Consoles transceiver to get the signals to RS232 levels (or connect to the USB virtual COM port in the case of UART0). + Any of UART and USART0-3 may be used as a serial console. UART0 would + be the preferred default console setting. However, due to the communication + problems mentioned above, USART0 is used as the default serial console + in all configurations. But that is easily changed by modifying the + configuration as described under "Configurations" below. + Loading Code ============ + [NOTE: This text was mostly copied from the Arduino Due README.txt. I + believe, however, that there have been significant changes to the + tool environment such that Bossac may no longer be usable. I don't + know that for certain and perhaps someone with more knowledge of + the tools than I could make this work. See STATUS below for the + current issues that I see.] + Installing the Arduino USB Driver under Windows ----------------------------------------------- @@ -302,6 +304,25 @@ Loading Code $ bossac.exe --port=COM7 --usb-port=false --boot=1 Set boot flash true + STATUS: + At present this procedure does not work. I do the following: + + a) Open TeraTerm, select COM7 at 1200 baud, type a few ENTERs, and + close teraterm. + + b) Execute the following command which claims to have successfully + written to FLASH. + + bossac.exe --info --debug --port COM7 --usb-port=0 --erase --write --verify -b nuttx.bin -R + + But the code does not boot. There is no indication of life. + + c) Repeat a) then + + bossac.exe --info --debug --port COM7 --usb-port=0 --verify -b nuttx.bin + + And it says that the content of the FLASH is not good. + Uploading NuttX to the Flip&Click Using JTAG -------------------------------------------- @@ -465,15 +486,16 @@ Configurations reconfiguration process. 2. Unless stated otherwise, all configurations generate console - output on UART0 which is available both on the USB virtual COM port - and on the PWML connector (see the section "Serial Consoles" above). + output on USART0 which is available either on the Arduion Shield + connector or on mikroBUS A as described above in the section entitled + "Serial Consoles". 3. Unless otherwise stated, the configurations are setup for Cygwin under Windows: Build Setup: CONFIG_HOST_WINDOWS=y : Microsoft Windows - CONFIG_WINDIWS_CYGWIN=y : Cygwin under Windoes + CONFIG_WINDIWS_CYGWIN=y : Cygwin under Windows 3. All of these configurations are set up to build under Windows using the "GNU Tools for ARM Embedded Processors" that is maintained by ARM diff --git a/configs/flipnclick-sam3x/nsh/defconfig b/configs/flipnclick-sam3x/nsh/defconfig index 79057461ad6..f0ba4aedf39 100644 --- a/configs/flipnclick-sam3x/nsh/defconfig +++ b/configs/flipnclick-sam3x/nsh/defconfig @@ -1,4 +1,5 @@ # CONFIG_ARCH_RAMFUNCS is not set +# CONFIG_SAM34_UART0 is not set CONFIG_ARCH_BOARD_FLIPNCLICK_SAM3X=y CONFIG_ARCH_BOARD="flipnclick-sam3x" CONFIG_ARCH_CHIP_ATSAM3X8E=y @@ -33,12 +34,13 @@ CONFIG_RAM_SIZE=65536 CONFIG_RAM_START=0x20000000 CONFIG_RAW_BINARY=y CONFIG_RR_INTERVAL=200 +CONFIG_SAM34_USART0=y CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y CONFIG_START_DAY=28 CONFIG_START_MONTH=6 CONFIG_START_YEAR=2013 CONFIG_TASK_NAME_SIZE=0 -CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USART0_SERIAL_CONSOLE=y CONFIG_USER_ENTRYPOINT="nsh_main" CONFIG_WDOG_INTRESERVE=0 diff --git a/configs/freedom-k64f/README.txt b/configs/freedom-k64f/README.txt index 5559b2fe5f1..a2ce126b7de 100644 --- a/configs/freedom-k64f/README.txt +++ b/configs/freedom-k64f/README.txt @@ -618,7 +618,7 @@ GNU Toolchain Options ===================== The NuttX make system supports several GNU-based toolchains under Linux, - Cygwin under Windows, and Windoes native. To select a toolchain: + Cygwin under Windows, and Windows native. To select a toolchain: 1. Use 'make menuconfig' and select the toolchain that you are using under the System Type menu. diff --git a/configs/freedom-k66f/README.txt b/configs/freedom-k66f/README.txt index 7f5da7cffaa..c78a3c4c807 100644 --- a/configs/freedom-k66f/README.txt +++ b/configs/freedom-k66f/README.txt @@ -621,7 +621,7 @@ GNU Toolchain Options ===================== The NuttX make system supports several GNU-based toolchains under Linux, - Cygwin under Windows, and Windoes native. To select a toolchain: + Cygwin under Windows, and Windows native. To select a toolchain: 1. Use 'make menuconfig' and select the toolchain that you are using under the System Type menu. @@ -972,4 +972,5 @@ Status 2017-02-14: nsh: SDHC DMA is not working yet. Buttons and SDIO with automounter is working. netnsh:Is building but Ehternet is not working yet. TX is called but - not IRQ is issued. \ No newline at end of file + not IRQ is issued. + From d314feab82a4bd20ab9b7d3f4e988e5f285b8cf7 Mon Sep 17 00:00:00 2001 From: Matt Thompson Date: Thu, 25 Jan 2018 11:55:40 +0000 Subject: [PATCH 38/40] Merged in extent3d/nuttx (pull request #582) SAMDL: Added SAMD DAC header file. Fixed SAMD EVSYS header. Added SAMD TC header file. Fixed some minor typos * SAMD External Interrupt Controller (EIC) support * removed comment * SAMDL: SPI must be disabled before changing the mode bits in CTRLA register * arch/arm/src/lc823450: Assign I2S IRQ handling to CPU0 Previous commit assumed that the caller is running on CPU0. However, the caller sometimes runs at CPU1. This patch will assign the caller to CPU0 explicitly. Signed-off-by: Masayuki Ishikawa * arch/arm/src/lc823450: Change irqwarn() to ASSERT() in up_ack_irq() Signed-off-by: Masayuki Ishikawa * configs/lc823450-xgevk: Update README.txt and defconfigs Update comments on SMP in README.txt Enable SYSTEM_TIME64 in defconfigs. Enable INSTRUMENTATION in rndis configuration. Signed-off-by: Masayuki Ishikawa * configst/stm3240g-eval: Remove only bogus logic to start the NX server. That was there only to support the knxwm configuration and was implemented priorit to boardctl(BOARCIOC_NX_START). * drivers/input/ft5x06.c: Remove cool logic to disable polling when there there is no client waiting for read data. That was a great idea to save CPU cycles when there is nothing reading from the touchscrren but, unfortunately, does not work with readers that open the driver in non-blocking mode. So I think we just have to eat the CPUs even when there is nothing waiting for touchscreen input. * configs/lpcxpresso-lpc54628/lvgl: Add LittlevGL graphics demo configuration. * configs/lpcxpresso-lpc54628: Update README * include/termios.h: Update comments; fix long lines. * sched/semaphore: Add ASSERT(false) in nxsem_post() if no waiting task is found. Signed-off-by: Masayuki Ishikawa * sched/sched/sched_sporadic.c: fix compiler error when priority inheritance is enabled. Noted by eunb.song@samsung.com * Change ASSERT(false) to DEBUGPANIC(). * Documentation: Fix copy/paste error in NX graphics document. Noted by Henjiu Kang. * sched/sched: Fix some priority inheritance related issues noted during review of logic. Also add some REVISIT comments for some issues noted in the design. * Update README and some comments * Issue #85: /dev/userleds is not working for nucleo-l432kc fixed * configs/nucleo-l432kc: Fix numerous cloning errors/typos. * Update TODO list * NUCLEO F432KC typo fixed, correct name is L432KC Just README.txt and comments affected, no changes in the code * Merged in raiden00/nuttx (pull request #579) Master * stm32_hritm: add interface to get timer clock frequency stm32_hrtim: fix timer freq calculation stm32_hrtim: add compar/capture registers significant bits checking stm32_hrtim: minor changes * stm32f334-disco: add buck converter and boost converter logic Approved-by: Gregory Nutt * fs/userfs: use correct req type in userfs_truncate, remove use of undeclared buf * Merged in david_alessio/nuttx/refactor-pll-setup (pull request #581) Refactor pll setup * fix typo in #def * refactor PLL setup code... * refactored PLL/CLK config, easier, checks for correctness * call go_os_start if STACK_COLORIZED * smarter config of EXTCLK output freq * cosmetic Approved-by: Gregory Nutt * The existence of the network driver ioctl() method should depend on CONFIG_NETDEV_IOCTL rather than CONFIG_NETDEV_PHY_IOCTL. The former enables the method, the later enables a subset of possible driver IOCTLs. This change should be basically a no-operation. The affected ioctl methods only support those subset of driver IOCTLs selected by CONFIG_NETDEV_PHY_IOCTL and the network logic will tolerate a nul ioctl method. * net/tcp: Write buffering logic should not wait for a free buffer if the socket was opened non-blocking. Also, rename the TCP write buffering macros from WRB_* to TCPWB_* to make room in the namespace for write buffering with other protocols. * net/udp: Remove some conditional logic that was true if there is only a single network device, but not true in the multi-device context. * This commit adds an as-of-yet untested implemented of UDP write buffering. Squashed commit of the following: net/udp: Address most of the issues with UDP write buffering. There is a remaining issue with handling one network going down in a multi-network environment. None of this has been test but it is certainly ready for test. Hence, the feature is marked EXPERIMENTAL. net/udp: Some baby steps toward a corrected write buffering design. net/udp: Remove pesky write buffer macros. Eliminate trailing space at the end of lines. net/udp: A little more UDP write buffering logic. Still at least on big gaping hole in the design. net/udp: Undefined CONFIG_NET_SENDTO_TIMEOUT. net/udp: Crude, naive port of the TCP write buffering logic into UDP. This commit is certainly non-functional and is simply a starting point for the implementatin of UDP write buffering. net/udp: Rename udp/udp_psock_sendto.c udp/udp_psock_sendto_unbuffered.c. * net/udp: In sendto(), return EHOSTUNREACH if if the network is down. * net/udp: Resolves final design issues with UDP write buffering. 100% code complete but also 100% untested. * net/udp and tcp: Yet another (cosmetic) change to UDP and TCP write buffer macro naming. * net/udp: UDP write buffering is basically functional but needs a lot more verification. * net/udp: Fix memory leak with UDP + write buffer is closed. Also update TODO and comments and refresh a configuration. * Update some comments. * drivers/mtd/at24xx.c: Correct page size for AT24C02 part. * arch/arm/src/stm32: Make STM32 usable with an external RTC. drivers/timers/ds3231.c: Correct some debug statments. * arch/arm/src/stm32/stm32_spi.c: Removed unnecessary (and incorrect) speed limitation * arch/arm/src/stm32/stm32f40xxx_i2c.c: Correct some recent changes to STM32F4 I2C that broke poll mode of operation. * configs/flipnclick-sam3x: Using JTAG (vs. Bossac) I was finally able to load code and verify the basic NSH configuration. Updated READMEs. Also switched to USART0 (vs UART0) for the serial console because I was not getting bi-directional communication on the VCOM. * SAMDL: Added SAMD DAC header file. Fixed SAMD EVSYS header. Added SAMD TC header file. Fixed some minor typos * fix typo * added missing EVCTRL register bits in TC Approved-by: Gregory Nutt --- arch/arm/src/samdl/chip/samd_dac.h | 136 ++++++++++++++ arch/arm/src/samdl/chip/samd_evsys.h | 34 ++-- arch/arm/src/samdl/chip/samd_tc.h | 254 +++++++++++++++++++++++++++ arch/arm/src/samdl/sam_dac.h | 77 ++++++++ arch/arm/src/samdl/sam_evsys.h | 76 ++++++++ arch/arm/src/samdl/samd_periphclks.h | 6 +- 6 files changed, 565 insertions(+), 18 deletions(-) create mode 100644 arch/arm/src/samdl/chip/samd_dac.h create mode 100644 arch/arm/src/samdl/chip/samd_tc.h create mode 100644 arch/arm/src/samdl/sam_dac.h create mode 100644 arch/arm/src/samdl/sam_evsys.h diff --git a/arch/arm/src/samdl/chip/samd_dac.h b/arch/arm/src/samdl/chip/samd_dac.h new file mode 100644 index 00000000000..274cab701ef --- /dev/null +++ b/arch/arm/src/samdl/chip/samd_dac.h @@ -0,0 +1,136 @@ +/******************************************************************************************** + * arch/arm/src/samdl/chip/saml_dac.h + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * "Atmel SAM L21E / SAM L21G / SAM L21J Smart ARM-Based Microcontroller + * Datasheet", Atmel-42385C-SAML21_Datasheet_Preliminary-03/20/15 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_SAMDL_CHIP_SAMD_DAC_H +#define __ARCH_ARM_SRC_SAMDL_CHIP_SAMD_DAC_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +#include "chip.h" + +#ifdef CONFIG_ARCH_FAMILY_SAMD21 + +/******************************************************************************************** + * Pre-processor Definitions + ********************************************************************************************/ +/* DAC register offsets ********************************************************************/ + +#define SAM_DAC_CTRLA_OFFSET 0x0000 /* Control A Register */ +#define SAM_DAC_CTRLB_OFFSET 0x0001 /* Control B Register */ +#define SAM_DAC_EVCTRL_OFFSET 0x0002 /* Event Control Register */ +#define SAM_DAC_INTENCLR_OFFSET 0x0004 /* Interrupt Enable Clear Register */ +#define SAM_DAC_INTENSET_OFFSET 0x0005 /* Interrupt Enable Set Register */ +#define SAM_DAC_INTFLAG_OFFSET 0x0006 /* Interrupt Flag Status and Clear Register */ +#define SAM_DAC_STATUS_OFFSET 0x0007 /* Status Register */ +#define SAM_DAC_DATA0_OFFSET 0x0008 /* Data DAC0 Register */ +#define SAM_DAC_DATA1_OFFSET 0x0009 /* Data DAC1 Register */ +#define SAM_DAC_DATABUF0_OFFSET 0x000C /* Data Buffer DAC0 Register */ +#define SAM_DAC_DATABUF1_OFFSET 0x000D /* Data Buffer DAC1 Register */ + +/* DAC register addresses ******************************************************************/ + +#define SAM_DAC_CTRLA (SAM_DAC_BASE+SAM_DAC_CTRLA_OFFSET) +#define SAM_DAC_CTRLB (SAM_DAC_BASE+SAM_DAC_CTRLB_OFFSET) +#define SAM_DAC_EVCTRL (SAM_DAC_BASE+SAM_DAC_EVCTRL_OFFSET) +#define SAM_DAC_INTENCLR (SAM_DAC_BASE+SAM_DAC_INTENCLR_OFFSET) +#define SAM_DAC_INTENSET (SAM_DAC_BASE+SAM_DAC_INTENSET_OFFSET) +#define SAM_DAC_INTFLAG (SAM_DAC_BASE+SAM_DAC_INTFLAG_OFFSET) +#define SAM_DAC_STATUS (SAM_DAC_BASE+SAM_DAC_STATUS_OFFSET) +#define SAM_DAC_DATA0 (SAM_DAC_BASE+SAM_DAC_DATA0_OFFSET) +#define SAM_DAC_DATA1 (SAM_DAC_BASE+SAM_DAC_DATA1_OFFSET) +#define SAM_DAC_DATABUF0 (SAM_DAC_BASE+SAM_DAC_DATABUF0_OFFSET) +#define SAM_DAC_DATABUF1 (SAM_DAC_BASE+SAM_DAC_DATABUF1_OFFSET) + +/* DAC register bit definitions ************************************************************/ + +/* Control A Register */ + +#define DAC_CTRLA_SWRTS (1 << 0) /* Bit 0: Software reset */ +#define DAC_CTRLA_ENABLE (1 << 1) /* Bit 1: Enable DAC controller */ +#define DAC_CTRLA_RUNSTDBY (1 << 2) /* Bit 1: Run in standby */ + +/* Control B Register */ + +#define DAC_CTRLB_EOEN (1 << 0) /* Bit 0: External Output Enable (to Vout) */ +#define DAC_CTRLB_IOEN (1 << 1) /* Bit 1: Internal Output Enable (to analog comparator) */ +#define DAC_CTRLB_LEFTADJ (1 << 2) /* Bit 2: Left-Adjusted Data */ +#define DAC_CTRLB_VPD (1 << 3) /* Bit 3: Voltage Pump Disabled */ +#define DAC_CTRLB_BDWP (1 << 4) /* Bit 4: Bypass DATABUF Write protection */ +#define DAC_CTRLB_REFSEL_SHIFT (6) /* Bit 7:6: Reference selection */ +#define DAC_CTRLB_REFSEL_MASK (3 << DAC_CTRLB_REFSEL_SHIFT) +# define DAC_CTRLB_REFSEL_INTREF (0 << DAC_CTRLB_REFSEL_SHIFT) /* Internal voltage reference */ +# define DAC_CTRLB_REFSEL_VDDANA (1 << DAC_CTRLB_REFSEL_SHIFT) /* Analog voltage supply */ +# define DAC_CTRLB_REFSEL_VREFA (2 << DAC_CTRLB_REFSEL_SHIFT) /* External voltage reference */ + +/* Event Control Register */ + +#define DAC_EVCTRL_STARTEI (1 << 0) /* Bit 0: Start conversion event input */ +#define DAC_EVCTRL_EMPTYEO (1 << 1) /* Bit 1: Data buffer empty event output */ + +/* Common bit definitions for Interrupt Enable Clear Register, Interrupt Enable Set + * Register, and Interrupt Flag Status and Clear Register + */ + +#define DAC_INT_UNDERRUN (1 << 0) /* Bit 0: Underrun interrupt */ +#define DAC_INT_EMPTY (1 << 1) /* Bit 1: Data buffer empty interrupt */ +#define DAC_INT_SYNCRDY (1 << 2) /* Bit 2: Sync ready */ +#define DAC_INT_ALL 0x07 + +/* Status Register */ + +#define DAC_STATUS_SYNCBUSY (1 << 7) /* Bit 0: Sync busy */ + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ + +/******************************************************************************************** + * Public Data + ********************************************************************************************/ + +/******************************************************************************************** + * Public Functions + ********************************************************************************************/ + +#endif /* CONFIG_ARCH_FAMILY_SAMD21 */ +#endif /* __ARCH_ARM_SRC_SAMDL_CHIP_SAMD_DAC_H */ diff --git a/arch/arm/src/samdl/chip/samd_evsys.h b/arch/arm/src/samdl/chip/samd_evsys.h index e1489a2622b..84ea384f092 100644 --- a/arch/arm/src/samdl/chip/samd_evsys.h +++ b/arch/arm/src/samdl/chip/samd_evsys.h @@ -68,9 +68,9 @@ #define SAM_EVSYS_CTRL (SAM_EVSYS_BASE+SAM_EVSYS_CTRL_OFFSET) #define SAM_EVSYS_CHANNEL (SAM_EVSYS_BASE+SAM_EVSYS_CHANNEL_OFFSET) #define SAM_EVSYS_USER (SAM_EVSYS_BASE+SAM_EVSYS_USER_OFFSET) -#define SAM_EVSYS_CHSTATUS (SAM_EVSYS_BASE+SAM_EVSYS_CHSTATUS_OFFSET -#define SAM_EVSYS_INTENCLR (SAM_EVSYS_BASE+SAM_EVSYS_INTENCLR_OFFSET -#define SAM_EVSYS_INTENSET (SAM_EVSYS_BASE+SAM_EVSYS_INTENSET_OFFSET +#define SAM_EVSYS_CHSTATUS (SAM_EVSYS_BASE+SAM_EVSYS_CHSTATUS_OFFSET) +#define SAM_EVSYS_INTENCLR (SAM_EVSYS_BASE+SAM_EVSYS_INTENCLR_OFFSET) +#define SAM_EVSYS_INTENSET (SAM_EVSYS_BASE+SAM_EVSYS_INTENSET_OFFSET) #define SAM_EVSYS_INTFLAG (SAM_EVSYS_BASE+SAM_EVSYS_INTFLAG_OFFSET) /* EVSYS register bit definitions ***********************************************************/ @@ -302,12 +302,14 @@ /* Channel status register */ -#define EVSYS_CHSTATUS_USRRDY_SHIFT (0) /* Bits 0-7: User Ready for Channel n, n=0-7 */ -#define EVSYS_CHSTATUS_USRRDY_MASK (0xff << EVSYS_CHSTATUS_USRRDY_SHIFT) -# define EVSYS_CHSTATUS_USRRDY(n) (1 << (n)) -#define EVSYS_CHSTATUS_CHBUSY_SHIFT (8) /* Bits 8-15: Channel Busy n, n=0-7 */ -#define EVSYS_CHSTATUS_CHBUSY_MASK (0xff << EVSYS_CHSTATUS_CHBUSY_SHIFT) -# define EVSYS_CHSTATUS_CHBUSY(n) (1 << ((n) + 8)) +#ifdef CONFIG_ARCH_FAMILY_SAMD20 +# define EVSYS_CHSTATUS_USRRDY_SHIFT (0) /* Bits 0-7: User Ready for Channel n, n=0-7 */ +# define EVSYS_CHSTATUS_USRRDY_MASK (0xff << EVSYS_CHSTATUS_USRRDY_SHIFT) +# define EVSYS_CHSTATUS_USRRDY(n) (1 << (n)) +# define EVSYS_CHSTATUS_CHBUSY_SHIFT (8) /* Bits 8-15: Channel Busy n, n=0-7 */ +# define EVSYS_CHSTATUS_CHBUSY_MASK (0xff << EVSYS_CHSTATUS_CHBUSY_SHIFT) +# define EVSYS_CHSTATUS_CHBUSY(n) (1 << ((n) + 8)) +#endif #ifdef CONFIG_ARCH_FAMILY_SAMD21 # define EVSYS_CHSTATUS_USRRDYH_SHIFT (16) /* Bits 16-19: User Ready for Channel n, n=8-11 */ @@ -320,12 +322,14 @@ /* Interrupt enable clear, interrupt enable set, and interrupt flag status and clear registers */ -#define EVSYS_INT_OVR_SHIFT (0) /* Bits 0-7: Overrun channel n interrupt, n=0-7 */ -#define EVSYS_INT_OVR_MASK (0xff << EVSYS_INT_OVR_SHIFT) -# define EVSYS_INT_OVR(n) (1 << (n)) -#define EVSYS_INT_EVD_SHIFT (8) /* Bits 8-15: Event detected channel n interrupt, n=0-7 */ -#define EVSYS_INT_EVD_MASK (0xff << EVSYS_INT_EVD_SHIFT) -# define EVSYS_INT_EVD(n) (1 << ((n) + 8)) +#ifdef CONFIG_ARCH_FAMILY_SAMD20 +# define EVSYS_INT_OVR_SHIFT (0) /* Bits 0-7: Overrun channel n interrupt, n=0-7 */ +# define EVSYS_INT_OVR_MASK (0xff << EVSYS_INT_OVR_SHIFT) +# define EVSYS_INT_OVR(n) (1 << (n)) +# define EVSYS_INT_EVD_SHIFT (8) /* Bits 8-15: Event detected channel n interrupt, n=0-7 */ +# define EVSYS_INT_EVD_MASK (0xff << EVSYS_INT_EVD_SHIFT) +# define EVSYS_INT_EVD(n) (1 << ((n) + 8)) +#endif #ifdef CONFIG_ARCH_FAMILY_SAMD21 # define EVSYS_INT_OVR_SHIFT (16) /* Bits 16-19: Overrun channel n interrupt, n=8-11 */ diff --git a/arch/arm/src/samdl/chip/samd_tc.h b/arch/arm/src/samdl/chip/samd_tc.h new file mode 100644 index 00000000000..fe3d2c40592 --- /dev/null +++ b/arch/arm/src/samdl/chip/samd_tc.h @@ -0,0 +1,254 @@ +/******************************************************************************************** + * arch/arm/src/samdl/chip/samd_tc.h + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Matt Thompson + * + * References: + * "Microchip SAMD21 datasheet" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ********************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_SAMDL_CHIP_SAMD_TC_H +#define __ARCH_ARM_SRC_SAMDL_CHIP_SAMD_TC_H + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +#include "chip.h" + +#ifdef CONFIG_ARCH_FAMILY_SAMD21 + +/******************************************************************************************** + * Pre-processor Definitions + ********************************************************************************************/ +/* TC register offsets *********************************************************************/ + +#define SAM_TC_CTRLA_OFFSET 0x0000 /* Control A register */ +#define SAM_TC_READREQ_OFFSET 0x0002 /* Read request register */ +#define SAM_TC_CTRLBCLR_OFFSET 0x0004 /* Control B clear register */ +#define SAM_TC_CTRLBSET_OFFSET 0x0005 /* Control B clear register */ +#define SAM_TC_CTRLC_OFFSET 0x0006 /* Control C register */ +#define SAM_TC_DBGCTRL_OFFSET 0x0008 /* Debug control register */ +#define SAM_TC_EVCTRL_OFFSET 0x000A /* Event control register */ +#define SAM_TC_INTENCLR_OFFSET 0x000C /* Interrupt enable clear register */ +#define SAM_TC_INTENSET_OFFSET 0x000D /* Interrupt enable set register */ +#define SAM_TC_INTFLAG_OFFSET 0x000E /* Interrupt flag register */ +#define SAM_TC_STATUS_OFFSET 0x000F /* Status register */ +#define SAM_TC_COUNT_OFFSET 0x0010 /* Count register */ +#define SAM_TC_CC0_OFFSET 0x0018 /* Capture Compare 0 register */ +#define SAM_TC_CC1_OFFSET 0x001C /* Capture Compare 1 register */ + +/* TC register addresses *******************************************************************/ + +#define SAM_TC3_CTRLA (SAM_TC3_BASE+SAM_TC_CTRLA_OFFSET) +#define SAM_TC3_READREQ (SAM_TC3_BASE+SAM_TC_READREQ_OFFSET) +#define SAM_TC3_CTRLBCLR (SAM_TC3_BASE+SAM_TC_CTRLBCLR_OFFSET) +#define SAM_TC3_CTRLBSET (SAM_TC3_BASE+SAM_TC_CTRLBSET_OFFSET) +#define SAM_TC3_CTRLC (SAM_TC3_BASE+SAM_TC_CTRLC_OFFSET) +#define SAM_TC3_DBGCTRL (SAM_TC3_BASE+SAM_TC_DBGCTRL_OFFSET) +#define SAM_TC3_EVCTRL (SAM_TC3_BASE+SAM_TC_EVCTRL_OFFSET) +#define SAM_TC3_INTENCLR (SAM_TC3_BASE+SAM_TC_INTENCLR_OFFSET) +#define SAM_TC3_INTENSET (SAM_TC3_BASE+SAM_TC_INTENSET_OFFSET) +#define SAM_TC3_INTFLAG (SAM_TC3_BASE+SAM_TC_INTFLAG_OFFSET) +#define SAM_TC3_STATUS (SAM_TC3_BASE+SAM_TC_STATUS_OFFSET) +#define SAM_TC3_COUNT (SAM_TC3_BASE+SAM_TC_COUNT_OFFSET) +#define SAM_TC3_CC0 (SAM_TC3_BASE+SAM_TC_CC0_OFFSET) +#define SAM_TC3_CC1 (SAM_TC3_BASE+SAM_TC_CC1_OFFSET) + +#define SAM_TC4_CTRLA (SAM_TC4_BASE+SAM_TC_CTRLA_OFFSET) +#define SAM_TC4_READREQ (SAM_TC4_BASE+SAM_TC_READREQ_OFFSET) +#define SAM_TC4_CTRLBCLR (SAM_TC4_BASE+SAM_TC_CTRLBCLR_OFFSET) +#define SAM_TC4_CTRLBSET (SAM_TC4_BASE+SAM_TC_CTRLBSET_OFFSET) +#define SAM_TC4_CTRLC (SAM_TC4_BASE+SAM_TC_CTRLC_OFFSET) +#define SAM_TC4_DBGCTRL (SAM_TC4_BASE+SAM_TC_DBGCTRL_OFFSET) +#define SAM_TC4_EVCTRL (SAM_TC4_BASE+SAM_TC_EVCTRL_OFFSET) +#define SAM_TC4_INTENCLR (SAM_TC4_BASE+SAM_TC_INTENCLR_OFFSET) +#define SAM_TC4_INTENSET (SAM_TC4_BASE+SAM_TC_INTENSET_OFFSET) +#define SAM_TC4_INTFLAG (SAM_TC4_BASE+SAM_TC_INTFLAG_OFFSET) +#define SAM_TC4_STATUS (SAM_TC4_BASE+SAM_TC_STATUS_OFFSET) +#define SAM_TC4_COUNT (SAM_TC4_BASE+SAM_TC_COUNT_OFFSET) +#define SAM_TC4_CC0 (SAM_TC4_BASE+SAM_TC_CC0_OFFSET) +#define SAM_TC4_CC1 (SAM_TC4_BASE+SAM_TC_CC1_OFFSET) + +#define SAM_TC5_CTRLA (SAM_TC5_BASE+SAM_TC_CTRLA_OFFSET) +#define SAM_TC5_READREQ (SAM_TC5_BASE+SAM_TC_READREQ_OFFSET) +#define SAM_TC5_CTRLBCLR (SAM_TC5_BASE+SAM_TC_CTRLBCLR_OFFSET) +#define SAM_TC5_CTRLBSET (SAM_TC5_BASE+SAM_TC_CTRLBSET_OFFSET) +#define SAM_TC5_CTRLC (SAM_TC5_BASE+SAM_TC_CTRLC_OFFSET) +#define SAM_TC5_DBGCTRL (SAM_TC5_BASE+SAM_TC_DBGCTRL_OFFSET) +#define SAM_TC5_EVCTRL (SAM_TC5_BASE+SAM_TC_EVCTRL_OFFSET) +#define SAM_TC5_INTENCLR (SAM_TC5_BASE+SAM_TC_INTENCLR_OFFSET) +#define SAM_TC5_INTENSET (SAM_TC5_BASE+SAM_TC_INTENSET_OFFSET) +#define SAM_TC5_INTFLAG (SAM_TC5_BASE+SAM_TC_INTFLAG_OFFSET) +#define SAM_TC5_STATUS (SAM_TC5_BASE+SAM_TC_STATUS_OFFSET) +#define SAM_TC5_COUNT (SAM_TC5_BASE+SAM_TC_COUNT_OFFSET) +#define SAM_TC5_CC0 (SAM_TC5_BASE+SAM_TC_CC0_OFFSET) +#define SAM_TC5_CC1 (SAM_TC5_BASE+SAM_TC_CC1_OFFSET) + +#define SAM_TC6_CTRLA (SAM_TC6_BASE+SAM_TC_CTRLA_OFFSET) +#define SAM_TC6_READREQ (SAM_TC6_BASE+SAM_TC_READREQ_OFFSET) +#define SAM_TC6_CTRLBCLR (SAM_TC6_BASE+SAM_TC_CTRLBCLR_OFFSET) +#define SAM_TC6_CTRLBSET (SAM_TC6_BASE+SAM_TC_CTRLBSET_OFFSET) +#define SAM_TC6_CTRLC (SAM_TC6_BASE+SAM_TC_CTRLC_OFFSET) +#define SAM_TC6_DBGCTRL (SAM_TC6_BASE+SAM_TC_DBGCTRL_OFFSET) +#define SAM_TC6_EVCTRL (SAM_TC6_BASE+SAM_TC_EVCTRL_OFFSET) +#define SAM_TC6_INTENCLR (SAM_TC6_BASE+SAM_TC_INTENCLR_OFFSET) +#define SAM_TC6_INTENSET (SAM_TC6_BASE+SAM_TC_INTENSET_OFFSET) +#define SAM_TC6_INTFLAG (SAM_TC6_BASE+SAM_TC_INTFLAG_OFFSET) +#define SAM_TC6_STATUS (SAM_TC6_BASE+SAM_TC_STATUS_OFFSET) +#define SAM_TC6_COUNT (SAM_TC6_BASE+SAM_TC_COUNT_OFFSET) +#define SAM_TC6_CC0 (SAM_TC6_BASE+SAM_TC_CC0_OFFSET) +#define SAM_TC6_CC1 (SAM_TC6_BASE+SAM_TC_CC1_OFFSET) + +#define SAM_TC7_CTRLA (SAM_TC7_BASE+SAM_TC_CTRLA_OFFSET) +#define SAM_TC7_READREQ (SAM_TC7_BASE+SAM_TC_READREQ_OFFSET) +#define SAM_TC7_CTRLBCLR (SAM_TC7_BASE+SAM_TC_CTRLBCLR_OFFSET) +#define SAM_TC7_CTRLBSET (SAM_TC7_BASE+SAM_TC_CTRLBSET_OFFSET) +#define SAM_TC7_CTRLC (SAM_TC7_BASE+SAM_TC_CTRLC_OFFSET) +#define SAM_TC7_DBGCTRL (SAM_TC7_BASE+SAM_TC_DBGCTRL_OFFSET) +#define SAM_TC7_EVCTRL (SAM_TC7_BASE+SAM_TC_EVCTRL_OFFSET) +#define SAM_TC7_INTENCLR (SAM_TC7_BASE+SAM_TC_INTENCLR_OFFSET) +#define SAM_TC7_INTENSET (SAM_TC7_BASE+SAM_TC_INTENSET_OFFSET) +#define SAM_TC7_INTFLAG (SAM_TC7_BASE+SAM_TC_INTFLAG_OFFSET) +#define SAM_TC7_STATUS (SAM_TC7_BASE+SAM_TC_STATUS_OFFSET) +#define SAM_TC7_COUNT (SAM_TC7_BASE+SAM_TC_COUNT_OFFSET) +#define SAM_TC7_CC0 (SAM_TC7_BASE+SAM_TC_CC0_OFFSET) +#define SAM_TC7_CC1 (SAM_TC7_BASE+SAM_TC_CC1_OFFSET) + +/* TC register bit definitions *************************************************************/ + +/* Control A register */ + +#define TC_CTRLA_SWRST (1 << 0) /* Bit 0: Software reset */ +#define TC_CTRLA_ENABLE (1 << 1) /* Bit 1: Enable */ +#define TC_CTRLA_MODE_SHIFT (2) +#define TC_CTRLA_MODE_MASK (3 << TC_CTRLA_MODE_SHIFT) +# define TC_CTRLA_MODE_COUNT16 (0 << TC_CTRLA_MODE_SHIFT) +# define TC_CTRLA_MODE_COUNT8 (1 << TC_CTRLA_MODE_SHIFT) +# define TC_CTRLA_MODE_COUNT32 (2 << TC_CTRLA_MODE_SHIFT) +#define TC_CTRLA_WAVEGEN_SHIFT (5) +#define TC_CTRLA_WAVEGEN_MASK (3 << TC_CTRLA_WAVEGEN_SHIFT) +# define TC_CTRLA_WAVEGEN_NFRQ (0 << TC_CTRLA_WAVEGEN_SHIFT) +# define TC_CTRLA_WAVEGEN_MFRQ (1 << TC_CTRLA_WAVEGEN_SHIFT) +# define TC_CTRLA_WAVEGEN_NPWM (2 << TC_CTRLA_WAVEGEN_SHIFT) +# define TC_CTRLA_WAVEGEN_MPWM (3 << TC_CTRLA_WAVEGEN_SHIFT) +#define TC_CTRLA_PRESCALER_SHIFT (8) +#define TC_CTRLA_PRESCALER_MASK (7 << TC_CTRLA_PRESCALER_SHIFT) +# define TC_CTRLA_PRESCALER_DIV1 (0 << TC_CTRLA_PRESCALER_SHIFT) +# define TC_CTRLA_PRESCALER_DIV2 (1 << TC_CTRLA_PRESCALER_SHIFT) +# define TC_CTRLA_PRESCALER_DIV4 (2 << TC_CTRLA_PRESCALER_SHIFT) +# define TC_CTRLA_PRESCALER_DIV8 (3 << TC_CTRLA_PRESCALER_SHIFT) +# define TC_CTRLA_PRESCALER_DIV16 (4 << TC_CTRLA_PRESCALER_SHIFT) +# define TC_CTRLA_PRESCALER_DIV64 (5 << TC_CTRLA_PRESCALER_SHIFT) +# define TC_CTRLA_PRESCALER_DIV256 (6 << TC_CTRLA_PRESCALER_SHIFT) +# define TC_CTRLA_PRESCALER_DIV1024 (7 << TC_CTRLA_PRESCALER_SHIFT) +#define TC_CTRLA_RUNSTDBY (1 << 11) +#define TC_CTRLA_PRESCSYNC_SHIFT (12) +#define TC_CTRLA_PRESCSYNC_MASK (3 << TC_CTRLA_PRESCSYNC_SHIFT) +# define TC_CTRLA_PRESCSYNC_GCLK (0 << TC_CTRLA_PRESCSYNC_SHIFT) +# define TC_CTRLA_PRESCSYNC_PRESC (1 << TC_CTRLA_PRESCSYNC_SHIFT) +# define TC_CTRLA_PRESCSYNC_RESYNC (2 << TC_CTRLA_PRESCSYNC_SHIFT) + +/* Read Request register */ + +#define TC_READREQ_ADDR_SHIFT (0) +#define TC_READREQ_ADDR_MASK (0x1F << TC_READREQ_ADDR_SHIFT) +#define TC_READREQ_RCONT (1 << 14) +#define TC_READREQ_RREQ (1 << 15) + +/* Control B Set/Clear register */ + +#define TC_CTRLB_DIR (1 << 0) +#define TC_CTRLB_ONESHOT (1 << 2) +#define TC_CTRLB_CMD_SHIFT (6) +#define TC_CTRLB_CMD_MASK (3 << TC_CTRLBCLR_CMD_SHIFT) +# define TC_CTRLB_CMD_NONE (0 << TC_CTRLBCLR_CMD_SHIFT) +# define TC_CTRLB_CMD_RETRIGGER (1 << TC_CTRLBCLR_CMD_SHIFT) +# define TC_CTRLB_CMD_STOP (2 << TC_CTRLBCLR_CMD_SHIFT) + +/* Control C register */ + +#define TC_CTRLC_INVEN0 (1 << 0) +#define TC_CTRLC_INVEN1 (1 << 1) +#define TC_CTRLC_CPTEN0 (1 << 4) +#define TC_CTRLC_CPTEN1 (1 << 5) + +/* Debug control register */ + +#define TC_DBGCTRL_DBGRUN (1 << 0) + +/* Event control register */ + +#define TC_EVCTRL_EVACT_SHIFT (0) +#define TC_EVCTRL_EVACT_MASK (7 << TC_EVCTRL_EVACT_SHIFT) +# define TC_EVCTRL_EVACT_OFF (0 << TC_EVCTRL_EVACT_SHIFT) +# define TC_EVCTRL_EVACT_RETRIGGER (1 << TC_EVCTRL_EVACT_SHIFT) +# define TC_EVCTRL_EVACT_COUNT (2 << TC_EVCTRL_EVACT_SHIFT) +# define TC_EVCTRL_EVACT_START (3 << TC_EVCTRL_EVACT_SHIFT) +# define TC_EVCTRL_EVACT_PPW (5 << TC_EVCTRL_EVACT_SHIFT) +# define TC_EVCTRL_EVACT_PWP (6 << TC_EVCTRL_EVACT_SHIFT) +#define TC_EVCTRL_TCINV (1 << 4) +#define TC_EVCTRL_TCEI (1 << 5) +#define TC_EVCTRL_OVFEO (1 << 8) +#define TC_EVCTRL_MCEO0 (1 << 12) +#define TC_EVCTRL_MCEO1 (1 << 13) + +/* Interrupt register bits */ + +#define TC_INT_OVF (1 << 0) +#define TC_INT_ERR (1 << 1) +#define TC_INT_SYNCRDY (1 << 3) +#define TC_INT_MC0 (1 << 4) +#define TC_INT_MC1 (1 << 5) + +/* Status register */ + +#define TC_STATUS_STOP (1 << 3) +#define TC_STATUS_SLAVE (1 << 4) +#define TC_STATUS_SYNCBUSY (1 << 7) + +/******************************************************************************************** + * Public Types + ********************************************************************************************/ + +/******************************************************************************************** + * Public Data + ********************************************************************************************/ + +/******************************************************************************************** + * Public Functions + ********************************************************************************************/ + +#endif /* CONFIG_ARCH_FAMILY_SAMD21 */ +#endif /* __ARCH_ARM_SRC_SAMDL_CHIP_SAMD_TC_H */ diff --git a/arch/arm/src/samdl/sam_dac.h b/arch/arm/src/samdl/sam_dac.h new file mode 100644 index 00000000000..b78afd36c1d --- /dev/null +++ b/arch/arm/src/samdl/sam_dac.h @@ -0,0 +1,77 @@ +/**************************************************************************** + * arch/arm/src/samdl/sam_dac.h + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Matt Thompson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_SAMDL_SAM_DAC_H +#define __ARCH_ARM_SRC_SAMDL_SAM_DAC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "sam_config.h" +#include "sam_port.h" + +#if defined(CONFIG_ARCH_FAMILY_SAMD20) || defined(CONFIG_ARCH_FAMILY_SAMD21) +# include "chip/samd_dac.h" +#elif defined(CONFIG_ARCH_FAMILY_SAML21) +# include "chip/saml_dac.h" +#else +# error Unrecognized SAMD/L architecture +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ARCH_ARM_SRC_SAMDL_SAM_DAC_H */ diff --git a/arch/arm/src/samdl/sam_evsys.h b/arch/arm/src/samdl/sam_evsys.h new file mode 100644 index 00000000000..13b41fa3e55 --- /dev/null +++ b/arch/arm/src/samdl/sam_evsys.h @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/arm/src/samdl/sam_evsys.h + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Matt Thompson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_SAMDL_SAM_EVSYS_H +#define __ARCH_ARM_SRC_SAMDL_SAM_EVSYS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "sam_config.h" +#include "sam_port.h" + +#if defined(CONFIG_ARCH_FAMILY_SAMD20) || defined(CONFIG_ARCH_FAMILY_SAMD21) +# include "chip/samd_evsys.h" +#elif defined(CONFIG_ARCH_FAMILY_SAML21) +# include "chip/saml_evsys.h" +#else +# error Unrecognized SAMD/L architecture +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ARCH_ARM_SRC_SAMDL_SAM_EVSYS_H */ diff --git a/arch/arm/src/samdl/samd_periphclks.h b/arch/arm/src/samdl/samd_periphclks.h index 0ba3df0f879..e5de81f754d 100644 --- a/arch/arm/src/samdl/samd_periphclks.h +++ b/arch/arm/src/samdl/samd_periphclks.h @@ -75,7 +75,7 @@ #define sam_apbc_enableperiph(s) modifyreg32(SAM_PM_APBCMASK,0,s) #define sam_pac2_enableperiph() sam_apbc_enableperiph(PM_APBCMASK_PAC2) -#define sam_devsys_enableperiph() sam_apbc_enableperiph(PM_APBCMASK_EVSYS) +#define sam_evsys_enableperiph() sam_apbc_enableperiph(PM_APBCMASK_EVSYS) #define sam_sercom_enableperiph(n) sam_apbc_enableperiph(PM_APBCMASK_SERCOM(n)) #define sam_sercom0_enableperiph() sam_apbc_enableperiph(PM_APBCMASK_SERCOM0) #define sam_sercom1_enableperiph() sam_apbc_enableperiph(PM_APBCMASK_SERCOM1) @@ -135,7 +135,7 @@ #define sam_apbc_disableperiph(s) modifyreg32(SAM_PM_APBCMASK,s,0) #define sam_pac2_disableperiph() sam_apbc_disableperiph(PM_APBCMASK_PAC2) -#define sam_devsys_disableperiph() sam_apbc_disableperiph(PM_APBCMASK_EVSYS) +#define sam_evsys_disableperiph() sam_apbc_disableperiph(PM_APBCMASK_EVSYS) #define sam_sercom_disableperiph(n) sam_apbc_disableperiph(PM_APBCMASK_SERCOM(n)) #define sam_sercom0_disableperiph() sam_apbc_disableperiph(PM_APBCMASK_SERCOM0) #define sam_sercom1_disableperiph() sam_apbc_disableperiph(PM_APBCMASK_SERCOM1) @@ -195,7 +195,7 @@ #define sam_apbc_isenabled(s) (getreg32(SAM_PM_APBCMASK) & (s)) != 0) #define sam_pac2_isenabled() sam_apbc_isenabled(PM_APBCMASK_PAC2) -#define sam_devsys_isenabled() sam_apbc_isenabled(PM_APBCMASK_EVSYS) +#define sam_evsys_isenabled() sam_apbc_isenabled(PM_APBCMASK_EVSYS) #define sam_sercom_isenabled(n) sam_apbc_isenabled(PM_APBCMASK_SERCOM(n)) #define sam_sercom0_isenabled() sam_apbc_isenabled(PM_APBCMASK_SERCOM0) #define sam_sercom1_isenabled() sam_apbc_isenabled(PM_APBCMASK_SERCOM1) From 633e90225e07843bf589fcebbf4aa7b162cf8a42 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 25 Jan 2018 10:04:00 -0600 Subject: [PATCH 39/40] configs/flipnclick-sam3x (also Arduio-Due): Remove disabling of environmont, mountpoints, and poll. Add NSH arch initialization so that procfs will be automounted. Increase task name size from 0 to 32. Update README. --- configs/arduino-due/nsh/defconfig | 6 ++---- configs/flipnclick-sam3x/README.txt | 7 ++++--- configs/flipnclick-sam3x/nsh/defconfig | 6 ++---- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/configs/arduino-due/nsh/defconfig b/configs/arduino-due/nsh/defconfig index 15814e72310..a791c14a5b1 100644 --- a/configs/arduino-due/nsh/defconfig +++ b/configs/arduino-due/nsh/defconfig @@ -11,9 +11,6 @@ CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT=y CONFIG_BOARD_LOOPSPERMSEC=6965 CONFIG_BUILTIN=y CONFIG_CXX_NEWLONG=y -CONFIG_DISABLE_ENVIRON=y -CONFIG_DISABLE_MOUNTPOINT=y -CONFIG_DISABLE_POLL=y CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y CONFIG_EXAMPLES_NSH=y CONFIG_FS_PROCFS=y @@ -24,6 +21,7 @@ CONFIG_MAX_WDOGPARMS=2 CONFIG_MM_REGIONS=3 CONFIG_NFILE_DESCRIPTORS=8 CONFIG_NFILE_STREAMS=8 +CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y CONFIG_NSH_DISABLE_IFUPDOWN=y CONFIG_NSH_FILEIOSIZE=512 @@ -40,7 +38,7 @@ CONFIG_SDCLONE_DISABLE=y CONFIG_START_DAY=28 CONFIG_START_MONTH=6 CONFIG_START_YEAR=2013 -CONFIG_TASK_NAME_SIZE=0 +CONFIG_TASK_NAME_SIZE=32 CONFIG_UART0_SERIAL_CONSOLE=y CONFIG_USER_ENTRYPOINT="nsh_main" CONFIG_WDOG_INTRESERVE=0 diff --git a/configs/flipnclick-sam3x/README.txt b/configs/flipnclick-sam3x/README.txt index 8ab7a159a8f..38e9ae2dbbd 100644 --- a/configs/flipnclick-sam3x/README.txt +++ b/configs/flipnclick-sam3x/README.txt @@ -349,9 +349,10 @@ Loading Code You should be able to use a 10- to 20-pin adapter to connect a SAM-ICE or J-Link debugger to the Flip&Click SAM3X. I have this Olimex adapter: - https://www.olimex.com/Products/ARM/JTAG/ARM-JTAG-20-10/ . But so far I - have been unable to get the get the SAM-ICE to communicate with the - Flip&Click. + https://www.olimex.com/Products/ARM/JTAG/ARM-JTAG-20-10/ . I have been + loading code and debugging with no problems using JTAG. + + You can find photos my setup here: http://www.nuttx.org/doku.php?id=wiki:howtos:flipnclick-sam3x Flip&Click SAM3X-specific Configuration Options =============================================== diff --git a/configs/flipnclick-sam3x/nsh/defconfig b/configs/flipnclick-sam3x/nsh/defconfig index f0ba4aedf39..68e1421dc1c 100644 --- a/configs/flipnclick-sam3x/nsh/defconfig +++ b/configs/flipnclick-sam3x/nsh/defconfig @@ -9,9 +9,6 @@ CONFIG_ARCH_STACKDUMP=y CONFIG_ARCH="arm" CONFIG_BOARD_LOOPSPERMSEC=6965 CONFIG_BUILTIN=y -CONFIG_DISABLE_ENVIRON=y -CONFIG_DISABLE_MOUNTPOINT=y -CONFIG_DISABLE_POLL=y CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y CONFIG_EXAMPLES_NSH=y CONFIG_FS_PROCFS=y @@ -23,6 +20,7 @@ CONFIG_MAX_WDOGPARMS=2 CONFIG_MM_REGIONS=3 CONFIG_NFILE_DESCRIPTORS=8 CONFIG_NFILE_STREAMS=8 +CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y CONFIG_NSH_DISABLE_IFUPDOWN=y CONFIG_NSH_FILEIOSIZE=512 @@ -40,7 +38,7 @@ CONFIG_SDCLONE_DISABLE=y CONFIG_START_DAY=28 CONFIG_START_MONTH=6 CONFIG_START_YEAR=2013 -CONFIG_TASK_NAME_SIZE=0 +CONFIG_TASK_NAME_SIZE=32 CONFIG_USART0_SERIAL_CONSOLE=y CONFIG_USER_ENTRYPOINT="nsh_main" CONFIG_WDOG_INTRESERVE=0 From 483dfe80d913685ca8f8838967c29e08cef3c111 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 25 Jan 2018 12:45:02 -0600 Subject: [PATCH 40/40] configs/flipnclick-pic32mz and flipnclick-sam3x: Update README and add pin definitions to support SPI on all mikroBUS connectors. --- configs/flipnclick-pic32mz/README.txt | 34 +++++++++++++ configs/flipnclick-pic32mz/include/board.h | 46 +++++++++++++++++ .../src/flipnclick-pic32mz.h | 41 ++++++++++++++++ configs/flipnclick-sam3x/README.txt | 34 +++++++++++++ configs/flipnclick-sam3x/include/board.h | 42 +++++++++++++++- .../flipnclick-sam3x/src/flipnclick-sam3x.h | 49 +++++++++++++++++++ 6 files changed, 245 insertions(+), 1 deletion(-) diff --git a/configs/flipnclick-pic32mz/README.txt b/configs/flipnclick-pic32mz/README.txt index 3a1c3575d6d..6e11eaffdd2 100644 --- a/configs/flipnclick-pic32mz/README.txt +++ b/configs/flipnclick-pic32mz/README.txt @@ -14,6 +14,7 @@ Contents Creating Compatible NuttX HEX files Tool Issues Serial Console + SPI LEDs Configurations @@ -146,6 +147,39 @@ Serial Console transceiver to get the signals to RS232 levels (or connect to the USB virtual COM port in the case of UART0). +SPI +=== + + SPI3 is available on pins D10-D13 of the Arduino Shield connectors where + you would expect then. The SPI connector is configured as follows: + + Pin J1 Board Signal PIC32MZ + --- -- ------------ ------- + D10 8 SPI3_SCK RB14 + D10 7 SPI3_MISO RB9 + D11 6 SPI3_MOSI RB10 + D13 5 SPI3_SS RB9 + + SPI1 and SPI2 are also available on the mikroBUS Click connectors (in + addition to 5V and GND). The connectivity between connectors A and B and + between C and D differs only in the chip select pin: + + MikroBUS A: MikroBUS B: + Pin Board Signal PIC32MZ Pin Board Signal PIC32MZ + ---- ------------ ------- ---- ------------ ------- + CS SPI2_SS1 RA0 CS SPI2_SS0 RE4 + SCK SPI2_SCK RG6 SCK SPI2_SCK RG6 + MISO SPI2_MISO RC4 MISO SPI2_MISO RC4 + MOSI SPI2_MOSI RB5 MOSI SPI2_MOSI RB5 + + MikroBUS C: MikroBUS D: + Pin Board Signal PIC32MZ Pin Board Signal PIC32MZ + ---- ------------ ------- ---- ------------ ------- + CS SPI1_SS0 RD12 CS SPI1_SS1 RD13 + SCK SPI1_SCK RD1 SCK SPI1_SCK RD1 + MISO SPI1_MISO RD2 MISO SPI1_MISO RD2 + MOSI SPI1_MOSI RD3 MOSI SPI1_MOSI RD3 + LEDs and Buttons ================ diff --git a/configs/flipnclick-pic32mz/include/board.h b/configs/flipnclick-pic32mz/include/board.h index 490a8cde3fb..0bcdc3dab16 100644 --- a/configs/flipnclick-pic32mz/include/board.h +++ b/configs/flipnclick-pic32mz/include/board.h @@ -303,6 +303,52 @@ #define BOARD_U5RX_PPS U5RXR_RPD14 #define BOARD_U5TX_PPS U5TX_RPD15R +/* SPI **********************************************************************/ +/* SPI3 is available on pins D10-D13 of the Arduino Shield connectors where + * you would expect then. The SPI connector is configured as follows: + * + * Pin J1 Board Signal PIC32MZ + * --- -- ------------ ------- + * D10 8 SPI3_SCK RB14 + * D10 7 SPI3_MISO RB9 + * D11 6 SPI3_MOSI RB10 + * D13 5 SPI3_SS RB9 + * + * SPI1 and SPI2 are also available on the mikroBUS Click connectors (in + * addition to 5V and GND). The connectivity between connectors A and B and + * between C and D differs only in the chip select pin: + * + * MikroBUS A: MikroBUS B: + * Pin Board Signal PIC32MZ Pin Board Signal PIC32MZ + * ---- ------------ ------- ---- ------------ ------- + * CS SPI2_SS1 RA0 CS SPI2_SS0 RE4 + * SCK SPI2_SCK RG6 SCK SPI2_SCK RG6 + * MISO SPI2_MISO RC4 MISO SPI2_MISO RC4 + * MOSI SPI2_MOSI RB5 MOSI SPI2_MOSI RB5 + * + * MikroBUS C: MikroBUS D: + * Pin Board Signal PIC32MZ Pin Board Signal PIC32MZ + * ---- ------------ ------- ---- ------------ ------- + * CS SPI1_SS0 RD12 CS SPI1_SS1 RD13 + * SCK SPI1_SCK RD1 SCK SPI1_SCK RD1 + * MISO SPI1_MISO RD2 MISO SPI1_MISO RD2 + * MOSI SPI1_MOSI RD3 MOSI SPI1_MOSI RD3 + * + * Chip select pin definitions are provided in + * configs/flipnclick-pic32mz/src/flipnclick-pic32mz.h. + * + * CLK (output) pins have no alternative pin configurations. + */ + +#define BOARD_SDI1_PPS SDI1R_RPD2 +#define BOARD_SDO1_PPS SDO1_RPD3R + +#define BOARD_SDI2_PPS SDI2R_RPC4 +#define BOARD_SDO2_PPS SDO2_RPB5R + +#define BOARD_SDI3_PPS SDI3R_RPB9 +#define BOARD_SDO3_PPS SDO3_RPB9R + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/configs/flipnclick-pic32mz/src/flipnclick-pic32mz.h b/configs/flipnclick-pic32mz/src/flipnclick-pic32mz.h index a1cbc0a8ebc..ec514893eb4 100644 --- a/configs/flipnclick-pic32mz/src/flipnclick-pic32mz.h +++ b/configs/flipnclick-pic32mz/src/flipnclick-pic32mz.h @@ -85,6 +85,47 @@ #define GPIO_T1 (GPIO_INPUT | GPIO_INTERRUPT | GPIO_PORTD | GPIO_PIN10) #define GPIO_T2 (GPIO_INPUT | GPIO_INTERRUPT | GPIO_PORTD | GPIO_PIN11) +/* SPI Chip Selects + * + * SPI3 is available on pins D10-D13 of the Arduino Shield connectors where + * you would expect then. The SPI connector is configured as follows: + * + * Pin J1 Board Signal PIC32MZ + * --- -- ------------ ------- + * D10 8 SPI3_SCK RB14 + * D10 7 SPI3_MISO RB9 + * D11 6 SPI3_MOSI RB10 + * D13 5 SPI3_SS RB9 + */ + +#define GPIO_ARD_CS (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORTB | GPIO_PIN14) + +/* SPI1 and SPI2 are also available on the mikroBUS Click connectors (in + * addition to 5V and GND). The connectivity between connectors A and B and + * between C and D differs only in the chip select pin: + * + * MikroBUS A: MikroBUS B: + * Pin Board Signal PIC32MZ Pin Board Signal PIC32MZ + * ---- ------------ ------- ---- ------------ ------- + * CS SPI2_SS1 RA0 CS SPI2_SS0 RE4 + * SCK SPI2_SCK RG6 SCK SPI2_SCK RG6 + * MISO SPI2_MISO RC4 MISO SPI2_MISO RC4 + * MOSI SPI2_MOSI RB5 MOSI SPI2_MOSI RB5 + * + * MikroBUS C: MikroBUS D: + * Pin Board Signal PIC32MZ Pin Board Signal PIC32MZ + * ---- ------------ ------- ---- ------------ ------- + * CS SPI1_SS0 RD12 CS SPI1_SS1 RD13 + * SCK SPI1_SCK RD1 SCK SPI1_SCK RD1 + * MISO SPI1_MISO RD2 MISO SPI1_MISO RD2 + * MOSI SPI1_MOSI RD3 MOSI SPI1_MOSI RD3 + */ + +#define GPIO_MBA_CS (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORTA | GPIO_PIN0) +#define GPIO_MBB_CS (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORTE | GPIO_PIN4) +#define GPIO_MBC_CS (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORTD | GPIO_PIN12) +#define GPIO_MBD_CS (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORTD | GPIO_PIN13) + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/configs/flipnclick-sam3x/README.txt b/configs/flipnclick-sam3x/README.txt index 38e9ae2dbbd..6f286895058 100644 --- a/configs/flipnclick-sam3x/README.txt +++ b/configs/flipnclick-sam3x/README.txt @@ -14,6 +14,7 @@ Contents - STATUS - Buttons and LEDs - Serial Consoles + - SPI - Loading Code - Flip&Click SAM3X-specific Configuration Options - Configurations @@ -120,6 +121,39 @@ Serial Consoles in all configurations. But that is easily changed by modifying the configuration as described under "Configurations" below. +SPI +=== + + SPI0 is available on the Arduino compatible SPI connector (but no SPI is + available on pins D10-D13 of the main Arduino Shield connectors where + you might expect then). The SPI connector is configured as follows: + + Pin Board Signal SAM3X Pin Board Signal SAM3X + --- ------------ ----- --- ------------ ----- + 1 SPI0_MISO PA25 2 VCC-5V N/A + 3 SPI0_SCK PA27 4 SPI0_MOSI PA26 + 5 MRST NRSTB 6 GND N/A + + SPI0 is also available on each of the mikroBUS Click connectors (in + addition to 5V and GND). The connectivity differs only in the chip + select pin: + + MikroBUS A: MikroBUS B: + Pin Board Signal SAM3X Pin Board Signal SAM3X + ---- ------------ ----- ---- ------------ ----- + CS SPI0_CS0 PA28 CS PA29 PA29 + SCK SPI0_SCK PA27 SCK SPI0_SCK PA27 + MISO SPI0_MISO PA25 MISO SPI0_MISO PA25 + MOSI SPI0_MOSI PA26 MOSI SPI0_MOSI PA26 + + MikroBUS C: MikroBUS D: + Pin Board Signal SAM3X Pin Board Signal SAM3X + ---- ------------ ----- ---- ------------ ----- + CS SPI0_CS2 PB21 CS SPI0_CS3 PB23 + SCK SPI0_SCK PA27 SCK SPI0_SCK PA27 + MISO SPI0_MISO PA25 MISO SPI0_MISO PA25 + MOSI SPI0_MOSI PA26 MOSI SPI0_MOSI PA26 + Loading Code ============ diff --git a/configs/flipnclick-sam3x/include/board.h b/configs/flipnclick-sam3x/include/board.h index 0e2b42fe5d0..dd72568d783 100644 --- a/configs/flipnclick-sam3x/include/board.h +++ b/configs/flipnclick-sam3x/include/board.h @@ -79,7 +79,7 @@ /* PLLA configuration. * * Divider = 1 - * Multipler = 14 + * Multiplier = 14 */ #define BOARD_CKGR_PLLAR_MUL (13 << PMC_CKGR_PLLAR_MUL_SHIFT) @@ -255,4 +255,44 @@ * There are no alternatives for these pins. */ +/* SPI: + * + * SPI0 is available on the Arduino compatible SPI connector (but no SPI is + * available on pins D10-D13 of the main Arduino Shield connectors where + * you might expect then). The SPI connector is configured as follows: + * + * Pin Board Signal SAM3X Pin Board Signal SAM3X + * --- ------------ ----- --- ------------ ----- + * 1 SPI0_MISO PA25 2 VCC-5V N/A + * 3 SPI0_SCK PA27 4 SPI0_MOSI PA26 + * 5 MRST NRSTB 6 GND N/A + * + * SPI0 is also available on each of the mikroBUS Click connectors (in + * addition to 5V and GND). The connectivity differs only in the chip + * select pin: + * + * MikroBUS A: MikroBUS B: + * Pin Board Signal SAM3X Pin Board Signal SAM3X + * ---- ------------ ----- ---- ------------ ----- + * CS SPI0_CS0 PA28 CS PA29 PA29 + * SCK SPI0_SCK PA27 SCK SPI0_SCK PA27 + * MISO SPI0_MISO PA25 MISO SPI0_MISO PA25 + * MOSI SPI0_MOSI PA26 MOSI SPI0_MOSI PA26 + * + * MikroBUS C: MikroBUS D: + * Pin Board Signal SAM3X Pin Board Signal SAM3X + * ---- ------------ ----- ---- ------------ ----- + * CS SPI0_CS2 PB21 CS SPI0_CS3 PB23 + * SCK SPI0_SCK PA27 SCK SPI0_SCK PA27 + * MISO SPI0_MISO PA25 MISO SPI0_MISO PA25 + * MOSI SPI0_MOSI PA26 MOSI SPI0_MOSI PA26 + * + * Chip select pin definitions are provided in + * configs/flipnclick-sam3x/src/flipnclick-3x.h. + * + * There are no alternative pin selections for SPI0_MSIO and SPIO_MOSI. + */ + +#define GPIO_SPI0_SPCK GPIO_SPI0_SPCK_1 + #endif /* __CONFIGS_FLIPNCLICK_SAM3X_INCLUDE_BOARD_H */ diff --git a/configs/flipnclick-sam3x/src/flipnclick-sam3x.h b/configs/flipnclick-sam3x/src/flipnclick-sam3x.h index e35dacbe6d1..8887523ff73 100644 --- a/configs/flipnclick-sam3x/src/flipnclick-sam3x.h +++ b/configs/flipnclick-sam3x/src/flipnclick-sam3x.h @@ -79,6 +79,55 @@ #define GPIO_LED_D (GPIO_OUTPUT | GPIO_CFG_PULLUP | GPIO_OUTPUT_CLEAR | \ GPIO_PORT_PIOC | GPIO_PIN8) +/* SPI chip select pins. + * + * SPI0 is available on the Arduino compatible SPI connector (but no SPI is + * available on pins D10-D13 of the main Arduino Shield connectors where + * you might expect then). The SPI connector is configured as follows: + * + * Pin Board Signal SAM3X Pin Board Signal SAM3X + * --- ------------ ----- --- ------------ ----- + * 1 SPI0_MISO PA25 2 VCC-5V N/A + * 3 SPI0_SCK PA27 4 SPI0_MOSI PA26 + * 5 MRST NRSTB 6 GND N/A + * + * SPI0 is also available on each of the mikroBUS Click connectors (in + * addition to 5V and GND). The connectivity differs only in the chip + * select pin: + * + * MikroBUS A: MikroBUS B: + * Pin Board Signal SAM3X Pin Board Signal SAM3X + * ---- ------------ ----- ---- ------------ ----- + * CS SPI0_CS0 PA28 CS PA29 PA29 + * SCK SPI0_SCK PA27 SCK SPI0_SCK PA27 + * MISO SPI0_MISO PA25 MISO SPI0_MISO PA25 + * MOSI SPI0_MOSI PA26 MOSI SPI0_MOSI PA26 + * + * MikroBUS C: MikroBUS D: + * Pin Board Signal SAM3X Pin Board Signal SAM3X + * ---- ------------ ----- ---- ------------ ----- + * CS SPI0_CS2 PB21 CS SPI0_CS3 PB23 + * SCK SPI0_SCK PA27 SCK SPI0_SCK PA27 + * MISO SPI0_MISO PA25 MISO SPI0_MISO PA25 + * MOSI SPI0_MOSI PA26 MOSI SPI0_MOSI PA26 + */ + +#define GPIO_MBA_CS (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_SET | \ + GPIO_PORT_PIOA | GPIO_PIN28) +#define MBA_CSNUM 0 + +#define GPIO_MBB_CS (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_SET | \ + GPIO_PORT_PIOA | GPIO_PIN29) +#define MBB_CSNUM 1 + +#define GPIO_MBC_CS (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_SET | \ + GPIO_PORT_PIOB | GPIO_PIN21) +#define MBC_CSNUM 2 + +#define GPIO_MBD_CS (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_SET | \ + GPIO_PORT_PIOB | GPIO_PIN23) +#define MBD_CSNUM 3 + /************************************************************************************ * Public Types ************************************************************************************/