diff --git a/Makefile.unix b/Makefile.unix index b7bf86b8056..811b0551e36 100644 --- a/Makefile.unix +++ b/Makefile.unix @@ -280,7 +280,11 @@ tools/cnvwindeps$(HOSTEXEEXT): # Directories links. Most of establishing the NuttX configuration involves # setting up symbolic links with 'generic' directory names to specific, # configured directories. -# + +Make.defs: + echo "include $(TOPDIR)$(DELIM).config" > Make.defs + echo "include $(TOPDIR)$(DELIM)tools$(DELIM)Config.mk" >> Make.defs + # Link the arch//include directory to include/arch include/arch: Make.defs diff --git a/Makefile.win b/Makefile.win index e1d9bc1278c..32d42772c62 100644 --- a/Makefile.win +++ b/Makefile.win @@ -275,7 +275,11 @@ tools\mkdeps$(HOSTEXEEXT): # Directories links. Most of establishing the NuttX configuration involves # setting up symbolic links with 'generic' directory names to specific, # configured directories. -# + +Make.defs: + echo "include $(TOPDIR)$(DELIM).config" > Make.defs + echo "include $(TOPDIR)$(DELIM)tools$(DELIM)Config.mk" >> Make.defs + # Link the arch\\include directory to include\arch include\arch: Make.defs diff --git a/README.txt b/README.txt index 9a4775c77b7..c5e0b9c69e6 100644 --- a/README.txt +++ b/README.txt @@ -186,6 +186,13 @@ Ubuntu Bash under Windows 10 With these differences (perhaps a few other Windows quirks) the Ubuntu install works just like Ubuntu running natively on your PC. + A good tip for file sharing is to use symbolic links within your Ubuntu + home directory. For example, suppose you have your "projects" directory + at C:\Documents\projects. Then you can set up a link to the projects/ + directory in your Ubuntu directory like: + + $ ln -s /mnt/c/Documents/projects projects + Accessing Ubuntu Files From Windows ----------------------------------- In Ubuntu Userspace for Windows, the Ubuntu file system root directory is @@ -205,6 +212,8 @@ Ubuntu Bash under Windows 10 able to use Windows tools outside of the Ubuntu sandbox with versions of NuttX built within the sandbox using that path. + Executing Windows Tools from Ubuntu + ----------------------------------- You can also execute Windows tools from within the Ubuntu sandbox: $ /mnt/c/Program\ Files\ \(x86\)/Microchip/xc32/v1.43/bin/xc32-gcc.exe --version @@ -217,7 +226,7 @@ Ubuntu Bash under Windows 10 POSIX paths. I think you would have to use Linux tools only from within the Ubuntu sandbox. - Install Linux Software. + Install Ubuntu Software ----------------------- Use "sudo apt-get install ". As examples, this is how you would get GIT: diff --git a/TODO b/TODO index 2cf4fdcaaae..64c98a8c860 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -NuttX TODO List (Last updated May 18, 2017) +NuttX TODO List (Last updated May 31, 2017) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with @@ -45,6 +45,13 @@ o Task/Scheduler (sched/) terminated? 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 + 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 + mutexes, what should happen if the main thread exits while + holding a mutex?) Title: pause() NON-COMPLIANCE Description: In the POSIX description of this function the pause() function diff --git a/arch/arm/src/stm32f7/stm32_spi.c b/arch/arm/src/stm32f7/stm32_spi.c index c00e717a09a..d6b4cb9e9c3 100644 --- a/arch/arm/src/stm32f7/stm32_spi.c +++ b/arch/arm/src/stm32f7/stm32_spi.c @@ -80,6 +80,7 @@ #include "up_internal.h" #include "up_arch.h" +#include "cache.h" #include "chip.h" #include "stm32_gpio.h" #include "stm32_dma.h" @@ -110,12 +111,10 @@ #ifdef CONFIG_STM32F7_SPI_DMA -# error "SPI DMA not yet supported" - # if defined(CONFIG_SPI_DMAPRIO) # define SPI_DMA_PRIO CONFIG_SPI_DMAPRIO # elif defined(DMA_SCR_PRIMED) -# define SPI_DMA_PRIO DMA_SCR_PRIMED +# define SPI_DMA_PRIO DMA_SCR_PRILO # else # error "Unknown STM32 DMA" # endif @@ -264,8 +263,8 @@ static struct stm32_spidev_s g_spi1dev = .spiirq = STM32_IRQ_SPI1, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI1_RX, - .txch = DMACHAN_SPI1_TX, + .rxch = DMAMAP_SPI1_RX, + .txch = DMAMAP_SPI1_TX, #endif }; #endif @@ -308,8 +307,8 @@ static struct stm32_spidev_s g_spi2dev = .spiirq = STM32_IRQ_SPI2, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI2_RX, - .txch = DMACHAN_SPI2_TX, + .rxch = DMAMAP_SPI2_RX, + .txch = DMAMAP_SPI2_TX, #endif }; #endif @@ -352,8 +351,8 @@ static struct stm32_spidev_s g_spi3dev = .spiirq = STM32_IRQ_SPI3, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI3_RX, - .txch = DMACHAN_SPI3_TX, + .rxch = DMAMAP_SPI3_RX, + .txch = DMAMAP_SPI3_TX, #endif }; #endif @@ -396,8 +395,8 @@ static struct stm32_spidev_s g_spi4dev = .spiirq = STM32_IRQ_SPI4, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI4_RX, - .txch = DMACHAN_SPI4_TX, + .rxch = DMAMAP_SPI4_RX, + .txch = DMAMAP_SPI4_TX, #endif }; #endif @@ -440,8 +439,8 @@ static struct stm32_spidev_s g_spi5dev = .spiirq = STM32_IRQ_SPI5, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI5_RX, - .txch = DMACHAN_SPI5_TX, + .rxch = DMAMAP_SPI5_RX, + .txch = DMAMAP_SPI5_TX, #endif }; #endif @@ -484,8 +483,8 @@ static struct stm32_spidev_s g_spi6dev = .spiirq = STM32_IRQ_SPI6, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI6_RX, - .txch = DMACHAN_SPI6_TX, + .rxch = DMAMAP_SPI6_RX, + .txch = DMAMAP_SPI6_TX, #endif }; #endif @@ -927,7 +926,7 @@ static void spi_dmatxsetup(FAR struct stm32_spidev_s *priv, FAR const void *txbu ************************************************************************************/ #ifdef CONFIG_STM32F7_SPI_DMA -static inline void spi_dmarxstart(FAR struct stm32_spidev_s *priv) +static void spi_dmarxstart(FAR struct stm32_spidev_s *priv) { priv->rxresult = 0; stm32_dmastart(priv->rxdma, spi_dmarxcallback, priv, false); @@ -943,7 +942,7 @@ static inline void spi_dmarxstart(FAR struct stm32_spidev_s *priv) ************************************************************************************/ #ifdef CONFIG_STM32F7_SPI_DMA -static inline void spi_dmatxstart(FAR struct stm32_spidev_s *priv) +static void spi_dmatxstart(FAR struct stm32_spidev_s *priv) { priv->txresult = 0; stm32_dmastart(priv->txdma, spi_dmatxcallback, priv, false); @@ -1528,6 +1527,8 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, { FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + DEBUGASSERT(priv != NULL); + #ifdef CONFIG_STM32F7_DMACAPABLE if ((txbuffer && !stm32_dmacapable((uint32_t)txbuffer, nwords, priv->txccr)) || (rxbuffer && !stm32_dmacapable((uint32_t)rxbuffer, nwords, priv->rxccr))) @@ -1539,17 +1540,31 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, else #endif { - static uint16_t rxdummy = 0xffff; + static uint8_t rxdummy[ARMV7M_DCACHE_LINESIZE] + __attribute__((aligned(ARMV7M_DCACHE_LINESIZE))); static const uint16_t txdummy = 0xffff; + size_t buflen = nwords; + + if (spi_9to16bitmode(priv)) + { + buflen = nwords * sizeof(uint16_t); + } spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords); - DEBUGASSERT(priv && priv->spibase); + DEBUGASSERT(priv->spibase != 0); /* Setup DMAs */ - spi_dmarxsetup(priv, rxbuffer, &rxdummy, nwords); + spi_dmarxsetup(priv, rxbuffer, (uint16_t *)rxdummy, nwords); spi_dmatxsetup(priv, txbuffer, &txdummy, nwords); + /* Flush cache to physical memory */ + + if (txbuffer) + { + arch_flush_dcache((uintptr_t)txbuffer, (uintptr_t)txbuffer + buflen); + } + /* Start the DMAs */ spi_dmarxstart(priv); @@ -1559,6 +1574,19 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, spi_dmarxwait(priv); spi_dmatxwait(priv); + + /* Force RAM re-read */ + + if (rxbuffer) + { + arch_invalidate_dcache((uintptr_t)rxbuffer, + (uintptr_t)rxbuffer + buflen); + } + else + { + arch_invalidate_dcache((uintptr_t)rxdummy, + (uintptr_t)rxdummy + sizeof(rxdummy)); + } } } #endif /* CONFIG_STM32F7_SPI_DMA */ @@ -1694,7 +1722,7 @@ static void spi_bus_initialize(FAR struct stm32_spidev_s *priv) priv->txdma = stm32_dmachannel(priv->txch); DEBUGASSERT(priv->rxdma && priv->txdma); - spi_putreg(priv, STM32_SPI_CR2_OFFSET, SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN); + spi_modifycr2(priv, SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN, 0); #endif /* Enable spi */ diff --git a/arch/arm/src/stm32l4/stm32l4_gpio.c b/arch/arm/src/stm32l4/stm32l4_gpio.c index 049c40fd2cf..f46f341662c 100644 --- a/arch/arm/src/stm32l4/stm32l4_gpio.c +++ b/arch/arm/src/stm32l4/stm32l4_gpio.c @@ -309,17 +309,15 @@ int stm32l4_configgpio(uint32_t cfgset) /* Otherwise, it is an input pin. Should it configured as an EXTI interrupt? */ - if ((cfgset & GPIO_EXTI) != 0) + if (pinmode != GPIO_MODER_OUTPUT && (cfgset & GPIO_EXTI) != 0) { -#if 0 - /* "In STM32 F1 the selection of the EXTI line source is performed through - * the EXTIx bits in the AFIO_EXTICRx registers, while in F2 series this - * selection is done through the EXTIx bits in the SYSCFG_EXTICRx registers. + /* The selection of the EXTI line source is performed through the EXTIx + * bits in the SYSCFG_EXTICRx registers. * - * "Only the mapping of the EXTICRx registers has been changed, without any - * changes to the meaning of the EXTIx bits. However, the range of EXTI - * bits values has been extended to 0b1000 to support the two ports added - * in F2, port H and I (in F1 series the maximum value is 0b0110)." + * The range of EXTI bit values in STM32L4x6 goes to 0b1000 to support the + * ports up to PI in STM32L496xx devices. For STM32L4x3 the EXTI bit values + * end at 0b111 (for PH0, PH1 and PH3 only) and values for non-existent + * ports F and G are reserved. */ uint32_t regaddr; @@ -334,7 +332,6 @@ int stm32l4_configgpio(uint32_t cfgset) regval |= (((uint32_t)port) << shift); putreg32(regval, regaddr); -#endif } leave_critical_section(flags); diff --git a/arch/arm/src/stm32l4/stm32l4_rcc.c b/arch/arm/src/stm32l4/stm32l4_rcc.c index ffe1c4d2dc7..c2f3cfa198d 100644 --- a/arch/arm/src/stm32l4/stm32l4_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4_rcc.c @@ -114,7 +114,7 @@ static inline void rcc_resetbkp(void) /* Check if the RTC is already configured */ - init_stat = rtc_is_inits(); + init_stat = stm32l4_rtc_is_initialized(); if(!init_stat) { /* Enable write access to the backup domain (RTC registers, RTC diff --git a/arch/arm/src/stm32l4/stm32l4_rtc.h b/arch/arm/src/stm32l4/stm32l4_rtc.h index 18e7f6031be..3e0a5a21307 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtc.h +++ b/arch/arm/src/stm32l4/stm32l4_rtc.h @@ -76,7 +76,7 @@ enum alm_id_e RTC_ALARM_LAST }; -/* Structure used to pass parmaters to set an alarm */ +/* Structure used to pass parameters to set an alarm */ struct alm_setalarm_s { @@ -106,7 +106,7 @@ extern "C" ****************************************************************************/ /************************************************************************************ - * Name: rtc_is_inits + * Name: stm32l4_rtc_is_initialized * * Description: * Returns 'true' if the RTC has been initialized (according to the RTC itself). @@ -120,10 +120,10 @@ extern "C" * bool -- true if the INITS flag is set in the ISR. * ************************************************************************************/ -#ifdef CONFIG_RTC_DRIVER -bool rtc_is_inits(void); -#endif +#ifdef CONFIG_RTC_DRIVER +bool stm32l4_rtc_is_initialized(void); +#endif /**************************************************************************** * Name: stm32l4_rtc_getdatetime_with_subseconds diff --git a/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c b/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c index 5ab212dd86f..f3415af305d 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c +++ b/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c @@ -176,7 +176,7 @@ static void stm32l4_alarm_callback(FAR void *arg, unsigned int alarmid) rtc_alarm_callback_t cb; FAR void *priv; - DEBUGASSERT(priv != NULL); + DEBUGASSERT(arg != NULL); DEBUGASSERT(alarmid == RTC_ALARMA || alarmid == RTC_ALARMB); lower = (struct stm32l4_lowerhalf_s *)arg; diff --git a/arch/arm/src/stm32l4/stm32l4_rtcc.c b/arch/arm/src/stm32l4/stm32l4_rtcc.c index f36d4d040c4..d053ee99293 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtcc.c +++ b/arch/arm/src/stm32l4/stm32l4_rtcc.c @@ -95,6 +95,10 @@ # define CONFIG_RTC_MAGIC_REG (0) #endif +#define RTC_MAGIC CONFIG_RTC_MAGIC +#define RTC_MAGIC_TIME_SET CONFIG_RTC_MAGIC_TIME_SET +#define RTC_MAGIC_REG STM32L4_RTC_BKR(CONFIG_RTC_MAGIC_REG) + /* Constants ************************************************************************/ #define SYNCHRO_TIMEOUT (0x00020000) @@ -816,7 +820,7 @@ static inline void rtc_enable_alarm(void) ************************************************************************************/ /************************************************************************************ - * Name: rtc_is_inits + * Name: stm32l4_rtc_is_initialized * * Description: * Returns 'true' if the RTC has been initialized (according to the RTC itself). @@ -831,7 +835,7 @@ static inline void rtc_enable_alarm(void) * ************************************************************************************/ -bool rtc_is_inits(void) +bool stm32l4_rtc_is_initialized(void) { uint32_t regval; @@ -867,8 +871,7 @@ int up_rtc_initialize(void) * backed, we don't need or want to re-initialize on each reset. */ - init_stat = rtc_is_inits(); - + init_stat = stm32l4_rtc_is_initialized(); if (!init_stat) { /* Enable write access to the backup domain (RTC registers, RTC @@ -1164,7 +1167,7 @@ int stm32l4_rtc_setdatetime(FAR const struct tm *tp) /* Then write the broken out values to the RTC */ - /* Convert the struct tm format to RTC time register fields. All of the STM32 + /* Convert the struct tm format to RTC time register fields. * All of the ranges of values correspond between struct tm and the time * register. */ @@ -1216,10 +1219,10 @@ int stm32l4_rtc_setdatetime(FAR const struct tm *tp) /* Remember that the RTC is initialized and had its time set. */ - if (getreg32(CONFIG_RTC_MAGIC_REG) != CONFIG_RTC_MAGIC_TIME_SET) + if (getreg32(RTC_MAGIC_REG) != RTC_MAGIC_TIME_SET) { stm32l4_pwr_enablebkp(true); - putreg32(CONFIG_RTC_MAGIC_TIME_SET, CONFIG_RTC_MAGIC_REG); + putreg32(RTC_MAGIC_TIME_SET, RTC_MAGIC_REG); stm32l4_pwr_enablebkp(false); } @@ -1243,7 +1246,7 @@ int stm32l4_rtc_setdatetime(FAR const struct tm *tp) bool stm32l4_rtc_havesettime(void) { - return getreg32(CONFIG_RTC_MAGIC_REG) == CONFIG_RTC_MAGIC_TIME_SET; + return getreg32(RTC_MAGIC_REG) == RTC_MAGIC_TIME_SET; } /************************************************************************************ diff --git a/arch/arm/src/tiva/tiva_ssi.c b/arch/arm/src/tiva/tiva_ssi.c index 709850e01a8..9930c6184f5 100644 --- a/arch/arm/src/tiva/tiva_ssi.c +++ b/arch/arm/src/tiva/tiva_ssi.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/tiva/tiva_ssi.c * - * Copyright (C) 2009-2010, 2014, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2009-2010, 2014, 2016-2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -1616,8 +1616,8 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port) * to the SSI3 peripheral, bringing it a fully functional state. */ - tiva_ssi1_enablepwr(); - tiva_ssi1_enableclk(); + tiva_ssi3_enablepwr(); + tiva_ssi3_enableclk(); /* Configure SSI3 GPIOs */ @@ -1626,7 +1626,7 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port) tiva_configgpio(GPIO_SSI3_RX); /* PE2: SSI3 receive (SSI3Rx) */ tiva_configgpio(GPIO_SSI3_TX); /* PE3: SSI3 transmit (SSI3Tx) */ break; -#endif /* CONFIG_TIVA_SSI1 */ +#endif /* CONFIG_TIVA_SSI3 */ default: leave_critical_section(flags); diff --git a/configs/nucleo-f4x1re/src/stm32_userleds.c b/configs/nucleo-f4x1re/src/stm32_userleds.c index dd775007118..dcfaa895100 100644 --- a/configs/nucleo-f4x1re/src/stm32_userleds.c +++ b/configs/nucleo-f4x1re/src/stm32_userleds.c @@ -183,7 +183,7 @@ void board_userled(int led, bool ledon) { if (led == 1) { - stm32_gpiowrite(GPIO_LD2, ldeon); + stm32_gpiowrite(GPIO_LD2, ledon); } } @@ -193,10 +193,7 @@ void board_userled(int led, bool ledon) void board_userled_all(uint8_t ledset) { - if (led == 1) - { - stm32_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0); - } + stm32_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0); } /**************************************************************************** diff --git a/configs/sim/ostest/defconfig b/configs/sim/ostest/defconfig index d13dc5b9911..374b538fc48 100644 --- a/configs/sim/ostest/defconfig +++ b/configs/sim/ostest/defconfig @@ -28,6 +28,7 @@ CONFIG_BUILD_FLAT=y # CONFIG_MOTOROLA_SREC is not set # CONFIG_RAW_BINARY is not set # CONFIG_UBOOT_UIMAGE is not set +# CONFIG_DFU_BINARY is not set # # Customize Header Files @@ -77,11 +78,11 @@ CONFIG_HOST_X86_64=y CONFIG_SIM_X8664_SYSTEMV=y # CONFIG_SIM_X8664_MICROSOFT is not set # CONFIG_SIM_WALLTIME is not set -CONFIG_SIM_NET_HOST_ROUTE=y -# CONFIG_SIM_NET_BRIDGE is not set # CONFIG_SIM_FRAMEBUFFER is not set # CONFIG_SIM_SPIFLASH is not set # CONFIG_SIM_QSPIFLASH is not set +# CONFIG_ARCH_TOOLCHAIN_IAR is not set +# CONFIG_ARCH_TOOLCHAIN_GNU is not set # # Architecture Options @@ -102,6 +103,7 @@ CONFIG_ARCH_HAVE_MULTICPU=y # CONFIG_ARCH_HAVE_EXTCLK is not set CONFIG_ARCH_HAVE_POWEROFF=y # CONFIG_ARCH_HAVE_RESET is not set +# CONFIG_ARCH_HAVE_RTC_SUBSECONDS is not set # CONFIG_ARCH_STACKDUMP is not set # CONFIG_ENDIAN_BIG is not set # CONFIG_ARCH_IDLE_CUSTOM is not set @@ -204,6 +206,8 @@ CONFIG_SCHED_WAITPID=y # CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_PTHREAD_MUTEX_ROBUST=y +# CONFIG_PTHREAD_MUTEX_UNSAFE is not set +# CONFIG_PTHREAD_MUTEX_BOTH is not set CONFIG_NPTHREAD_KEYS=4 # CONFIG_PTHREAD_CLEANUP is not set # CONFIG_CANCELLATION_POINTS is not set @@ -368,6 +372,7 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_PSEUDOTERM is not set # CONFIG_USBDEV is not set # CONFIG_USBHOST is not set +# CONFIG_USBMISC is not set # CONFIG_HAVE_USBTRACE is not set # CONFIG_DRIVERS_WIRELESS is not set # CONFIG_DRIVERS_CONTACTLESS is not set @@ -376,7 +381,9 @@ CONFIG_SERIAL_CONSOLE=y # System Logging # # CONFIG_ARCH_SYSLOG is not set +CONFIG_SYSLOG_WRITE=y # CONFIG_RAMLOG is not set +# CONFIG_SYSLOG_BUFFER is not set # CONFIG_SYSLOG_INTBUFFER is not set # CONFIG_SYSLOG_TIMESTAMP is not set CONFIG_SYSLOG_SERIAL_CONSOLE=y @@ -437,6 +444,11 @@ CONFIG_MM_REGIONS=1 # CONFIG_ARCH_HAVE_HEAP2 is not set # CONFIG_GRAN is not set +# +# Common I/O Buffer Support +# +# CONFIG_MM_IOB is not set + # # Audio Support # @@ -445,6 +457,7 @@ CONFIG_MM_REGIONS=1 # # Wireless Support # +# CONFIG_WIRELESS is not set # # Binary Loader @@ -594,7 +607,6 @@ CONFIG_LIB_SENDFILE_BUFSIZE=512 # CONFIG_EXAMPLES_MM is not set # CONFIG_EXAMPLES_MODBUS is not set # CONFIG_EXAMPLES_MOUNT is not set -# CONFIG_EXAMPLES_NRF24L01TERM is not set # CONFIG_EXAMPLES_NSH is not set # CONFIG_EXAMPLES_NULL is not set # CONFIG_EXAMPLES_NX is not set @@ -630,6 +642,7 @@ CONFIG_EXAMPLES_OSTEST_WAITRESULT=y # CONFIG_EXAMPLES_TOUCHSCREEN is not set # CONFIG_EXAMPLES_WATCHDOG is not set # CONFIG_EXAMPLES_WEBSERVER is not set +# CONFIG_EXAMPLES_XBC_TEST is not set # # File System Utilities @@ -700,3 +713,14 @@ CONFIG_EXAMPLES_OSTEST_WAITRESULT=y # CONFIG_SYSTEM_UBLOXMODEM is not set # CONFIG_SYSTEM_VI is not set # CONFIG_SYSTEM_ZMODEM is not set + +# +# Wireless Libraries and NSH Add-Ons +# + +# +# IEEE 802.15.4 applications +# +# CONFIG_IEEE802154_LIBMAC is not set +# CONFIG_IEEE802154_LIBUTILS is not set +# CONFIG_IEEE802154_I8SAK is not set diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 0fc96d6c918..69d77e62d2f 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -322,6 +322,30 @@ config STMPE811_REGDEBUG endif # INPUT_STMPE811 +config INPUT_CYPRESS_MBR3108 + bool "Enable Cypress MBR3108 CapSense driver" + default n + ---help--- + Enable support for Cypress MBR3108 CapSense touch button & proximity + input sensor. + +if INPUT_CYPRESS_MBR3108 + +config INPUT_CYPRESS_MBR3108_DEBUG + bool "Enable debug support for Cypress sensor" + default n + depends on DEBUG_FEATURES + ---help--- + Enable debugging traces for MBR3108 driver + +config INPUT_CYPRESS_MBR3108_NPOLLWAITERS + int "Number of waiters to poll" + default 1 + ---help--- + Maximum number of threads that can be waiting on poll() + +endif # INPUT_CYPRESS_MBR3108 + config BUTTONS bool "Button Inputs" default n diff --git a/drivers/input/Make.defs b/drivers/input/Make.defs index 8285bfda0f7..af98782596b 100644 --- a/drivers/input/Make.defs +++ b/drivers/input/Make.defs @@ -71,6 +71,10 @@ ifneq ($(CONFIG_INPUT_STMPE811_TEMP_DISABLE),y) endif endif +ifeq ($(CONFIG_INPUT_CYPRESS_MBR3108),y) + CSRCS += cypress_mbr3108.c +endif + ifeq ($(CONFIG_BUTTONS),y) CSRCS += button_upper.c ifeq ($(CONFIG_BUTTONS_LOWER),y) diff --git a/drivers/input/cypress_mbr3108.c b/drivers/input/cypress_mbr3108.c new file mode 100644 index 00000000000..d1b29f672c2 --- /dev/null +++ b/drivers/input/cypress_mbr3108.c @@ -0,0 +1,1157 @@ +/**************************************************************************** + * drivers/input/cypress_mbr3108.c + * + * Copyright (C) 2014 Haltian Ltd. All rights reserved. + * Author: Jussi Kivilinna + * + * 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 +#include +#include +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_INPUT_CYPRESS_MBR3108_DEBUG +# define mbr3108_dbg(x, ...) _info(x, ##__VA_ARGS__) +#else +# define mbr3108_dbg(x, ...) iinfo(x, ##__VA_ARGS__) +#endif + +/* Register macros */ + +#define MBR3108_SENSOR_EN 0x0 +#define MBR3108_FSS_EN 0x02 +#define MBR3108_TOGGLE_EN 0x04 +#define MBR3108_LED_ON_EN 0x06 +#define MBR3108_SENSITIVITY0 0x08 +#define MBR3108_SENSITIVITY1 0x09 +#define MBR3108_BASE_THRESHOLD0 0x0c +#define MBR3108_BASE_THRESHOLD1 0x0d +#define MBR3108_FINGER_THRESHOLD2 0x0e +#define MBR3108_FINGER_THRESHOLD3 0x0f +#define MBR3108_FINGER_THRESHOLD4 0x10 +#define MBR3108_FINGER_THRESHOLD5 0x11 +#define MBR3108_FINGER_THRESHOLD6 0x12 +#define MBR3108_FINGER_THRESHOLD7 0x13 +#define MBR3108_SENSOR_DEBOUNCE 0x1c +#define MBR3108_BUTTON_HYS 0x1d +#define MBR3108_BUTTON_LBR 0x1f +#define MBR3108_BUTTON_NNT 0x20 +#define MBR3108_BUTTON_NT 0x21 +#define MBR3108_PROX_EN 0x26 +#define MBR3108_PROX_CFG 0x27 +#define MBR3108_PROX_CFG2 0x28 +#define MBR3108_PROX_TOUCH_TH0 0x2a +#define MBR3108_PROX_TOUCH_TH1 0x2c +#define MBR3108_PROX_RESOLUTION0 0x2e +#define MBR3108_PROX_RESOLUTION1 0x2f +#define MBR3108_PROX_HYS 0x30 +#define MBR3108_PROX_LBR 0x32 +#define MBR3108_PROX_NNT 0x33 +#define MBR3108_PROX_NT 0x34 +#define MBR3108_PROX_POSITIVE_TH0 0x35 +#define MBR3108_PROX_POSITIVE_TH1 0x36 +#define MBR3108_PROX_NEGATIVE_TH0 0x39 +#define MBR3108_PROX_NEGATIVE_TH1 0x3a +#define MBR3108_LED_ON_TIME 0x3d +#define MBR3108_BUZZER_CFG 0x3e +#define MBR3108_BUZZER_ON_TIME 0x3f +#define MBR3108_GPO_CFG 0x40 +#define MBR3108_PWM_DUTYCYCLE_CFG0 0x41 +#define MBR3108_PWM_DUTYCYCLE_CFG1 0x42 +#define MBR3108_PWM_DUTYCYCLE_CFG2 0x43 +#define MBR3108_PWM_DUTYCYCLE_CFG3 0x44 +#define MBR3108_SPO_CFG 0x4c +#define MBR3108_DEVICE_CFG0 0x4d +#define MBR3108_DEVICE_CFG1 0x4e +#define MBR3108_DEVICE_CFG2 0x4f +#define MBR3108_DEVICE_CFG3 0x50 +#define MBR3108_I2C_ADDR 0x51 +#define MBR3108_REFRESH_CTRL 0x52 +#define MBR3108_STATE_TIMEOUT 0x55 +#define MBR3108_CONFIG_CRC 0x7e +#define MBR3108_GPO_OUTPUT_STATE 0x80 +#define MBR3108_SENSOR_ID 0x82 +#define MBR3108_CTRL_CMD 0x86 +#define MBR3108_CTRL_CMD_STATUS 0x88 +#define MBR3108_CTRL_CMD_ERR 0x89 +#define MBR3108_SYSTEM_STATUS 0x8a +#define MBR3108_PREV_CTRL_CMD_CODE 0x8c +#define MBR3108_FAMILY_ID 0x8f +#define MBR3108_DEVICE_ID 0x90 +#define MBR3108_DEVICE_REV 0x92 +#define MBR3108_CALC_CRC 0x94 +#define MBR3108_TOTAL_WORKING_SNS 0x97 +#define MBR3108_SNS_CP_HIGH 0x98 +#define MBR3108_SNS_VDD_SHORT 0x9a +#define MBR3108_SNS_GND_SHORT 0x9c +#define MBR3108_SNS_SNS_SHORT 0x9e +#define MBR3108_CMOD_SHIELD_TEST 0xa0 +#define MBR3108_BUTTON_STAT 0xaa +#define MBR3108_LATCHED_BUTTON_STAT 0xac +#define MBR3108_PROX_STAT 0xae +#define MBR3108_LATCHED_PROX_STAT 0xaf +#define MBR3108_SYNC_COUNTER0 0xb9 +#define MBR3108_DIFFERENCE_COUNT_SENSOR0 0xba +#define MBR3108_DIFFERENCE_COUNT_SENSOR1 0xbc +#define MBR3108_DIFFERENCE_COUNT_SENSOR2 0xbe +#define MBR3108_DIFFERENCE_COUNT_SENSOR3 0xc0 +#define MBR3108_DIFFERENCE_COUNT_SENSOR4 0xc2 +#define MBR3108_DIFFERENCE_COUNT_SENSOR5 0xc4 +#define MBR3108_DIFFERENCE_COUNT_SENSOR6 0xc6 +#define MBR3108_DIFFERENCE_COUNT_SENSOR7 0xc8 +#define MBR3108_GPO_DATA 0xda +#define MBR3108_SYNC_COUNTER1 0xdb +#define MBR3108_DEBUG_SENSOR_ID 0xdc +#define MBR3108_DEBUG_CP 0xdd +#define MBR3108_DEBUG_DIFFERENCE_COUNT0 0xde +#define MBR3108_DEBUG_BASELINE0 0xe0 +#define MBR3108_DEBUG_RAW_COUNT0 0xe2 +#define MBR3108_DEBUG_AVG_RAW_COUNT0 0xe4 +#define MBR3108_SYNC_COUNTER2 0xe7 + +/* Device commands for MBR3108_CTRL_CMD */ + +#define MBR3108_CMD_COMPLETED 0 +#define MBR3108_CMD_CHECK_CONFIG_CRC 2 +#define MBR3108_CMD_SET_CONFIG_CRC 3 +#define MBR3108_CMD_ENTER_LOW_POWER_MODE 7 +#define MBR3108_CMD_CLEAR_LATCHED 8 +#define MBR3108_CMD_RESET_ADV_LOWPASS_FILTER_PROX_SENS_0 9 +#define MBR3108_CMD_RESET_ADV_LOWPASS_FILTER_PROX_SENS_1 10 +#define MBR3108_CMD_SOFTWARE_RESET 255 + +#define MBR3108_CMD_STATUS_SUCCESS 0 +#define MBR3108_CMD_STATUS_ERROR 1 +#define MBR3108_CMD_STATUS_MASK 1 + +/* Completion times for device commands */ + +#define MBR3108_CMD_MSECS_CHECK_CONFIG_CRC 280 /* >220 (typ.) */ +#define MBR3108_CMD_MSECS_SOFTWARE_RESET 50 +#define MBR3108_CMD_MSECS_CLEAR_LATCHED 50 + +/* Other macros */ + +#define MBR3108_I2C_RETRIES 10 +#define MBR3108_NUM_SENSORS 8 +#define MBR3108_EXPECTED_FAMILY_ID 0x9a +#define MBR3108_EXPECTED_DEVICE_ID 0x0a03 +#define MBR3108_EXPECTED_DEVICE_REV 1 +#define MBR3108_SYNC_RETRIES 10 + +#ifndef CONFIG_MBR3108_I2C_FREQUENCY +# define CONFIG_MBR3108_I2C_FREQUENCY 400000 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct mbr3108_dev_s +{ + /* I2C bus and address for device. */ + + struct i2c_master_s *i2c; + uint8_t addr; + + /* Configuration for device. */ + + struct mbr3108_board_s *board; + const struct mbr3108_sensor_conf_s *sensor_conf; + sem_t devsem; + uint8_t cref; + struct mbr3108_debug_conf_s debug_conf; + bool int_pending; + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *fds[CONFIG_INPUT_CYPRESS_MBR3108_NPOLLWAITERS]; +#endif +}; + +/**************************************************************************** +* Private Function Prototypes +*****************************************************************************/ + +static int mbr3108_open(FAR struct file *filep); +static int mbr3108_close(FAR struct file *filep); +static ssize_t mbr3108_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t mbr3108_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +#ifndef CONFIG_DISABLE_POLL +static int mbr3108_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); +#endif + +/**************************************************************************** +* Private Data +****************************************************************************/ + +static const struct file_operations g_mbr3108_fileops = +{ + mbr3108_open, /* open */ + mbr3108_close, /* close */ + mbr3108_read, /* read */ + mbr3108_write, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , mbr3108_poll /* poll */ +#endif +}; + +/**************************************************************************** +* Private Functions +****************************************************************************/ + +static int mbr3108_i2c_write(FAR struct mbr3108_dev_s *dev, uint8_t reg, + const uint8_t *buf, size_t buflen) +{ + struct i2c_msg_s msgv[2] = + { + { + .frequency = CONFIG_MBR3108_I2C_FREQUENCY, + .addr = dev->addr, + .flags = 0, + .buffer = ®, + .length = 1 + }, + { + .frequency = CONFIG_MBR3108_I2C_FREQUENCY, + .addr = dev->addr, + .flags = I2C_M_NORESTART, + .buffer = (void *)buf, + .length = buflen + } + }; + int ret = -EIO; + int retries; + + /* MBR3108 will respond with NACK to address when in low-power mode. Host + * needs to retry address selection multiple times to get MBR3108 to wake-up. + */ + + for (retries = 0; retries < MBR3108_I2C_RETRIES; retries++) + { + ret = I2C_TRANSFER(dev->i2c, msgv, 2); + if (ret == -ENXIO) + { + /* -ENXIO is returned when getting NACK from response. + * Keep trying. + */ + + continue; + } + + if (ret >= 0) + { + /* Success! */ + + return 0; + } + } + + /* Failed to read sensor. */ + + return ret; +} + +static int mbr3108_i2c_read(FAR struct mbr3108_dev_s *dev, uint8_t reg, + uint8_t *buf, size_t buflen) +{ + struct i2c_msg_s msgv[2] = + { + { + .frequency = CONFIG_MBR3108_I2C_FREQUENCY, + .addr = dev->addr, + .flags = 0, + .buffer = ®, + .length = 1 + }, + { + .frequency = CONFIG_MBR3108_I2C_FREQUENCY, + .addr = dev->addr, + .flags = I2C_M_READ, + .buffer = buf, + .length = buflen + } + }; + int ret = -EIO; + int retries; + + /* MBR3108 will respond with NACK to address when in low-power mode. Host + * needs to retry address selection multiple times to get MBR3108 to wake-up. + */ + + for (retries = 0; retries < MBR3108_I2C_RETRIES; retries++) + { + ret = I2C_TRANSFER(dev->i2c, msgv, 2); + if (ret == -ENXIO) + { + /* -ENXIO is returned when getting NACK from response. + * Keep trying. + */ + + continue; + } + else if (ret >= 0) + { + /* Success! */ + + return 0; + } + else + { + /* Some other error. Try to reset I2C bus and keep trying. */ + +#ifdef CONFIG_I2C_RESET + if (retries == MBR3108_I2C_RETRIES - 1) + { + break; + } + + ret = I2C_RESET(dev->i2c); + if (ret < 0) + { + mbr3108_dbg("I2C_RESET failed: %d\n", ret); + return ret; + } +#endif + } + } + + /* Failed to read sensor. */ + + return ret; +} + +static int mbr3108_check_cmd_status(FAR struct mbr3108_dev_s *dev) +{ + const uint8_t start_reg = MBR3108_CTRL_CMD; + const uint8_t last_reg = MBR3108_CTRL_CMD_ERR; + uint8_t readbuf[MBR3108_CTRL_CMD_ERR - MBR3108_CTRL_CMD + 1]; + uint8_t cmd, cmd_status, cmd_err; + int ret; + + DEBUGASSERT(last_reg - start_reg + 1 == sizeof(readbuf)); + + /* Multi-byte read to get command status. */ + + ret = mbr3108_i2c_read(dev, start_reg, readbuf, sizeof(readbuf)); + if (ret < 0) + { + mbr3108_dbg("cmd status get failed. ret=%d\n", ret); + return ret; + } + + cmd = readbuf[MBR3108_CTRL_CMD - MBR3108_CTRL_CMD]; + cmd_status = readbuf[MBR3108_CTRL_CMD_STATUS - MBR3108_CTRL_CMD]; + cmd_err = readbuf[MBR3108_CTRL_CMD_ERR - MBR3108_CTRL_CMD]; + + mbr3108_dbg("cmd: %d, status: %d, err: %d\n", cmd, cmd_status, cmd_err); + + if (cmd != MBR3108_CMD_COMPLETED) + { + return -EBUSY; + } + + if ((cmd_status & MBR3108_CMD_STATUS_MASK) == MBR3108_CMD_STATUS_SUCCESS) + { + /* Success. */ + + return 0; + } + + return cmd_err; +} + +static int mbr3108_save_check_crc(FAR struct mbr3108_dev_s *dev) +{ + uint8_t reg = MBR3108_CTRL_CMD; + uint8_t cmd = MBR3108_CMD_CHECK_CONFIG_CRC; + int ret; + + ret = mbr3108_i2c_write(dev, reg, &cmd, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_CTRL_CMD:CHECK_CONFIG_CRC write failed.\n"); + return ret; + } + + usleep(MBR3108_CMD_MSECS_CHECK_CONFIG_CRC * 1000); + + ret = mbr3108_check_cmd_status(dev); + if (ret != 0) + { + return ret < 0 ? ret : -EIO; + } + + return 0; +} + +static int mbr3108_software_reset(FAR struct mbr3108_dev_s *dev) +{ + uint8_t reg = MBR3108_CTRL_CMD; + uint8_t cmd = MBR3108_CMD_SOFTWARE_RESET; + int ret; + + ret = mbr3108_i2c_write(dev, reg, &cmd, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_CTRL_CMD:SOFTWARE_RESET write failed.\n"); + return ret; + } + + usleep(MBR3108_CMD_MSECS_SOFTWARE_RESET * 1000); + + ret = mbr3108_check_cmd_status(dev); + if (ret != 0) + { + return ret < 0 ? ret : -EIO; + } + + return 0; +} + +static int mbr3108_enter_low_power_mode(FAR struct mbr3108_dev_s *dev) +{ + uint8_t reg = MBR3108_CTRL_CMD; + uint8_t cmd = MBR3108_CMD_ENTER_LOW_POWER_MODE; + int ret; + + ret = mbr3108_i2c_write(dev, reg, &cmd, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_CTRL_CMD:SOFTWARE_RESET write failed.\n"); + return ret; + } + + /* Device is now in low-power mode and not scanning. Further communication + * will cause wake-up and make chip resume scanning operations. + */ + + return 0; +} + +static int mbr3108_clear_latched(FAR struct mbr3108_dev_s *dev) +{ + uint8_t reg = MBR3108_CTRL_CMD; + uint8_t cmd = MBR3108_CMD_CLEAR_LATCHED; + int ret; + + ret = mbr3108_i2c_write(dev, reg, &cmd, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_CTRL_CMD:MBR3108_CMD_CLEAR_LATCHED write failed.\n"); + return ret; + } + + usleep(MBR3108_CMD_MSECS_CLEAR_LATCHED * 1000); + + ret = mbr3108_check_cmd_status(dev); + if (ret != 0) + { + return ret < 0 ? ret : -EIO; + } + + return 0; +} + +static int mbr3108_debug_setup(FAR struct mbr3108_dev_s *dev, + FAR const struct mbr3108_debug_conf_s *conf) +{ + uint8_t reg = MBR3108_SENSOR_ID; + int ret; + + /* Store new debug configuration. */ + + dev->debug_conf = *conf; + + if (!conf->debug_mode) + { + return 0; + } + + /* Setup debug sensor id. */ + + ret = mbr3108_i2c_write(dev, reg, &conf->debug_sensor_id, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_SENSOR_ID write failed.\n"); + + dev->debug_conf.debug_mode = false; + } + + return ret; +} + +static int mbr3108_device_configuration(FAR struct mbr3108_dev_s *dev, + FAR const struct mbr3108_sensor_conf_s *conf) +{ + const uint8_t start_reg = MBR3108_SENSOR_EN; + const uint8_t last_reg = MBR3108_CONFIG_CRC + 1; + uint8_t value; + int ret = 0; + + DEBUGASSERT(sizeof(conf->conf_data) == last_reg - start_reg + 1); + + ret = mbr3108_i2c_read(dev, MBR3108_CTRL_CMD, &value, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_CTRL_CMD read failed.\n"); + return ret; + } + + if (value != MBR3108_CMD_COMPLETED) + { + /* Device is busy processing previous command. */ + + return -EBUSY; + } + + ret = mbr3108_i2c_write(dev, start_reg, conf->conf_data, + last_reg - start_reg + 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108 configuration write failed.\n"); + return ret; + } + + ret = mbr3108_save_check_crc(dev); + if (ret < 0) + { + mbr3108_dbg("MBR3108 save check CRC failed. ret=%d\n", ret); + return ret; + } + + ret = mbr3108_software_reset(dev); + if (ret < 0) + { + mbr3108_dbg("MBR3108 software reset failed.\n"); + return ret; + } + + dev->board->irq_enable(dev->board, true); + + return 0; +} + +static int mbr3108_get_sensor_status(FAR struct mbr3108_dev_s *dev, + FAR void *buf) +{ + struct mbr3108_sensor_status_s status = {}; + const uint8_t start_reg = MBR3108_BUTTON_STAT; + const uint8_t last_reg = MBR3108_LATCHED_PROX_STAT; + uint8_t readbuf[MBR3108_LATCHED_PROX_STAT - MBR3108_BUTTON_STAT + 1]; + int ret; + + DEBUGASSERT(last_reg - start_reg + 1 == sizeof(readbuf)); + + /* Attempt to sensor status registers.*/ + + ret = mbr3108_i2c_read(dev, start_reg, readbuf, sizeof(readbuf)); + if (ret < 0) + { + mbr3108_dbg("Sensor status read failed.\n"); + + return ret; + } + + status.button = (readbuf[MBR3108_BUTTON_STAT + 0 - start_reg]) | + (readbuf[MBR3108_BUTTON_STAT + 1 - start_reg] << 8); + status.proximity = readbuf[MBR3108_PROX_STAT - start_reg]; + + status.latched_button = + (readbuf[MBR3108_LATCHED_BUTTON_STAT + 0 - start_reg]) | + (readbuf[MBR3108_LATCHED_BUTTON_STAT + 1 - start_reg] << 8); + status.latched_proximity = readbuf[MBR3108_LATCHED_PROX_STAT - start_reg]; + + memcpy(buf, &status, sizeof(status)); + + mbr3108_dbg("but: %x, prox: %x; latched[btn: %x, prox: %x]\n", + status.button, status.proximity, status.latched_button, + status.latched_button); + + return 0; +} + +static int mbr3108_get_sensor_debug_data(FAR struct mbr3108_dev_s *dev, + FAR void *buf) +{ + struct mbr3108_sensor_debug_s data = {}; + const uint8_t start_reg = MBR3108_SYNC_COUNTER1; + const uint8_t last_reg = MBR3108_SYNC_COUNTER2; + uint8_t readbuf[MBR3108_SYNC_COUNTER2 - MBR3108_SYNC_COUNTER1 + 1]; + int ret; + int retries; + uint8_t sync1, sync2; + + DEBUGASSERT(last_reg - start_reg + 1 == sizeof(readbuf)); + + for (retries = MBR3108_SYNC_RETRIES; retries > 0; retries--) + { + ret = mbr3108_i2c_read(dev, start_reg, readbuf, sizeof(readbuf)); + if (ret < 0) + { + mbr3108_dbg("Sensor debug data read failed.\n"); + + return ret; + } + + /* Sync counters need to match. */ + + sync1 = readbuf[MBR3108_SYNC_COUNTER1 - start_reg]; + sync2 = readbuf[MBR3108_SYNC_COUNTER2 - start_reg]; + + if (sync1 == sync2) + { + break; + } + } + + if (retries == 0) + { + return -EIO; + } + + data.sensor_average_counts = + (readbuf[MBR3108_DEBUG_AVG_RAW_COUNT0 + 0 - start_reg]) | + (readbuf[MBR3108_DEBUG_AVG_RAW_COUNT0 + 1 - start_reg] << 8); + data.sensor_baseline = + (readbuf[MBR3108_DEBUG_BASELINE0 + 0 - start_reg]) | + (readbuf[MBR3108_DEBUG_BASELINE0 + 1 - start_reg] << 8); + data.sensor_diff_counts = + (readbuf[MBR3108_DEBUG_DIFFERENCE_COUNT0 + 0 - start_reg]) | + (readbuf[MBR3108_DEBUG_DIFFERENCE_COUNT0 + 1 - start_reg] << 8); + data.sensor_raw_counts = + (readbuf[MBR3108_DEBUG_RAW_COUNT0 + 0 - start_reg]) | + (readbuf[MBR3108_DEBUG_RAW_COUNT0 + 1 - start_reg] << 8); + data.sensor_total_capacitance = readbuf[MBR3108_DEBUG_CP - start_reg]; + + memcpy(buf, &data, sizeof(data)); + + mbr3108_dbg("avg_cnt: %d, baseline: %d, diff_cnt: %d, raw_cnt: %d, " + "total_cp: %d\n", + data.sensor_average_counts, data.sensor_baseline, + data.sensor_diff_counts, data.sensor_raw_counts, + data.sensor_total_capacitance); + + return 0; +} + +static int mbr3108_probe_device(FAR struct mbr3108_dev_s *dev) +{ + const uint8_t start_reg = MBR3108_FAMILY_ID; + const uint8_t last_reg = MBR3108_DEVICE_REV; + uint8_t readbuf[MBR3108_DEVICE_REV - MBR3108_FAMILY_ID + 1]; + uint8_t fam_id; + uint16_t dev_id; + uint8_t dev_rev; + int ret; + + DEBUGASSERT(last_reg - start_reg + 1 == sizeof(readbuf)); + + /* Attempt to read device identification registers with multi-byte read.*/ + + ret = mbr3108_i2c_read(dev, start_reg, readbuf, sizeof(readbuf)); + if (ret < 0) + { + /* Failed to read registers from device. */ + + mbr3108_dbg("Probe failed.\n"); + + return ret; + } + + /* Check result. */ + + fam_id = readbuf[MBR3108_FAMILY_ID - start_reg]; + dev_id = (readbuf[MBR3108_DEVICE_ID + 0 - start_reg]) | + (readbuf[MBR3108_DEVICE_ID + 1 - start_reg] << 8); + dev_rev = readbuf[MBR3108_DEVICE_REV - start_reg]; + + mbr3108_dbg("family_id: 0x%02x, device_id: 0x%04x, device_rev: %d\n", + fam_id, dev_id, dev_rev); + + if (fam_id != MBR3108_EXPECTED_FAMILY_ID || + dev_id != MBR3108_EXPECTED_DEVICE_ID || + dev_rev != MBR3108_EXPECTED_DEVICE_REV) + { + mbr3108_dbg("Probe failed, dev-id mismatch!\n"); + mbr3108_dbg( + " Expected: family_id: 0x%02x, device_id: 0x%04x, device_rev: %d\n", + MBR3108_EXPECTED_FAMILY_ID, + MBR3108_EXPECTED_DEVICE_ID, + MBR3108_EXPECTED_DEVICE_REV); + + return -ENXIO; + } + + return 0; +} + +static ssize_t mbr3108_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct inode *inode; + FAR struct mbr3108_dev_s *priv; + size_t outlen; + irqstate_t flags; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + ret = -EINVAL; + + if (priv->debug_conf.debug_mode) + { + outlen = sizeof(struct mbr3108_sensor_debug_s); + if (buflen >= outlen) + { + ret = mbr3108_get_sensor_debug_data(priv, buffer); + } + } + else + { + outlen = sizeof(struct mbr3108_sensor_status_s); + if (buflen >= outlen) + { + ret = mbr3108_get_sensor_status(priv, buffer); + } + } + + flags = enter_critical_section(); + priv->int_pending = false; + leave_critical_section(flags); + + sem_post(&priv->devsem); + return ret < 0 ? ret : outlen; +} + +static ssize_t mbr3108_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + FAR struct inode *inode; + FAR struct mbr3108_dev_s *priv; + enum mbr3108_cmd_e type; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + if (buflen < sizeof(enum mbr3108_cmd_e)) + { + return -EINVAL; + } + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + type = *(FAR const enum mbr3108_cmd_e *)buffer; + + switch (type) + { + case CYPRESS_MBR3108_CMD_SENSOR_CONF: + { + FAR const struct mbr3108_cmd_sensor_conf_s *conf = + (FAR const struct mbr3108_cmd_sensor_conf_s *)buffer; + + if (buflen != sizeof(*conf)) + { + ret = -EINVAL; + goto out; + } + + ret = mbr3108_device_configuration(priv, &conf->conf); + break; + } + + case CYPRESS_MBR3108_CMD_DEBUG_CONF: + { + FAR const struct mbr3108_cmd_debug_conf_s *conf = + (FAR const struct mbr3108_cmd_debug_conf_s *)buffer; + + if (buflen != sizeof(*conf)) + { + ret = -EINVAL; + goto out; + } + + ret = mbr3108_debug_setup(priv, &conf->conf); + break; + } + + case CYPRESS_MBR3108_CMD_CLEAR_LATCHED: + { + if (buflen != sizeof(type)) + { + ret = -EINVAL; + goto out; + } + + ret = mbr3108_clear_latched(priv); + break; + } + + default: + ret = -EINVAL; + break; + } + +out: + sem_post(&priv->devsem); + + return ret < 0 ? ret : buflen; +} + +static int mbr3108_open(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct mbr3108_dev_s *priv; + unsigned int use_count; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + while (sem_wait(&priv->devsem) != 0) + { + assert(errno == EINTR); + } + + use_count = priv->cref + 1; + if (use_count == 1) + { + /* First user, do power on. */ + + ret = priv->board->set_power(priv->board, true); + if (ret < 0) + { + goto out_sem; + } + + /* Let chip to power up before probing */ + + usleep(100 * 1000); + + /* Check that device exists on I2C. */ + + ret = mbr3108_probe_device(priv); + if (ret < 0) + { + /* No such device. Power off the switch. */ + + (void)priv->board->set_power(priv->board, false); + goto out_sem; + } + + if (priv->sensor_conf) + { + /* Do configuration. */ + + ret = mbr3108_device_configuration(priv, priv->sensor_conf); + if (ret < 0) + { + /* Configuration failed. Power off the switch. */ + + (void)priv->board->set_power(priv->board, false); + goto out_sem; + } + } + + priv->cref = use_count; + } + else + { + DEBUGASSERT(use_count < UINT8_MAX && use_count > priv->cref); + + priv->cref = use_count; + ret = 0; + } + +out_sem: + sem_post(&priv->devsem); + return ret; +} + +static int mbr3108_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct mbr3108_dev_s *priv; + int use_count; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + while (sem_wait(&priv->devsem) != 0) + { + assert(errno == EINTR); + } + + use_count = priv->cref - 1; + if (use_count == 0) + { + /* Disable interrupt */ + + priv->board->irq_enable(priv->board, false); + + /* Set chip in low-power mode. */ + + (void)mbr3108_enter_low_power_mode(priv); + + /* Last user, do power off. */ + + (void)priv->board->set_power(priv->board, false); + + priv->debug_conf.debug_mode = false; + priv->cref = use_count; + } + else + { + DEBUGASSERT(use_count > 0); + + priv->cref = use_count; + } + + sem_post(&priv->devsem); + + return 0; +} + +#ifndef CONFIG_DISABLE_POLL + +static void mbr3108_poll_notify(FAR struct mbr3108_dev_s *priv) +{ + int i; + + DEBUGASSERT(priv != NULL); + + for (i = 0; i < CONFIG_INPUT_CYPRESS_MBR3108_NPOLLWAITERS; i++) + { + struct pollfd *fds = priv->fds[i]; + if (fds) + { + mbr3108_dbg("Report events: %02x\n", fds->revents); + + fds->revents |= POLLIN; + sem_post(fds->sem); + } + } +} + +static int mbr3108_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct mbr3108_dev_s *priv; + FAR struct inode *inode; + bool pending; + int ret = 0; + int i; + + DEBUGASSERT(filep && fds); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct mbr3108_dev_s *)inode->i_private; + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + if (setup) + { + /* Ignore waits that do not include POLLIN */ + + if ((fds->events & POLLIN) == 0) + { + ret = -EDEADLK; + goto out; + } + + /* This is a request to set up the poll. Find an available slot for the + * poll structure reference. + */ + + for (i = 0; i < CONFIG_INPUT_CYPRESS_MBR3108_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!priv->fds[i]) + { + /* Bind the poll structure and this slot */ + + priv->fds[i] = fds; + fds->priv = &priv->fds[i]; + break; + } + } + + if (i >= CONFIG_INPUT_CYPRESS_MBR3108_NPOLLWAITERS) + { + fds->priv = NULL; + ret = -EBUSY; + } + else + { + pending = priv->int_pending; + if (pending) + { + mbr3108_poll_notify(priv); + } + } + } + else if (fds->priv) + { + /* This is a request to tear down the poll. */ + + FAR struct pollfd **slot = (FAR struct pollfd **)fds->priv; + DEBUGASSERT(slot != NULL); + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +out: + sem_post(&priv->devsem); + return ret; +} + +#endif /* !CONFIG_DISABLE_POLL */ + +static int mbr3108_isr_handler(int irq, FAR void *context, FAR void *arg) +{ + FAR struct mbr3108_dev_s *priv = (FAR struct mbr3108_dev_s *)arg; + irqstate_t flags; + + DEBUGASSERT(priv != NULL); + + flags = enter_critical_section(); + priv->int_pending = true; + leave_critical_section(flags); + +#ifndef CONFIG_DISABLE_POLL + mbr3108_poll_notify(priv); +#endif + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int cypress_mbr3108_register(FAR const char *devpath, + FAR struct i2c_master_s *i2c_dev, + uint8_t i2c_devaddr, + struct mbr3108_board_s *board_config, + const struct mbr3108_sensor_conf_s *sensor_conf) +{ + struct mbr3108_dev_s *priv; + int ret = 0; + + /* Allocate device private structure. */ + + priv = kmm_zalloc(sizeof(struct mbr3108_dev_s)); + if (!priv) + { + mbr3108_dbg("Memory cannot be allocated for mbr3108 sensor\n"); + return -ENOMEM; + } + + /* Setup device structure. */ + + priv->addr = i2c_devaddr; + priv->i2c = i2c_dev; + priv->board = board_config; + priv->sensor_conf = sensor_conf; + + sem_init(&priv->devsem, 0, 1); + + ret = register_driver(devpath, &g_mbr3108_fileops, 0666, priv); + if (ret < 0) + { + kmm_free(priv); + mbr3108_dbg("Error occurred during the driver registering\n"); + return ret; + } + + mbr3108_dbg("Registered with %d\n", ret); + + /* Prepare interrupt line and handler. */ + + priv->board->irq_attach(priv->board, mbr3108_isr_handler, priv); + priv->board->irq_enable(priv->board, false); + + return 0; +} diff --git a/drivers/mtd/mtd_config.c b/drivers/mtd/mtd_config.c index 69ac00237d0..2566efedc85 100644 --- a/drivers/mtd/mtd_config.c +++ b/drivers/mtd/mtd_config.c @@ -352,7 +352,14 @@ static int mtdconfig_findfirstentry(FAR struct mtdconfig_struct_s *dev, off_t bytes_left_in_block; uint16_t endblock; - mtdconfig_readbytes(dev, 0, sig, sizeof(sig)); /* Read the signature bytes */ + /* Read the signature bytes */ + + ret = mtdconfig_readbytes(dev, 0, sig, sizeof(sig)); + if (ret != OK) + { + return 0; + } + if (sig[0] != 'C' || sig[1] != 'D' || sig[2] != CONFIGDATA_FORMAT_VERSION) { /* Config Data partition not formatted. */ @@ -788,7 +795,14 @@ static off_t mtdconfig_consolidate(FAR struct mtdconfig_struct_s *dev) /* Scan all headers and move them to the src_offset */ retry_relocate: - MTD_READ(dev->mtd, src_offset, sizeof(hdr), (uint8_t *) &hdr); + bytes = MTD_READ(dev->mtd, src_offset, sizeof(hdr), (uint8_t *) &hdr); + if (bytes != sizeof(hdr)) + { + /* I/O Error! */ + + goto errout; + } + if (hdr.flags == MTD_ERASED_FLAGS) { /* Test if the source entry is active or if we are at the end @@ -967,6 +981,11 @@ static ssize_t mtdconfig_read(FAR struct file *filep, FAR char *buffer, /* Read data from the file */ bytes = MTD_READ(dev->mtd, dev->readoff, len, (uint8_t *) buffer); + if (bytes != len) + { + return -EIO; + } + dev->readoff += bytes; return bytes; } @@ -981,6 +1000,7 @@ static int mtdconfig_findentry(FAR struct mtdconfig_struct_s *dev, FAR struct mtdconfig_header_s *phdr) { uint16_t endblock; + int ret; #ifdef CONFIG_MTD_CONFIG_RAM_CONSOLIDATE endblock = dev->neraseblocks; @@ -1013,7 +1033,15 @@ static int mtdconfig_findentry(FAR struct mtdconfig_struct_s *dev, /* Read the 1st header from the next block */ - mtdconfig_readbytes(dev, offset, (uint8_t *) phdr, sizeof(*phdr)); + ret = mtdconfig_readbytes(dev, offset, (uint8_t *) phdr, sizeof(*phdr)); + if (ret != OK) + { + /* Error reading the data */ + + offset = 0; + break; + } + if (phdr->flags == MTD_ERASED_FLAGS) { continue; diff --git a/drivers/mtd/mtd_partition.c b/drivers/mtd/mtd_partition.c index 655fe368261..f8438cdd976 100644 --- a/drivers/mtd/mtd_partition.c +++ b/drivers/mtd/mtd_partition.c @@ -157,7 +157,7 @@ static int part_procfs_stat(FAR const char *relpath, ****************************************************************************/ #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_PROCFS_EXCLUDE_PARTITIONS) -struct mtd_partition_s *g_pfirstpartition = NULL; +static struct mtd_partition_s *g_pfirstpartition = NULL; const struct procfs_operations part_procfsoperations = { diff --git a/drivers/mtd/smart.c b/drivers/mtd/smart.c index c5c6e80a3e9..e483bc99d3f 100644 --- a/drivers/mtd/smart.c +++ b/drivers/mtd/smart.c @@ -1368,7 +1368,8 @@ static int smart_add_sector_to_cache(FAR struct smart_struct_s *dev, index = 1; if (dev->cache_entries < CONFIG_MTD_SMART_SECTOR_CACHE_SIZE) { - index = dev->cache_entries++; + oldest = 0; + index = dev->cache_entries++; } else { @@ -1387,7 +1388,7 @@ static int smart_add_sector_to_cache(FAR struct smart_struct_s *dev, if (dev->sCache[x].birth < oldest) { oldest = dev->sCache[x].birth; - index = x; + index = x; } } } diff --git a/drivers/mtd/w25.c b/drivers/mtd/w25.c index 79ac0a5a66b..458c85e092b 100644 --- a/drivers/mtd/w25.c +++ b/drivers/mtd/w25.c @@ -224,6 +224,7 @@ struct w25_dev_s struct mtd_dev_s mtd; /* MTD interface */ FAR struct spi_dev_s *spi; /* Saved SPI interface instance */ uint16_t nsectors; /* Number of erase sectors */ + uint8_t prev_instr; /* Previous instruction given to W25 device */ #if defined(CONFIG_W25_SECTOR512) && !defined(CONFIG_W25_READONLY) uint8_t flags; /* Buffered sector flags */ @@ -247,6 +248,7 @@ static void w25_unprotect(FAR struct w25_dev_s *priv); static uint8_t w25_waitwritecomplete(FAR struct w25_dev_s *priv); static inline void w25_wren(FAR struct w25_dev_s *priv); static inline void w25_wrdi(FAR struct w25_dev_s *priv); +static bool w25_is_erased(struct w25_dev_s *priv, off_t address, off_t size); static void w25_sectorerase(FAR struct w25_dev_s *priv, off_t offset); static inline int w25_chiperase(FAR struct w25_dev_s *priv); static void w25_byteread(FAR struct w25_dev_s *priv, FAR uint8_t *buffer, @@ -494,17 +496,17 @@ static uint8_t w25_waitwritecomplete(struct w25_dev_s *priv) /* Given that writing could take up to few tens of milliseconds, and erasing * could take more. The following short delay in the "busy" case will allow - * other peripherals to access the SPI bus. + * other peripherals to access the SPI bus. Delay would slow down writing + * too much, so go to sleep only if previous operation was not a page program + * operation. */ -#if 0 /* Makes writes too slow */ - if ((status & W25_SR_BUSY) != 0) + if (priv->prev_instr != W25_PP && (status & W25_SR_BUSY) != 0) { w25_unlock(priv->spi); usleep(1000); w25_lock(priv->spi); } -#endif } while ((status & W25_SR_BUSY) != 0); @@ -549,6 +551,55 @@ static inline void w25_wrdi(struct w25_dev_s *priv) SPI_SELECT(priv->spi, SPIDEV_FLASH(0), false); } +/************************************************************************************ + * Name: w25_is_erased + ************************************************************************************/ + +static bool w25_is_erased(struct w25_dev_s *priv, off_t address, off_t size) +{ + size_t npages = size >> W25_PAGE_SHIFT; + uint32_t erased_32; + unsigned int i; + uint32_t *buf; + + DEBUGASSERT((address % W25_PAGE_SIZE) == 0); + DEBUGASSERT((size % W25_PAGE_SIZE) == 0); + + buf = kmm_malloc(W25_PAGE_SIZE); + if (!buf) + { + return false; + } + + memset(&erased_32, W25_ERASED_STATE, sizeof(erased_32)); + + /* Walk all pages in given area. */ + + while (npages) + { + /* Check if all bytes of page is in erased state. */ + + w25_byteread(priv, (unsigned char *)buf, address, W25_PAGE_SIZE); + + for (i = 0; i < W25_PAGE_SIZE / sizeof(uint32_t); i++) + { + if (buf[i] != erased_32) + { + /* Page not in erased state! */ + + kmm_free(buf); + return false; + } + } + + address += W25_PAGE_SIZE; + npages--; + } + + kmm_free(buf); + return true; +} + /************************************************************************************ * Name: w25_sectorerase ************************************************************************************/ @@ -559,6 +610,15 @@ static void w25_sectorerase(struct w25_dev_s *priv, off_t sector) finfo("sector: %08lx\n", (long)sector); + /* Check if sector is already erased. */ + + if (w25_is_erased(priv, address, W25_SECTOR_SIZE)) + { + /* Sector already in erased state, so skip erase. */ + + return; + } + /* Wait for any preceding write or erase operation to complete. */ (void)w25_waitwritecomplete(priv); @@ -574,6 +634,7 @@ static void w25_sectorerase(struct w25_dev_s *priv, off_t sector) /* Send the "Sector Erase (SE)" instruction */ (void)SPI_SEND(priv->spi, W25_SE); + priv->prev_instr = W25_SE; /* Send the sector address high byte first. Only the most significant bits (those * corresponding to the sector) have any meaning. @@ -611,6 +672,7 @@ static inline int w25_chiperase(struct w25_dev_s *priv) /* Send the "Chip Erase (CE)" instruction */ (void)SPI_SEND(priv->spi, W25_CE); + priv->prev_instr = W25_CE; /* Deselect the FLASH */ @@ -647,8 +709,10 @@ static void w25_byteread(FAR struct w25_dev_s *priv, FAR uint8_t *buffer, #ifdef CONFIG_W25_SLOWREAD (void)SPI_SEND(priv->spi, W25_RDDATA); + priv->prev_instr = W25_RDDATA; #else (void)SPI_SEND(priv->spi, W25_FRD); + priv->prev_instr = W25_FRD; #endif /* Send the address high byte first. */ @@ -704,6 +768,7 @@ static void w25_pagewrite(struct w25_dev_s *priv, FAR const uint8_t *buffer, /* Send the "Page Program (W25_PP)" Command */ SPI_SEND(priv->spi, W25_PP); + priv->prev_instr = W25_PP; /* Send the address high byte first. */ @@ -760,6 +825,7 @@ static inline void w25_bytewrite(struct w25_dev_s *priv, FAR const uint8_t *buff /* Send "Page Program (PP)" command */ (void)SPI_SEND(priv->spi, W25_PP); + priv->prev_instr = W25_PP; /* Send the page offset high byte first. */ diff --git a/drivers/rwbuffer.c b/drivers/rwbuffer.c index a7db82e156d..3871454e402 100644 --- a/drivers/rwbuffer.c +++ b/drivers/rwbuffer.c @@ -406,7 +406,9 @@ static int rwb_rhreload(struct rwbuffer_s *rwb, off_t startblock) int rwb_invalidate_writebuffer(FAR struct rwbuffer_s *rwb, off_t startblock, size_t blockcount) { - int ret; + int ret = OK; + + /* Is there a write buffer? Is data saved in the write buffer? */ if (rwb->wrmaxblocks > 0 && rwb->wrnblocks > 0) { @@ -909,7 +911,7 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock, */ } else -#else +#endif /* CONFIG_DRVR_WRITEBUFFER */ { /* No write buffer.. just pass the write operation through via the * flush callback. @@ -917,7 +919,6 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock, ret = rwb->wrflush(rwb->dev, wrbuffer, startblock, nblocks); } -#endif return (ssize_t)ret; } diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index 03911022b57..43c82293f1e 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -41,6 +41,11 @@ config HTS221 if HTS221 +config HTS221_I2C_FREQUENCY + int "HTS221 I2C frequency" + default 400000 + range 1 400000 + config DEBUG_HTS221 bool "Debug support for the HTS221" default n @@ -84,6 +89,11 @@ config LIS2DH if LIS2DH +config LIS2DH_I2C_FREQUENCY + int "LIS2DH I2C frequency" + default 400000 + range 1 400000 + config DEBUG_LIS2DH bool "Debug support for the LIS2DH" default n @@ -144,6 +154,11 @@ config LPS25H if LPS25H +config LPS25H_I2C_FREQUENCY + int "LPS25H I2C frequency" + default 400000 + range 1 400000 + config DEBUG_LPS25H bool "Debug support for the LPS25H" default n diff --git a/drivers/sensors/hts221.c b/drivers/sensors/hts221.c index 9f3138bddf6..9b85cf7e93f 100644 --- a/drivers/sensors/hts221.c +++ b/drivers/sensors/hts221.c @@ -61,6 +61,10 @@ # define hts221_dbg(x, ...) sninfo(x, ##__VA_ARGS__) #endif +#ifndef CONFIG_HTS221_I2C_FREQUENCY +# define CONFIG_HTS221_I2C_FREQUENCY 400000 +#endif + #define HTS221_WHO_AM_I 0x0f #define HTS221_AV_CONF 0x10 #define HTS221_CTRL_REG1 0x20 @@ -221,16 +225,18 @@ static int32_t hts221_write_reg8(FAR struct hts221_dev_s *priv, struct i2c_msg_s msgv[2] = { { - .addr = priv->addr, - .flags = 0, - .buffer = (FAR void *)&command[0], - .length = 1 + .frequency = CONFIG_HTS221_I2C_FREQUENCY, + .addr = priv->addr, + .flags = 0, + .buffer = (FAR void *)&command[0], + .length = 1 }, { - .addr = priv->addr, - .flags = I2C_M_NORESTART, - .buffer = (FAR void *)&command[1], - .length = 1 + .frequency = CONFIG_HTS221_I2C_FREQUENCY, + .addr = priv->addr, + .flags = I2C_M_NORESTART, + .buffer = (FAR void *)&command[1], + .length = 1 } }; @@ -243,16 +249,18 @@ static int hts221_read_reg(FAR struct hts221_dev_s *priv, struct i2c_msg_s msgv[2] = { { - .addr = priv->addr, - .flags = 0, - .buffer = (FAR void *)command, - .length = 1 + .frequency = CONFIG_HTS221_I2C_FREQUENCY, + .addr = priv->addr, + .flags = 0, + .buffer = (FAR void *)command, + .length = 1 }, { - .addr = priv->addr, - .flags = I2C_M_READ, - .buffer = value, - .length = 1 + .frequency = CONFIG_HTS221_I2C_FREQUENCY, + .addr = priv->addr, + .flags = I2C_M_READ, + .buffer = value, + .length = 1 } }; diff --git a/drivers/sensors/lis2dh.c b/drivers/sensors/lis2dh.c index f7a982f1518..67e0bf1185f 100644 --- a/drivers/sensors/lis2dh.c +++ b/drivers/sensors/lis2dh.c @@ -65,6 +65,10 @@ # define lis2dh_dbg(x, ...) sninfo(x, ##__VA_ARGS__) #endif +#ifndef CONFIG_LIS2DH_I2C_FREQUENCY +# define CONFIG_LIS2DH_I2C_FREQUENCY 400000 +#endif + #ifdef CONFIG_LIS2DH_DRIVER_SELFTEST # define LSB_AT_10BIT_RESOLUTION 4 # define LSB_AT_12BIT_RESOLUTION 1 @@ -1594,16 +1598,18 @@ static int lis2dh_access(FAR struct lis2dh_dev_s *dev, uint8_t subaddr, struct i2c_msg_s msgv[2] = { { - .addr = dev->addr, - .flags = 0, - .buffer = &subaddr, - .length = 1 + .frequency = CONFIG_LIS2DH_I2C_FREQUENCY, + .addr = dev->addr, + .flags = 0, + .buffer = &subaddr, + .length = 1 }, { - .addr = dev->addr, - .flags = flags, - .buffer = buf, - .length = length + .frequency = CONFIG_LIS2DH_I2C_FREQUENCY, + .addr = dev->addr, + .flags = flags, + .buffer = buf, + .length = length } }; diff --git a/drivers/sensors/lps25h.c b/drivers/sensors/lps25h.c index bd35f38043a..1eb762af0a7 100644 --- a/drivers/sensors/lps25h.c +++ b/drivers/sensors/lps25h.c @@ -58,6 +58,10 @@ # define lps25h_dbg(x, ...) sninfo(x, ##__VA_ARGS__) #endif +#ifndef CONFIG_LPS25H_I2C_FREQUENCY +# define CONFIG_LPS25H_I2C_FREQUENCY 400000 +#endif + #define LPS25H_PRESSURE_INTERNAL_DIVIDER 4096 /* 'AN4450 - Hardware and software guidelines for use of LPS25H pressure @@ -277,16 +281,18 @@ static int lps25h_write_reg8(struct lps25h_dev_s *dev, uint8_t reg_addr, struct i2c_msg_s msgv[2] = { { - .addr = dev->addr, - .flags = 0, - .buffer = ®_addr, - .length = 1 + .frequency = CONFIG_LPS25H_I2C_FREQUENCY, + .addr = dev->addr, + .flags = 0, + .buffer = ®_addr, + .length = 1 }, { - .addr = dev->addr, - .flags = I2C_M_NORESTART, - .buffer = (void *)&value, - .length = 1 + .frequency = CONFIG_LPS25H_I2C_FREQUENCY, + .addr = dev->addr, + .flags = I2C_M_NORESTART, + .buffer = (void *)&value, + .length = 1 } }; @@ -300,16 +306,18 @@ static int lps25h_read_reg8(FAR struct lps25h_dev_s *dev, struct i2c_msg_s msgv[2] = { { - .addr = dev->addr, - .flags = 0, - .buffer = reg_addr, - .length = 1 + .frequency = CONFIG_LPS25H_I2C_FREQUENCY, + .addr = dev->addr, + .flags = 0, + .buffer = reg_addr, + .length = 1 }, { - .addr = dev->addr, - .flags = I2C_M_READ, - .buffer = value, - .length = 1 + .frequency = CONFIG_LPS25H_I2C_FREQUENCY, + .addr = dev->addr, + .flags = I2C_M_READ, + .buffer = value, + .length = 1 } }; diff --git a/drivers/usbdev/usbmsc.h b/drivers/usbdev/usbmsc.h index 59dd5174dcc..daa3bcf4524 100644 --- a/drivers/usbdev/usbmsc.h +++ b/drivers/usbdev/usbmsc.h @@ -551,7 +551,7 @@ struct usb_strdesc_s; int usbmsc_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc); /************************************************************************************ - * Name: usbmsc_getepdesc + * Name: usbmsc_getdevdesc * * Description: * Return a pointer to the raw device descriptor diff --git a/drivers/usbmisc/Kconfig b/drivers/usbmisc/Kconfig index 68bd619ee3a..66690612833 100644 --- a/drivers/usbmisc/Kconfig +++ b/drivers/usbmisc/Kconfig @@ -14,6 +14,11 @@ config FUSB301 if FUSB301 +config FUSB301_I2C_FREQUENCY + int "FUSB301 I2C frequency" + default 400000 + range 1 400000 + config DEBUG_FUSB301 bool "Enable debug support for the FUSB301" default n diff --git a/drivers/usbmisc/fusb301.c b/drivers/usbmisc/fusb301.c index f24ae785582..d57d8a95ecc 100644 --- a/drivers/usbmisc/fusb301.c +++ b/drivers/usbmisc/fusb301.c @@ -63,6 +63,10 @@ # define fusb301_info(x, ...) uinfo(x, ##__VA_ARGS__) #endif +#ifndef CONFIG_FUSB301_I2C_FREQUENCY +# define CONFIG_FUSB301_I2C_FREQUENCY 400000 +#endif + /* Other macros */ #define FUSB301_I2C_RETRIES 10 @@ -146,15 +150,17 @@ static int fusb301_getreg(FAR struct fusb301_dev_s *priv, uint8_t reg) DEBUGASSERT(priv); - msg[0].addr = priv->addr; - msg[0].flags = 0; - msg[0].buffer = ® - msg[0].length = 1; + msg[0].frequency = CONFIG_FUSB301_I2C_FREQUENCY; + msg[0].addr = priv->addr; + msg[0].flags = 0; + msg[0].buffer = ® + msg[0].length = 1; - msg[1].addr = priv->addr; - msg[1].flags = I2C_M_READ; - msg[1].buffer = ®val; - msg[1].length = 1; + msg[1].frequency = CONFIG_FUSB301_I2C_FREQUENCY; + msg[1].addr = priv->addr; + msg[1].flags = I2C_M_READ; + msg[1].buffer = ®val; + msg[1].length = 1; /* Perform the transfer */ @@ -220,10 +226,11 @@ static int fusb301_putreg(FAR struct fusb301_dev_s *priv, uint8_t regaddr, /* Setup 8-bit FUSB301 address write message */ - msg.addr = priv->addr; - msg.flags = 0; - msg.buffer = txbuffer; - msg.length = 2; + msg.frequency = CONFIG_FUSB301_I2C_FREQUENCY; + msg.addr = priv->addr; + msg.flags = 0; + msg.buffer = txbuffer; + msg.length = 2; /* Perform the transfer */ diff --git a/fs/vfs/fs_fdopen.c b/fs/vfs/fs_fdopen.c index 43e00f184af..ebacc4c5ff9 100644 --- a/fs/vfs/fs_fdopen.c +++ b/fs/vfs/fs_fdopen.c @@ -221,11 +221,7 @@ FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb) { /* Zero the structure */ -#ifndef CONFIG_STDIO_DISABLE_BUFFERING memset(stream, 0, sizeof(FILE)); -#elif CONFIG_NUNGET_CHARS > 0 - stream->fs_nungotten = 0; -#endif #ifndef CONFIG_STDIO_DISABLE_BUFFERING /* Initialize the semaphore the manages access to the buffer */ diff --git a/include/nuttx/input/cypress_mbr3108.h b/include/nuttx/input/cypress_mbr3108.h new file mode 100644 index 00000000000..941de91cc02 --- /dev/null +++ b/include/nuttx/input/cypress_mbr3108.h @@ -0,0 +1,139 @@ +/**************************************************************************** + * include/nuttx/input/cypress_mbr3108.c + * + * Copyright (C) 2014 Haltian Ltd. All rights reserved. + * Author: Jussi Kivilinna + * + * 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 __INCLUDE_NUTTX_INPUT_CYPRESS_MBR3108_H_ +#define __INCLUDE_NUTTX_INPUT_CYPRESS_MBR3108_H_ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Sensor configuration for Cypress MBR3108 device */ + +begin_packed_struct struct mbr3108_sensor_conf_s +{ + uint8_t conf_data[128]; /* Sensor configuration, generated with EZ-Click. */ +} end_packed_struct; + +/* Debug configuration */ + +begin_packed_struct struct mbr3108_debug_conf_s +{ + bool debug_mode; /* Configure to debug mode if 'true'. */ + uint8_t debug_sensor_id; /* Sensor to read in debug mode. */ +} end_packed_struct; + +/* Write commands to MBR3108 driver. */ + +begin_packed_struct enum mbr3108_cmd_e +{ + CYPRESS_MBR3108_CMD_SENSOR_CONF = -3, + CYPRESS_MBR3108_CMD_DEBUG_CONF, + CYPRESS_MBR3108_CMD_CLEAR_LATCHED, +} end_packed_struct; + +/* CYPRESS_MBR3108_CMD_SENSOR_CONF command structure. Used to reconfigure + * chip with new configuration generated using EZ-Click tool. */ + +begin_packed_struct struct mbr3108_cmd_sensor_conf_s +{ + enum mbr3108_cmd_e id; + struct mbr3108_sensor_conf_s conf; +} end_packed_struct; + +/* CYPRESS_MBR3108_CMD_DEBUG_CONF command structure. Use to enable debug + * output from chip/sensor, see 'struct mbr3108_sensor_data_s'. */ + +begin_packed_struct struct mbr3108_cmd_debug_conf_s +{ + enum mbr3108_cmd_e id; + struct mbr3108_debug_conf_s conf; +} end_packed_struct; + +/* Sensor status output */ + +begin_packed_struct struct mbr3108_sensor_status_s +{ + unsigned int button:8; /* MBR3108 has maximum of 8 button sensors + * configurable. + * Each bit in this field indicate if + * corresponding button is pressed. */ + unsigned int latched_button:8; + unsigned int proximity:2; /* MBR3108 has maximum of 2 proximity + * sensors configurable. */ + unsigned int latched_proximity:2; +} end_packed_struct; + +/* Sensor debug data output */ + +begin_packed_struct struct mbr3108_sensor_debug_s +{ + uint8_t sensor_total_capacitance; + uint16_t sensor_diff_counts; + uint16_t sensor_baseline; + uint16_t sensor_raw_counts; + uint16_t sensor_average_counts; +} end_packed_struct; + +/* Board configuration */ + +struct mbr3108_board_s +{ + int (*irq_attach) (FAR struct mbr3108_board_s *state, xcpt_t isr, FAR void *arg); + void (*irq_enable) (FAR struct mbr3108_board_s *state, bool enable); + int (*set_power) (FAR struct mbr3108_board_s *state, bool on); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Device registration */ + +int cypress_mbr3108_register(FAR const char *devpath, + FAR struct i2c_master_s *dev, + uint8_t i2c_devaddr, + struct mbr3108_board_s *board_config, + const struct mbr3108_sensor_conf_s *sensor_conf); + +#endif /* __INCLUDE_NUTTX_INPUT_CYPRESS_MBR3108_H_ */ diff --git a/include/nuttx/spi/spi.h b/include/nuttx/spi/spi.h index c4757bb9754..08b28e26255 100644 --- a/include/nuttx/spi/spi.h +++ b/include/nuttx/spi/spi.h @@ -320,7 +320,7 @@ * ****************************************************************************/ -#define SPI_SEND(d,wd) ((d)->ops->send(d,(uint16_t)wd)) +#define SPI_SEND(d,wd) ((d)->ops->send(d,(uint16_t)(wd))) /**************************************************************************** * Name: SPI_SNDBLOCK diff --git a/include/nuttx/usb/usbmsc.h b/include/nuttx/usb/usbmsc.h index 2968b0a1b0e..bf248e9538c 100644 --- a/include/nuttx/usb/usbmsc.h +++ b/include/nuttx/usb/usbmsc.h @@ -71,7 +71,7 @@ * Public Types ************************************************************************************/ - /************************************************************************************ +/************************************************************************************ * Public Data ************************************************************************************/ diff --git a/libc/string/lib_vikmemcpy.c b/libc/string/lib_vikmemcpy.c index 41ab3ecf371..598672aac1c 100644 --- a/libc/string/lib_vikmemcpy.c +++ b/libc/string/lib_vikmemcpy.c @@ -240,9 +240,9 @@ #define COPY_SHIFT(shift) \ { \ - UIntN* dstN = (UIntN*)((((UIntN)dst8) PRE_LOOP_ADJUST) & \ + UIntN* dstN = (UIntN*)((((uintptr_t)dst8) PRE_LOOP_ADJUST) & \ ~(TYPE_WIDTH - 1)); \ - UIntN* srcN = (UIntN*)((((UIntN)src8) PRE_LOOP_ADJUST) & \ + UIntN* srcN = (UIntN*)((((uintptr_t)src8) PRE_LOOP_ADJUST) & \ ~(TYPE_WIDTH - 1)); \ size_t length = count / TYPE_WIDTH; \ UIntN srcWord = INC_VAL(srcN); \ @@ -324,13 +324,13 @@ FAR void *memcpy(FAR void *dest, FAR const void *src, size_t count) START_VAL(dst8); START_VAL(src8); - while (((UIntN)dst8 & (TYPE_WIDTH - 1)) != WHILE_DEST_BREAK) + while (((uintptr_t)dst8 & (TYPE_WIDTH - 1)) != WHILE_DEST_BREAK) { INC_VAL(dst8) = INC_VAL(src8); count--; } - switch ((((UIntN)src8) PRE_SWITCH_ADJUST) & (TYPE_WIDTH - 1)) + switch ((((uintptr_t)src8) PRE_SWITCH_ADJUST) & (TYPE_WIDTH - 1)) { case 0: COPY_NO_SHIFT(); break; case 1: COPY_SHIFT(1); break; diff --git a/sched/pthread/pthread_mutex.c b/sched/pthread/pthread_mutex.c index 13dde1a53d1..5a75481a51f 100644 --- a/sched/pthread/pthread_mutex.c +++ b/sched/pthread/pthread_mutex.c @@ -58,7 +58,7 @@ * Name: pthread_mutex_add * * Description: - * Add the mutex to the list of mutexes held by this thread. + * Add the mutex to the list of mutexes held by this pthread. * * Parameters: * mutex - The mux to be locked @@ -70,17 +70,89 @@ static void pthread_mutex_add(FAR struct pthread_mutex_s *mutex) { - FAR struct pthread_tcb_s *rtcb = (FAR struct pthread_tcb_s *)this_task(); - irqstate_t flags; + FAR struct tcb_s *rtcb = this_task(); DEBUGASSERT(mutex->flink == NULL); - /* Add the mutex to the list of mutexes held by this task */ + /* Check if this is a pthread. The main thread may also lock and unlock + * mutexes. The main thread, however, does not participate in the mutex + * consistency logic. Presumably, when the main thread exits, all of the + * child pthreads will also terminate. + * + * REVISIT: NuttX does not support that behavior at present; child pthreads + * will persist after the main thread exits. + */ - flags = enter_critical_section(); - mutex->flink = rtcb->mhead; - rtcb->mhead = mutex; - leave_critical_section(flags); + if ((rtcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) + { + FAR struct pthread_tcb_s *ptcb = (FAR struct pthread_tcb_s *)rtcb; + irqstate_t flags; + + /* Add the mutex to the list of mutexes held by this pthread */ + + flags = enter_critical_section(); + mutex->flink = ptcb->mhead; + ptcb->mhead = mutex; + leave_critical_section(flags); + } +} + +/**************************************************************************** + * Name: pthread_mutex_remove + * + * Description: + * Remove the mutex to the list of mutexes held by this pthread. + * + * Parameters: + * mutex - The mux to be locked + * + * Return Value: + * None + * + ****************************************************************************/ + +static void pthread_mutex_remove(FAR struct pthread_mutex_s *mutex) +{ + FAR struct tcb_s *rtcb = this_task(); + + /* Check if this is a pthread. The main thread may also lock and unlock + * mutexes. The main thread, however, does not participate in the mutex + * consistency logic. + */ + + if ((rtcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) + { + FAR struct pthread_tcb_s *ptcb = (FAR struct pthread_tcb_s *)rtcb; + FAR struct pthread_mutex_s *curr; + FAR struct pthread_mutex_s *prev; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Remove the mutex from the list of mutexes held by this task */ + + for (prev = NULL, curr = ptcb->mhead; + curr != NULL && curr != mutex; + prev = curr, curr = curr->flink); + + DEBUGASSERT(curr == mutex); + + /* Remove the mutex from the list. prev == NULL means that the mutex + * to be removed is at the head of the list. + */ + + if (prev == NULL) + { + ptcb->mhead = mutex->flink; + } + else + { + prev->flink = mutex->flink; + } + + mutex->flink = NULL; + leave_critical_section(flags); + } } /**************************************************************************** @@ -233,8 +305,6 @@ int pthread_mutex_trytake(FAR struct pthread_mutex_s *mutex) int pthread_mutex_give(FAR struct pthread_mutex_s *mutex) { - FAR struct pthread_mutex_s *curr; - FAR struct pthread_mutex_s *prev; int ret = EINVAL; /* Verify input parameters */ @@ -242,34 +312,9 @@ int pthread_mutex_give(FAR struct pthread_mutex_s *mutex) DEBUGASSERT(mutex != NULL); if (mutex != NULL) { - FAR struct pthread_tcb_s *rtcb = (FAR struct pthread_tcb_s *)this_task(); - irqstate_t flags; - - flags = enter_critical_section(); - /* Remove the mutex from the list of mutexes held by this task */ - for (prev = NULL, curr = rtcb->mhead; - curr != NULL && curr != mutex; - prev = curr, curr = curr->flink); - - DEBUGASSERT(curr == mutex); - - /* Remove the mutex from the list. prev == NULL means that the mutex - * to be removed is at the head of the list. - */ - - if (prev == NULL) - { - rtcb->mhead = mutex->flink; - } - else - { - prev->flink = mutex->flink; - } - - mutex->flink = NULL; - leave_critical_section(flags); + pthread_mutex_remove(mutex); /* Now release the underlying semaphore */ @@ -300,7 +345,7 @@ int pthread_mutex_give(FAR struct pthread_mutex_s *mutex) #ifdef CONFIG_CANCELLATION_POINTS uint16_t pthread_disable_cancel(void) { - FAR struct pthread_tcb_s *tcb = (FAR struct pthread_tcb_s *)this_task(); + FAR struct tcb_s *tcb = this_task(); irqstate_t flags; uint16_t old; @@ -309,15 +354,15 @@ uint16_t pthread_disable_cancel(void) */ flags = enter_critical_section(); - old = tcb->cmn.flags & (TCB_FLAG_CANCEL_PENDING | TCB_FLAG_NONCANCELABLE); - tcb->cmn.flags &= ~(TCB_FLAG_CANCEL_PENDING | TCB_FLAG_NONCANCELABLE); + old = tcb->flags & (TCB_FLAG_CANCEL_PENDING | TCB_FLAG_NONCANCELABLE); + tcb->flags &= ~(TCB_FLAG_CANCEL_PENDING | TCB_FLAG_NONCANCELABLE); leave_critical_section(flags); return old; } void pthread_enable_cancel(uint16_t cancelflags) { - FAR struct pthread_tcb_s *tcb = (FAR struct pthread_tcb_s *)this_task(); + FAR struct tcb_s *tcb = this_task(); irqstate_t flags; /* We need perform the following operations from within a critical section @@ -325,7 +370,7 @@ void pthread_enable_cancel(uint16_t cancelflags) */ flags = enter_critical_section(); - tcb->cmn.flags |= cancelflags; + tcb->flags |= cancelflags; /* What should we do if there is a pending cancellation? * @@ -337,8 +382,8 @@ void pthread_enable_cancel(uint16_t cancelflags) * then we need to terminate now by simply calling pthread_exit(). */ - if ((tcb->cmn.flags & TCB_FLAG_CANCEL_DEFERRED) == 0 && - (tcb->cmn.flags & TCB_FLAG_CANCEL_PENDING) != 0) + if ((tcb->flags & TCB_FLAG_CANCEL_DEFERRED) == 0 && + (tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0) { pthread_exit(NULL); }