diff --git a/ChangeLog b/ChangeLog index 06eba68671d..8f3cefa8ffc 100755 --- a/ChangeLog +++ b/ChangeLog @@ -12295,3 +12295,83 @@ Matthias Renner (2016-07-08). * drivers/pipe: Add missing configuration for pipe ring buffer size. From Frank Benkert (2016-07-08). + * STM32L4: Fix incorrect clock setup for LPTIM1. From ziggurat29 + (2016-07-08). + * nucleo-l476rg and stm32lf76vg-disco: Define timer clock frequencies on + STM32L4-based boards. From ziggurat29 (2016-07-08). + * STM32L4: Add support for tickless OS, and incidentally timers, pwm, + oneshot, free-running.... From ziggurat29 (2016-07-08). + * SAM3/4 I2C: Fix reversed logic in twi_startmessage(). From Wolfgang + Reissnegger (2016-07-09). + * VFS ioctl(). Per comments from David Sidrane, file_ioctl() should not + return succeed if the ioctl method is not supported. It probably + should return ENOTTY in that case (2016-07-09). + * libm: This change should significantly improve the performance of + single precision floating point math library functions. The vast + majority of changes have to do with preventing the compiler from + needlessly promoting floats to doubles, performing the calculation + with doubles, only to demote the result to float. These changes only + affect the math lib functions that return float. From David Alessio + (2016-07-11). + * STM32F4 Discovery: Add FPU support for ostest for the STM32F4Discovery + platform. From David Alessio (2016-07-11). + * Build system: Remove the includes/apps link to apps/include. It is + no longer used. From Sebastien Lorquet (2016-07-11). + * printf(): If there are no streams, let printf() fall back to use + syslog() for output (2016-07-11). + * Qemu-i486: Fix qemu-i486/ostest/Make.defs test for M32. From Heath + Petersen (2016-07-12). + * UART 16550: Handle when CONFIG_SERIAL_UART_ARCH_IOCTL is not enabled. + From Heath Petersen (2016-07-12). + * Kinetis Ethernet: Add support for the KSZ8081 PHY (2016-07-12). + * SST26 Driver: Before accessing the sst26 flash, the "Global Unlock" + command must me executed, which I do in the sst26 driver. BUT re- + reading the datasheet, the WREN instruction is required to enable the + execution of this command. This was not done. I have no idea how the + driver currently works except by chance. The writes should never + happen at all, the flash is half-enabled! From Sebastien Lorquet + (2016-07-12). + * Freedom K64F: Add a networking NSH configuration. (2016-07-12). + * N25Qxx Driver: Alter the notion of 'blocksize' to be equivalent to + 'flash write page size' in order to align with assumptions in the + smartfs driver (at least, maybe other things do as well). Correct a + bug that was previously masked by having blocksize=eraseblocksize + which would cause buffer overflows and delicious hardfaults. Trivial + spelling changes in comments, etc. From ziggurat29 (2016-07-12). + * STM32L476 Discovery: Update stm32l476 disco to include init code for + smartfs and nxffs for cases where those fs are included in build. + From ziggurat29 (2016-07-12). + * Kinetis Ethernet and Freedom-K64F: Freedcom-K64F PHY address was + wrong. Modified Ethernet driver to try all PHY addresses and then + only fail if the driver cannot find a usable PHY address. MDIO pin + must have an internal pull-up on the Freedom-K64F (2016-07-12). + * Kinetis Ethernet: Add support for CONFIG_NET_NOINTS (2016-07-12). + * SmartFS: Fix a 32-byte memory leak. From Ken Pettit (2016-07-12). + * Freedom-K64F: SDHC is now enabled in the nsh configuration (but does + not work)Add hooks for automounter; Change NSH configuration to use + Windows (2016-07-13). + * SAMV7 USBHS Device: This change solves a problem which causes data + loss while sending data via USB. This problem is caused by an incorrect + handling of the endpoint state in the USB driver sam_usbdevhs. This + leads under some circumstances to situations in which an DMA transfer + is setup while a previous DMA transfer is currently active. Amongst + other things I introduced the new endpoint state USBHS_EPSTATE_SENDING_DMA + for the fix. To reproduce the problem, I used a program which send as + many data as possible via a CDC/ACM device and verified the received + data on the PC. From Stefan Kolb (2016-07-13). + * STM32: Fix bug in oneshot timer. From Max Neklyudov (2016-07-13). + * STM32L4: Port foward bugfix from stm32 of oneshot timer. From + ziggurat29 (2016-07-13). + * STM32 and EFM32: I'm using syslog through ITM. In this case + syslog_channel function is call before RAM initialisation in + stm32_clockconfig. But syslog channel uses a global variable that is + reset to default by the RAM initialization. From Pierre-noel + Bouteville (2016-07-14). + * LPC43xx SPIFI: If CONFIG_SPIFI_SECTOR512 undefined, lpc43_bwrite + doesn't do actual write (probably copy/paste errors). Still not sure + about current state of lpc43_spifi implementation, but for me NXFFS + works with this patch. From Vytautas Lukenskas (2016-07-14). + * SMART MTD layer: Fixes freesector logic error when sectorsPerBlk=256, + adds DEBUGASSERT for invalid geometry and additional memory debug + logic. Also fixes the dangling pointer on error bug. From Ken + Pettit (2016-07-14). diff --git a/arch/arm/src/efm32/efm32_clockconfig.c b/arch/arm/src/efm32/efm32_clockconfig.c index 5ecdf03c12f..aeef784326b 100644 --- a/arch/arm/src/efm32/efm32_clockconfig.c +++ b/arch/arm/src/efm32/efm32_clockconfig.c @@ -909,9 +909,6 @@ static inline void efm32_itm_syslog(void) efm32_enable_auxhfrco(); - /* Then perform ARMv7-M ITM SYSLOG initialization */ - - itm_syslog_initialize(); } #else # define efm32_itm_syslog() diff --git a/arch/arm/src/efm32/efm32_start.c b/arch/arm/src/efm32/efm32_start.c index f62e1461d51..59c45afaa32 100644 --- a/arch/arm/src/efm32/efm32_start.c +++ b/arch/arm/src/efm32/efm32_start.c @@ -275,6 +275,12 @@ void __start(void) showprogress('C'); +#ifdef CONFIG_ARMV7M_ITMSYSLOG + /* Perform ARMv7-M ITM SYSLOG initialization */ + + itm_syslog_initialize(); +#endif + /* Perform early serial initialization */ up_earlyserialinit(); diff --git a/arch/arm/src/kinetis/Kconfig b/arch/arm/src/kinetis/Kconfig index 6a0c0367657..4be634107b2 100644 --- a/arch/arm/src/kinetis/Kconfig +++ b/arch/arm/src/kinetis/Kconfig @@ -615,13 +615,6 @@ config KINETIS_SD4BIT_FREQ Frequency to use for transferring data to/from an SD card using all four data lines. endif - -config KINETIS_SDHC_DMAPRIO - int "SDHC DMA priority" - depends on SDIO_DMA - ---help--- - SDHC DMA priority - endmenu # Kinetis SDHC Configuration menu "Kinetis UART Configuration" diff --git a/arch/arm/src/kinetis/kinetis_enet.c b/arch/arm/src/kinetis/kinetis_enet.c index 6c30bac4158..dc0be25e164 100644 --- a/arch/arm/src/kinetis/kinetis_enet.c +++ b/arch/arm/src/kinetis/kinetis_enet.c @@ -1840,7 +1840,7 @@ static inline int kinetis_initphy(struct kinetis_driver_s *priv) phydata = 0xffff; ret = kinetis_readmii(priv, phyaddr, MII_PHYID1, &phydata); } - while (ret >= 0 && phydata == 0xffff && ++retries < 3); + while ((ret < 0 || phydata == 0xffff) && ++retries < 3); /* If we successfully read anything then break out, using this PHY address */ diff --git a/arch/arm/src/kinetis/kinetis_sdhc.c b/arch/arm/src/kinetis/kinetis_sdhc.c index afc85f59892..0f1197b6e7b 100644 --- a/arch/arm/src/kinetis/kinetis_sdhc.c +++ b/arch/arm/src/kinetis/kinetis_sdhc.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/kinetis/kinetis_sdhc.c * - * Copyright (C) 2011-2012, 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2011-2012, 2014, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -85,10 +85,6 @@ # define CONFIG_KINETIS_SDHC_PRIO NVIC_SYSH_PRIORITY_DEFAULT #endif -#ifndef CONFIG_KINETIS_SDHC_DMAPRIO -# define CONFIG_KINETIS_SDHC_DMAPRIO DMA_CCR_PRIMED -#endif - #ifndef CONFIG_DEBUG_MEMCARD_INFO # undef CONFIG_SDIO_XFRDEBUG #endif diff --git a/arch/arm/src/kinetis/kinetis_usbdev.c b/arch/arm/src/kinetis/kinetis_usbdev.c index d8d9512cabf..231fc014303 100644 --- a/arch/arm/src/kinetis/kinetis_usbdev.c +++ b/arch/arm/src/kinetis/kinetis_usbdev.c @@ -2738,7 +2738,7 @@ static int khci_interrupt(int irq, void *context) #ifdef CONFIG_USBOTG /* Session Request Protocol (SRP) Time Out Check */ - /* if USB OTG SRP is ready */ + /* Check if USB OTG SRP is ready */ # warning "Missing logic" { /* Check if the 1 millisecond timer has expired */ @@ -2960,6 +2960,8 @@ x } } + UNUSED(otgir); /* May not be used, depending on above conditional logic */ + /* Clear the pending USB interrupt. Goto is used in the above to assure * that all interrupt exists pass through this logic. */ diff --git a/arch/arm/src/lpc43xx/lpc43_spifi.c b/arch/arm/src/lpc43xx/lpc43_spifi.c index 71920dc4775..57349370c02 100644 --- a/arch/arm/src/lpc43xx/lpc43_spifi.c +++ b/arch/arm/src/lpc43xx/lpc43_spifi.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/lpc43/lpc43_spifi.c * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -779,12 +779,13 @@ static ssize_t lpc43_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t lpc43_cachewrite(priv, buffer, startblock, nblocks); lpc43_dumpbuffer(__func__, buffer, nblocks << SPIFI_512SHIFT) - return nblocks; + return (ssize_t)nblocks; #else FAR struct lpc43_dev_s *priv = (FAR struct lpc43_dev_s *)dev; FAR uint8_t *dest; + int ret; finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); @@ -792,19 +793,17 @@ static ssize_t lpc43_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t dest = SPIFI_BASE + (startblock << SPIFI_BLKSHIFT); -#if defined(CONFIG_SPIFI_SECTOR512) /* Write all of the erase blocks to FLASH */ - ret = lpc43_pagewrite(priv, dest, buffer, nblocks << SPIFI_512SHIFT); + ret = lpc43_pagewrite(priv, dest, buffer, nblocks << SPIFI_BLKSHIFT); if (ret < 0) { ferr("ERROR: lpc43_pagewrite failed: %d\n", ret); return ret; } -#endif - lpc43_dumpbuffer(__func__, buffer, nblocks << SPIFI_BLKSHIFT) - return nblocks; + lpc43_dumpbuffer(__func__, buffer, nblocks << SPIFI_BLKSHIFT); + return (ssize_t)nblocks; #endif } diff --git a/arch/arm/src/sam34/chip/sam_tc.h b/arch/arm/src/sam34/chip/sam_tc.h index bb1bd15f0c1..e5951fcdc9a 100644 --- a/arch/arm/src/sam34/chip/sam_tc.h +++ b/arch/arm/src/sam34/chip/sam_tc.h @@ -2,7 +2,7 @@ * arch/arm/src/sam34/chip/sam_tc.h * Timer Counter (TC) definitions for the SAM3U, SAM4E, and SAM4S * - * Copyright (C) 2009, 2013-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2009, 2013-2014, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -537,16 +537,10 @@ # define TC_BMR_TC1XC1S_TIOA2 (3 << TC_BMR_TC1XC1S_SHIFT) #define TC_BMR_TC2XC2S_SHIFT (4) /* Bits 4-5: External Clock Signal 2 Selection */ #define TC_BMR_TC2XC2S_MASK (3 << TC_BMR_TC2XC2S_SHIFT) -#if defined(CONFIG_ARCH_CHIP_SAM4s) || defined(CONFIG_ARCH_CHIP_SAM4E) -# define TC_BMR_TC2XC2S_TCLK2 (0 << TC_BMR_TC2XC2S_SHIFT) -# define TC_BMR_TC2XC2S_TIOA1 (2 << TC_BMR_TC2XC2S_SHIFT) -# define TC_BMR_TC2XC2S_TIOA2 (3 << TC_BMR_TC2XC2S_SHIFT) -#else # define TC_BMR_TC2XC2S_TCLK2 (0 << TC_BMR_TC2XC2S_SHIFT) # define TC_BMR_TC2XC2S_NONE (1 << TC_BMR_TC2XC2S_SHIFT) # define TC_BMR_TC2XC2S_TIOA0 (2 << TC_BMR_TC2XC2S_SHIFT) # define TC_BMR_TC2XC2S_TIOA1 (3 << TC_BMR_TC2XC2S_SHIFT) -#endif #define TC_BMR_QDEN (1 << 8) /* Bit 8: Quadrature Decoder Enabled */ #define TC_BMR_POSEN (1 << 9) /* Bit 9: Position Enabled */ #define TC_BMR_SPEEDEN (1 << 10) /* Bit 10: Speed Enabled */ diff --git a/arch/arm/src/samv7/sam_usbdevhs.c b/arch/arm/src/samv7/sam_usbdevhs.c index 07bfe1d2d4b..087db9c0e1a 100644 --- a/arch/arm/src/samv7/sam_usbdevhs.c +++ b/arch/arm/src/samv7/sam_usbdevhs.c @@ -301,6 +301,7 @@ enum sam_epstate_e USBHS_EPSTATE_STALLED, /* Endpoint is stalled */ USBHS_EPSTATE_IDLE, /* Endpoint is idle (i.e. ready for transmission) */ USBHS_EPSTATE_SENDING, /* Endpoint is sending data */ + USBHS_EPSTATE_SENDING_DMA, /* Endpoint is sending data via DMA */ USBHS_EPSTATE_NBUSYBK, /* Endpoint DMA complete, waiting for NBUSYBK==0 */ USBHS_EPSTATE_RECEIVING, /* Endpoint is receiving data */ /* --- Endpoint 0 Only --- */ @@ -1006,7 +1007,7 @@ static void sam_dma_wrsetup(struct sam_usbdev_s *priv, struct sam_ep_s *privep, /* Switch to the sending state */ - privep->epstate = USBHS_EPSTATE_SENDING; + privep->epstate = USBHS_EPSTATE_SENDING_DMA; privreq->inflight = 0; /* Get the endpoint number */ @@ -1211,16 +1212,23 @@ static void sam_req_complete(struct sam_ep_s *privep, int16_t result) privreq->req.result = result; - /* Callback to the request completion handler */ - - privreq->flink = NULL; - privreq->req.callback(&privep->ep, &privreq->req); - - /* Reset the endpoint state and restore the stalled indication */ + /* Reset the endpoint state and restore the stalled indication. + * + * At least the USB class CDC/ACM calls the function sam_ep_submit within + * the callback. This function uses sam_req_write or sam_req_read to process + * the request, both functions can change the state. Therefore it is verry + * important to set the state to USBHS_EPSTATE_IDLE before the callback is + * called. + */ privep->epstate = USBHS_EPSTATE_IDLE; privep->zlpneeded = false; privep->zlpsent = false; + + /* Callback to the request completion handler */ + + privreq->flink = NULL; + privreq->req.callback(&privep->ep, &privreq->req); } } @@ -2497,7 +2505,8 @@ static void sam_dma_interrupt(struct sam_usbdev_s *priv, int epno) /* Were we sending? Or receiving? */ - if (privep->epstate == USBHS_EPSTATE_SENDING) + if (privep->epstate == USBHS_EPSTATE_SENDING || + privep->epstate == USBHS_EPSTATE_SENDING_DMA) { uint32_t nbusybk; uint32_t byct; @@ -2923,7 +2932,8 @@ static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno) */ if (privep->epstate == USBHS_EPSTATE_RECEIVING || - privep->epstate == USBHS_EPSTATE_SENDING) + privep->epstate == USBHS_EPSTATE_SENDING || + privep->epstate == USBHS_EPSTATE_SENDING_DMA) { sam_req_complete(privep, -EPROTO); } diff --git a/arch/arm/src/stm32/stm32_oneshot.c b/arch/arm/src/stm32/stm32_oneshot.c index 8f5e89df622..a47307e7212 100644 --- a/arch/arm/src/stm32/stm32_oneshot.c +++ b/arch/arm/src/stm32/stm32_oneshot.c @@ -95,9 +95,10 @@ static int stm32_oneshot_handler(int irq, void *context) * Disable the TC now and disable any further interrupts. */ + STM32_TIM_SETISR(oneshot->tch, NULL, 0); + STM32_TIM_DISABLEINT(oneshot->tch, 0); STM32_TIM_SETMODE(oneshot->tch, STM32_TIM_MODE_DISABLED); STM32_TIM_ACKINT(oneshot->tch, 0); - STM32_TIM_DISABLEINT(oneshot->tch, 0); /* The timer is no longer running */ @@ -351,6 +352,7 @@ int stm32_oneshot_cancel(struct stm32_oneshot_s *oneshot, /* Now we can disable the interrupt and stop the timer. */ STM32_TIM_DISABLEINT(oneshot->tch, 0); + STM32_TIM_SETISR(oneshot->tch, NULL, 0); STM32_TIM_SETMODE(oneshot->tch, STM32_TIM_MODE_DISABLED); oneshot->running = false; diff --git a/arch/arm/src/stm32/stm32_start.c b/arch/arm/src/stm32/stm32_start.c index 480d5f58b46..ac16478b337 100644 --- a/arch/arm/src/stm32/stm32_start.c +++ b/arch/arm/src/stm32/stm32_start.c @@ -282,6 +282,12 @@ void __start(void) showprogress('C'); +#ifdef CONFIG_ARMV7M_ITMSYSLOG + /* Perform ARMv7-M ITM SYSLOG initialization */ + + itm_syslog_initialize(); +#endif + /* Perform early serial initialization */ #ifdef USE_EARLYSERIALINIT diff --git a/arch/arm/src/stm32/stm32f40xxx_rcc.c b/arch/arm/src/stm32/stm32f40xxx_rcc.c index 3d259ec5c39..347d8a3d62b 100644 --- a/arch/arm/src/stm32/stm32f40xxx_rcc.c +++ b/arch/arm/src/stm32/stm32f40xxx_rcc.c @@ -919,7 +919,6 @@ static inline void rcc_itm_syslog(void) modifyreg32(STM32_DBGMCU_CR, DBGMCU_CR_TRACEMODE_MASK, DBGMCU_CR_ASYNCH | DBGMCU_CR_TRACEIOEN); - itm_syslog_initialize(); } #else # define rcc_itm_syslog() diff --git a/arch/arm/src/stm32l4/stm32l4_oneshot.c b/arch/arm/src/stm32l4/stm32l4_oneshot.c index 6c8027e15cb..073ca62d423 100644 --- a/arch/arm/src/stm32l4/stm32l4_oneshot.c +++ b/arch/arm/src/stm32l4/stm32l4_oneshot.c @@ -96,9 +96,10 @@ static int stm32l4_oneshot_handler(int irq, FAR void *context) * Disable the TC now and disable any further interrupts. */ + STM32L4_TIM_SETISR(oneshot->tch, NULL, 0); + STM32L4_TIM_DISABLEINT(oneshot->tch, 0); STM32L4_TIM_SETMODE(oneshot->tch, STM32L4_TIM_MODE_DISABLED); STM32L4_TIM_ACKINT(oneshot->tch, 0); - STM32L4_TIM_DISABLEINT(oneshot->tch, 0); /* The timer is no longer running */ @@ -353,6 +354,7 @@ int stm32l4_oneshot_cancel(FAR struct stm32l4_oneshot_s *oneshot, /* Now we can disable the interrupt and stop the timer. */ STM32L4_TIM_DISABLEINT(oneshot->tch, 0); + STM32L4_TIM_SETISR(oneshot->tch, NULL, 0); STM32L4_TIM_SETMODE(oneshot->tch, STM32L4_TIM_MODE_DISABLED); oneshot->running = false; diff --git a/arch/arm/src/stm32l4/stm32l4_serial.c b/arch/arm/src/stm32l4/stm32l4_serial.c index 548d1e19571..e85e73a3e35 100644 --- a/arch/arm/src/stm32l4/stm32l4_serial.c +++ b/arch/arm/src/stm32l4/stm32l4_serial.c @@ -139,65 +139,27 @@ /* DMA priority */ # ifndef CONFIG_USART_DMAPRIO -# if defined(CONFIG_STM32L4_STM32L15XX) || defined(CONFIG_STM32L4_STM32F10XX) || \ - defined(CONFIG_STM32L4_STM32F30XX) || defined(CONFIG_STM32L4_STM32F37XX) -# define CONFIG_USART_DMAPRIO DMA_CCR_PRIMED -# elif defined(CONFIG_STM32L4_STM32F20XX) || defined(CONFIG_STM32L4_STM32F40XX) -# define CONFIG_USART_DMAPRIO DMA_SCR_PRIMED -# else -# error "Unknown STM32 DMA" -# endif +# define CONFIG_USART_DMAPRIO DMA_CCR_PRIMED # endif -# if defined(CONFIG_STM32L4_STM32L15XX) || defined(CONFIG_STM32L4_STM32F10XX) || \ - defined(CONFIG_STM32L4_STM32F30XX) || defined(CONFIG_STM32L4_STM32F37XX) -# if (CONFIG_USART_DMAPRIO & ~DMA_CCR_PL_MASK) != 0 -# error "Illegal value for CONFIG_USART_DMAPRIO" -# endif -# elif defined(CONFIG_STM32L4_STM32F20XX) || defined(CONFIG_STM32L4_STM32F40XX) -# if (CONFIG_USART_DMAPRIO & ~DMA_SCR_PL_MASK) != 0 -# error "Illegal value for CONFIG_USART_DMAPRIO" -# endif -# else -# error "Unknown STM32 DMA" +# if (CONFIG_USART_DMAPRIO & ~DMA_CCR_PL_MASK) != 0 +# error "Illegal value for CONFIG_USART_DMAPRIO" # endif /* DMA control words */ -# if defined(CONFIG_STM32L4_STM32F20XX) || defined(CONFIG_STM32L4_STM32F40XX) -# define SERIAL_DMA_CONTROL_WORD \ - (DMA_SCR_DIR_P2M | \ - DMA_SCR_CIRC | \ - DMA_SCR_MINC | \ - DMA_SCR_PSIZE_8BITS | \ - DMA_SCR_MSIZE_8BITS | \ - CONFIG_USART_DMAPRIO | \ - DMA_SCR_PBURST_SINGLE | \ - DMA_SCR_MBURST_SINGLE) -# ifdef CONFIG_SERIAL_IFLOWCONTROL -# define SERIAL_DMA_IFLOW_CONTROL_WORD \ - (DMA_SCR_DIR_P2M | \ - DMA_SCR_MINC | \ - DMA_SCR_PSIZE_8BITS | \ - DMA_SCR_MSIZE_8BITS | \ - CONFIG_USART_DMAPRIO | \ - DMA_SCR_PBURST_SINGLE | \ - DMA_SCR_MBURST_SINGLE) -# endif -# else -# define SERIAL_DMA_CONTROL_WORD \ - (DMA_CCR_CIRC | \ - DMA_CCR_MINC | \ - DMA_CCR_PSIZE_8BITS | \ - DMA_CCR_MSIZE_8BITS | \ - CONFIG_USART_DMAPRIO) -# ifdef CONFIG_SERIAL_IFLOWCONTROL -# define SERIAL_DMA_IFLOW_CONTROL_WORD \ - (DMA_CCR_MINC | \ - DMA_CCR_PSIZE_8BITS | \ - DMA_CCR_MSIZE_8BITS | \ - CONFIG_USART_DMAPRIO) -# endif -# endif +# define SERIAL_DMA_CONTROL_WORD \ + (DMA_CCR_CIRC | \ + DMA_CCR_MINC | \ + DMA_CCR_PSIZE_8BITS | \ + DMA_CCR_MSIZE_8BITS | \ + CONFIG_USART_DMAPRIO) +# ifdef CONFIG_SERIAL_IFLOWCONTROL +# define SERIAL_DMA_IFLOW_CONTROL_WORD \ + (DMA_CCR_MINC | \ + DMA_CCR_PSIZE_8BITS | \ + DMA_CCR_MSIZE_8BITS | \ + CONFIG_USART_DMAPRIO) +# endif #endif @@ -1590,12 +1552,11 @@ static int up_interrupt_common(FAR struct stm32l4_serial_s *priv) static int stm32l4serial_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { -#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT) \ - || defined(CONFIG_STM32F7_SERIALBRK_BSDCOMPAT) +#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT) FAR struct inode *inode = filep->f_inode; FAR struct uart_dev_s *dev = inode->i_private; #endif -#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_STM32F7_SERIALBRK_BSDCOMPAT) +#if defined(CONFIG_SERIAL_TERMIOS) FAR struct stm32l4_serial_s *priv = (FAR struct stm32l4_serial_s *)dev->priv; #endif int ret = OK; @@ -1619,6 +1580,7 @@ static int stm32l4serial_ioctl(FAR struct file *filep, int cmd, #endif #ifdef CONFIG_STM32L4_USART_SINGLEWIRE +#warning please review the potential use of ALTERNATE_FUNCTION_OPENDRAIN case TIOCSSINGLEWIRE: { /* Change the TX port to be open-drain/push-pull and enable/disable @@ -1627,18 +1589,6 @@ static int stm32l4serial_ioctl(FAR struct file *filep, int cmd, uint32_t cr = stm32l4serial_getreg(priv, STM32L4_USART_CR3_OFFSET); -#if defined(CONFIG_STM32L4_STM32F10XX) - if (arg == SER_SINGLEWIRE_ENABLED) - { - stm32l4_configgpio((priv->tx_gpio & ~(GPIO_CNF_MASK)) | GPIO_CNF_AFOD); - cr |= USART_CR3_HDSEL; - } - else - { - stm32l4_configgpio((priv->tx_gpio & ~(GPIO_CNF_MASK)) | GPIO_CNF_AFPP); - cr &= ~USART_CR3_HDSEL; - } -#else if (arg == SER_SINGLEWIRE_ENABLED) { stm32l4_configgpio(priv->tx_gpio | GPIO_OPENDRAIN); @@ -1649,7 +1599,6 @@ static int stm32l4serial_ioctl(FAR struct file *filep, int cmd, stm32l4_configgpio(priv->tx_gpio | GPIO_PUSHPULL); cr &= ~USART_CR3_HDSEL; } -#endif stm32l4serial_putreg(priv, STM32L4_USART_CR3_OFFSET, cr); } @@ -2484,7 +2433,7 @@ void up_earlyserialinit(void) * ****************************************************************************/ -void stm32l4serial_getregit(void) +void up_serialinit(void) { #ifdef HAVE_UART char devname[16]; diff --git a/configs/freedom-k64f/Kconfig b/configs/freedom-k64f/Kconfig index 7c0f1fe281d..86130927032 100644 --- a/configs/freedom-k64f/Kconfig +++ b/configs/freedom-k64f/Kconfig @@ -4,4 +4,33 @@ # if ARCH_BOARD_FREEDOM_K64F -endif + +config FRDMK64F_SDHC_AUTOMOUNT + bool "SDHC automounter" + default n + depends on FS_AUTOMOUNTER && KINETIS_SDHC + +if FRDMK64F_SDHC_AUTOMOUNT + +config FRDMK64F_SDHC_AUTOMOUNT_FSTYPE + string "SDHC file system type" + default "vfat" + +config FRDMK64F_SDHC_AUTOMOUNT_BLKDEV + string "SDHC block device" + default "/dev/mmcsd0" + +config FRDMK64F_SDHC_AUTOMOUNT_MOUNTPOINT + string "SDHC mount point" + default "/mnt/sdcard" + +config FRDMK64F_SDHC_AUTOMOUNT_DDELAY + int "SDHC debounce delay (milliseconds)" + default 1000 + +config FRDMK64F_SDHC_AUTOMOUNT_UDELAY + int "SDHC unmount retry delay (milliseconds)" + default 2000 + +endif # FRDMK64F_SDHC_AUTOMOUNT +endif # ARCH_BOARD_FREEDOM_K64F diff --git a/configs/freedom-k64f/README.txt b/configs/freedom-k64f/README.txt index 0aaeb99a9cc..8814e0cb9a7 100644 --- a/configs/freedom-k64f/README.txt +++ b/configs/freedom-k64f/README.txt @@ -11,6 +11,8 @@ Contents o Serial Console o LEDs and Buttons o Networking Support + o SD Card Support + o USB Device Controller Support o Development Environment o GNU Toolchain Options o Freedom K64F Configuration Options @@ -409,6 +411,201 @@ f Application Configuration -> Network Utilities CONFIG_NSH_NETINIT_RETRYMSEC=2000 : Configure the network monitor as you like CONFIG_NSH_NETINIT_SIGNO=18 +SD Card Support +=============== + + Card Slot + --------- + A micro Secure Digital (SD) card slot is available on the FRDM-K64F connected to + the SD Host Controller (SDHC) signals of the MCU. This slot will accept micro + format SD memory cards. The SD card detect pin (PTE6) is an open switch that + shorts with VDD when card is inserted. + + ------------ ------------- -------- + SD Card Slot Board Signal K64F Pin + ------------ ------------- -------- + DAT0 SDHC0_D0 PTE0 + DAT1 SDHC0_D1 PTE1 + DAT2 SDHC0_D2 PTE5 + CD/DAT3 SDHC0_D3 PTE4 + CMD SDHC0_CMD PTE3 + CLK SDHC0_DCLK PTE2 + SWITCH D_CARD_DETECT PTE6 + ------------ ------------- -------- + + There is no Write Protect pin available to the K64F. + + Configuration Settings + ---------------------- + Enabling SDHC support. The Freedom K64F provides one microSD memory card + slot. Support for the SD slots can be enabled with the following + settings: + + System Type->Kinetic Peripheral Selection + CONFIG_KINETIS_SDHC=y : To enable SDHC0 support + + System Type + CONFIG_GPIO_IRQ=y : GPIO interrupts needed + CONFIG_KINETIS_PORTEINTS=y : Card detect pin is on PTE6 + + Device Drivers -> MMC/SD Driver Support + CONFIG_MMCSD=y : Enable MMC/SD support + CONFIG_MMSCD_NSLOTS=1 : One slot per driver instance + CONFIG_MMCSD_MULTIBLOCK_DISABLE=y : (REVISIT) + CONFIG_MMCSD_HAVECARDDETECT=y : Supports card-detect PIOs + CONFIG_MMCSD_MMCSUPPORT=n : Interferes with some SD cards + CONFIG_MMCSD_SPI=n : No SPI-based MMC/SD support + CONFIG_MMCSD_SDIO=y : SDIO-based MMC/SD support + CONFIG_SDIO_DMA=y : Use SDIO DMA + CONFIG_SDIO_BLOCKSETUP=y : Needs to know block sizes + + RTOS Features -> Work Queue Support + CONFIG_SCHED_WORKQUEUE=y : Driver needs work queue support + CONFIG_SCHED_HPWORK=y + + Application Configuration -> NSH Library + CONFIG_NSH_ARCHINIT=y : NSH board-initialization, and + CONFIG_LIB_BOARDCTL=y : Or + CONFIG_BOARD_INITIALIZE=y + + Using the SD card + ----------------- + + 1. After booting, the SDHC device will appear as /dev/mmcsd0. + 2. If you try mounting an SD card with nothing in the slot, the mount will + fail: + + nsh> mount -t vfat /dev/mmcsd0 /mnt/sd0 + nsh: mount: mount failed: 19 + + NSH can be configured to provide errors as strings instead of + numbers. But in this case, only the error number is reported. The + error numbers can be found in nuttx/include/errno.h: + + #define ENODEV 19 + #define ENODEV_STR "No such device" + + So the mount command is saying that there is no device or, more + correctly, that there is no card in the SD card slot. + + 3. Insert the SD card. Then the mount should succeed. + + nsh> mount -t vfat /dev/mmcsd0 /mnt/sd0 + nsh> ls /mnt/sd1 + /mnt/sd1: + atest.txt + nsh> cat /mnt/sd1/atest.txt + This is a test + + NOTE: See the next section entitled "Auto-Mounter" for another way + to mount your SD card. + + 4. Before removing the card, you must umount the file system. This is + equivalent to "ejecting" or "safely removing" the card on Windows: It + flushes any cached data to an SD card and makes the SD card unavailable + to the applications. + + nsh> umount -t /mnt/sd0 + + It is now safe to remove the card. NuttX provides into callbacks + that can be used by an application to automatically unmount the + volume when it is removed. But those callbacks are not used in + these configurations. + + Auto-Mounter + ------------ + NuttX implements an auto-mounter than can make working with SD cards + easier. With the auto-mounter, the file system will be automatically + mounted when the SD card is inserted into the SDHC slot and automatically + unmounted when the SD card is removed. + + Here is a sample configuration for the auto-mounter: + + File System Configuration + CONFIG_FS_AUTOMOUNTER=y + + Board-Specific Options + CONFIG_FRDMK64F_SDHC_AUTOMOUNT=y + CONFIG_FRDMK64F_SDHC_AUTOMOUNT_FSTYPE="vfat" + CONFIG_FRDMK64F_SDHC_AUTOMOUNT_BLKDEV="/dev/mmcsd0" + CONFIG_FRDMK64F_SDHC_AUTOMOUNT_MOUNTPOINT="/mnt/sdcard" + CONFIG_FRDMK64F_SDHC_AUTOMOUNT_DDELAY=1000 + CONFIG_FRDMK64F_SDHC_AUTOMOUNT_UDELAY=2000 + + WARNING: SD cards should never be removed without first unmounting + them. This is to avoid data and possible corruption of the file + system. Certainly this is the case if you are writing to the SD card + at the time of the removal. If you use the SD card for read-only access, + however, then I cannot think of any reason why removing the card without + mounting would be harmful. + +USB Device Controller Support +============================== + + USB Device Controller Support + ----------------------------- + The USBHS device controller driver is enabled with he following + configurationsettings: + + Device Drivers -> USB Device Driver Support + CONFIG_USBDEV=y : Enable USB device support + For full-speed/low-power mode: + CONFIG_USBDEV_DUALSPEED=n : Disable High speed support + For high-speed/normal mode: + CONFIG_USBDEV_DUALSPEED=y : Enable High speed support + CONFIG_USBDEV_DMA=y : Enable DMA methods + CONFIG_USBDEV_MAXPOWER=100 : Maximum power consumption + CONFIG_USBDEV_SELFPOWERED=y : Self-powered device + + System Type -> Kinetis Peripheral Selection + CONFIG_KINETIS_USBOTG=y + + CDC/ACM Device Class + -------------------- + In order to be usable, you must all enabled some class driver(s) for the + USBHS device controller. Here, for example, is how to configure the CDC/ACM + serial device class: + + Device Drivers -> USB Device Driver Support + CONFIG_CDCACM=y : USB Modem (CDC ACM) support + CONFIG_CDCACM_EP0MAXPACKET=64 : Enpoint 0 packet size + CONFIG_CDCACM_EPINTIN=1 : Interrupt IN endpoint number + CONFIG_CDCACM_EPINTIN_FSSIZE=64 : Full speed packet size + CONFIG_CDCACM_EPINTIN_HSSIZE=64 : High speed packet size + CONFIG_CDCACM_EPBULKOUT=3 : Bulk OUT endpoint number + CONFIG_CDCACM_EPBULKOUT_FSSIZE=64 : Full speed packet size + CONFIG_CDCACM_EPBULKOUT_HSSIZE=512 : High speed packet size + CONFIG_CDCACM_EPBULKIN=2 : Bulk IN endpoint number + CONFIG_CDCACM_EPBULKIN_FSSIZE=64 : Full speed packet size + CONFIG_CDCACM_EPBULKIN_HSSIZE=512 : High speed packet size + CONFIG_CDCACM_NWRREQS=4 : Number of write requests + CONFIG_CDCACM_NRDREQS=8 : Number of read requests + CONFIG_CDCACM_BULKIN_REQLEN=96 : Size of write request buffer (for full speed) + CONFIG_CDCACM_BULKIN_REQLEN=768 : Size of write request buffer (for high speed) + CONFIG_CDCACM_RXBUFSIZE=257 : Serial read buffer size + CONFIG_CDCACM_TXBUFSIZE=193 : Serial transmit buffer size (for full speed) + CONFIG_CDCACM_TXBUFSIZE=769 : Serial transmit buffer size (for high speed) + CONFIG_CDCACM_VENDORID=0x0525 : Vendor ID + CONFIG_CDCACM_PRODUCTID=0xa4a7 : Product ID + CONFIG_CDCACM_VENDORSTR="NuttX" : Vendor string + CONFIG_CDCACM_PRODUCTSTR="CDC/ACM Serial" : Product string + + Device Drivers -> Serial Driver Support + CONFIG_SERIAL_REMOVABLE=y : Support for removable serial device + + The CDC/ACM application provides commands to connect and disconnect the + CDC/ACM serial device: + + CONFIG_SYSTEM_CDCACM=y : Enable connect/disconnect support + CONFIG_SYSTEM_CDCACM_DEVMINOR=0 : Use device /dev/ttyACM0 + CONFIG_CDCACM_RXBUFSIZE=??? : A large RX may be needed + + If you include this CDC/ACM application, then you can connect the CDC/ACM + serial device to the host by entering the command 'sercon' and you detach + the serial device with the command 'serdis'. If you do no use this + application, they you will have to write logic in your board initialization + code to initialize and attach the USB device. + Development Environment ======================= @@ -636,8 +833,14 @@ Where is one of the following: NOTES: - 1. Most of the notes associated with the nsh configuration apply here - as well (see below). + 1. This configuration uses the mconf-based configuration tool. To + change this configuration using that tool, you should: + + a. Build and install the kconfig-mconf tool. See nuttx/README.txt + see additional README.txt files in the NuttX tools repository. + + b. Execute 'make menuconfig' in nuttx/ in order to start the + reconfiguration process. 2. Default platform/toolchain: @@ -646,13 +849,19 @@ Where is one of the following: CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIW=y : ARM/mbed toolcahin (arm-none-elf-gcc) CONFIG_INTELHEX_BINARY=y : Output formats: Intel hex binary - 3. No external pullup is available on MDIO signal when MK64FN1M0VLL12 MCU + 3. The Serial Console is provided on UART3 with the correct pin + configuration for use with an Arduino Serial Shield. + + 4. SDHC support is not enabled in this configuration. Refer to the + configuration settings listed above under "SD Card Support". + + 5. No external pullup is available on MDIO signal when MK64FN1M0VLL12 MCU is requests status of the Ethernet link connection. Internal pullup is required when port configuration for MDIO signal is enabled: CONFIG_KINETIS_ENET_MDIOPULLUP=y - 4. Configured to use a fixed IPv4 address: + 6. Configured to use a fixed IPv4 address: CONFIG_NSH_IPADDR=0x0a000002 CONFIG_NSH_DRIPADDR=0x0a000001 @@ -682,50 +891,53 @@ Where is one of the following: 2. Default platform/toolchain: - CONFIG_HOST_LINUX=y : Linux (Cygwin under Windows okay too). - CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT=y : Buildroot (arm-nuttx-elf-gcc) - CONFIG_ARMV7M_OABI_TOOLCHAIN=y : The older OABI version + CONFIG_HOST_WINDOWS=y : Cygwin under Windows + CONFIG_WINDOWS_CYGWIN=y + CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIW=y : ARM/mbed toolcahin (arm-none-elf-gcc) CONFIG_INTELHEX_BINARY=y : Output formats: Intel hex binary 3. The Serial Console is provided on UART3 with the correct pin configuration for use with an Arduino Serial Shield. - 4. An SDHC driver is has not yet been tested but can be enabled in the NSH - configuration by setting the following configuration values as follows: - - CONFIG_KINETIS_SDHC=y : Enable the SDHC driver - - CONFIG_MMCSD=y : Enable MMC/SD support - CONFIG_MMCSD_SDIO=y : Use the SDIO-based MMC/SD driver - CONFIG_MMCSD_NSLOTS=1 : One MMC/SD slot - - CONFIG_FAT=y : Eable FAT file system - CONFIG_FAT_LCNAMES=y : FAT lower case name support - CONFIG_FAT_LFN=y : FAT long file name support - CONFIG_FAT_MAXFNAME=32 : Maximum lenght of a long file name - - CONFIG_GPIO_IRQ=y : Enable GPIO interrupts - CONFIG_KINETIS_PORTEINTS=y : Enable PortE GPIO interrupts - - CONFIG_SCHED_WORKQUEUE=y : Enable the NuttX workqueue - - CONFIG_NSH_ARCHINIT=y : Provide NSH initializeation logic + 4. An SDHC driver is enabled in this configuration but does not yet work. + The basic problem seems to be that it does not sense the presence of + the SD card on PTE6. No interrupts are generated when the SD card is + inserted or removed. You might want to disable SDHC and MMC/SD if + you are using this configuration. Refer to the configuration + settings listed above under "SD Card Support". Status ====== 2016-07-11: Received hardware today and the board came up on the very first try. That does not happen often. At this point, the very basic - NSH configuration is working and LEDs are working. The only odd - behavior that I see is that pressing SW3 causes an unexpected interrupt - error. + NSH configuration is working and LEDs are working. + + The only odd behavior that I see is that pressing SW3 causes an NMI + interrupt (followed by a crash): + + kinetis_nmi: PANIC!!! NMI received + + I don't yet understand why this is. 2016-07-12: Added support for the KSZ8081 PHY and added the netnsh - configuration. The network is basically functional, but a lot more - testing is needed to confirm that. - + configuration. The network is basically functional. More testing is + needed, but I have not seen any obvious network failures. + In testing, I notice a strange thing. If I run at full optimization the code runs (albeit with bugs-to-be-solved). But with no optimization or even at -O1, the system fails to boot. This seems to be related to the watchdog timer. + 2016-07-13: Add SD automounter logic; broke out SDHC logic into a separate + file. The nsh configuration now has SDHC enabled be default. Does not + yet work. The basic problem seems to be that it does not sense the + presence of the SD card on PTE6. No interrupts are generated when the + SD card is inserted or removed. You might want to disable SDHC and + MMC/SD if you are using this configuration. + + The nsh configuration now builds successfully with USB device enabled. + USB device, however, has not yet been tested. I have not yet looked + into 48MHz clocking requirements. + + \ No newline at end of file diff --git a/configs/freedom-k64f/netnsh/defconfig b/configs/freedom-k64f/netnsh/defconfig index a4a8968bdd5..bb0ee7a5817 100644 --- a/configs/freedom-k64f/netnsh/defconfig +++ b/configs/freedom-k64f/netnsh/defconfig @@ -285,7 +285,7 @@ CONFIG_ARCH_HAVE_RAMVECTORS=y # # Board Settings # -CONFIG_BOARD_LOOPSPERMSEC=9535 +CONFIG_BOARD_LOOPSPERMSEC=10016 # CONFIG_ARCH_CALIBRATION is not set # diff --git a/configs/freedom-k64f/nsh/defconfig b/configs/freedom-k64f/nsh/defconfig index 7fb687ca4a6..347552c2ed8 100644 --- a/configs/freedom-k64f/nsh/defconfig +++ b/configs/freedom-k64f/nsh/defconfig @@ -8,10 +8,14 @@ # # CONFIG_EXPERIMENTAL is not set # CONFIG_DEFAULT_SMALL is not set -CONFIG_HOST_LINUX=y +# CONFIG_HOST_LINUX is not set # CONFIG_HOST_OSX is not set -# CONFIG_HOST_WINDOWS is not set +CONFIG_HOST_WINDOWS=y # CONFIG_HOST_OTHER is not set +# CONFIG_WINDOWS_NATIVE is not set +CONFIG_WINDOWS_CYGWIN=y +# CONFIG_WINDOWS_MSYS is not set +# CONFIG_WINDOWS_OTHER is not set # # Build Configuration @@ -135,12 +139,15 @@ CONFIG_ARM_HAVE_MPU_UNIFIED=y # CONFIG_ARMV7M_HAVE_DCACHE is not set # CONFIG_ARMV7M_HAVE_ITCM is not set # CONFIG_ARMV7M_HAVE_DTCM is not set -# CONFIG_ARMV7M_TOOLCHAIN_IARL is not set -CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT=y -# CONFIG_ARMV7M_TOOLCHAIN_CODEREDL is not set -# CONFIG_ARMV7M_TOOLCHAIN_CODESOURCERYL is not set +# CONFIG_ARMV7M_TOOLCHAIN_IARW is not set +# CONFIG_ARMV7M_TOOLCHAIN_ATOLLIC is not set +# CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT is not set +# CONFIG_ARMV7M_TOOLCHAIN_CODEREDW is not set +# CONFIG_ARMV7M_TOOLCHAIN_CODESOURCERYW is not set +# CONFIG_ARMV7M_TOOLCHAIN_DEVKITARM is not set # CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIL is not set -CONFIG_ARMV7M_OABI_TOOLCHAIN=y +CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIW=y +# CONFIG_ARMV7M_TOOLCHAIN_RAISONANCE is not set # CONFIG_ARMV7M_HAVE_STACKCHECK is not set # CONFIG_ARMV7M_ITMSYSLOG is not set @@ -208,7 +215,7 @@ CONFIG_KINETIS_UART3=y # CONFIG_KINETIS_ADC1 is not set # CONFIG_KINETIS_CMP is not set # CONFIG_KINETIS_VREF is not set -# CONFIG_KINETIS_SDHC is not set +CONFIG_KINETIS_SDHC=y # CONFIG_KINETIS_FTM0 is not set # CONFIG_KINETIS_FTM1 is not set # CONFIG_KINETIS_FTM2 is not set @@ -229,11 +236,23 @@ CONFIG_KINETIS_UART3=y # # Kinetis GPIO Interrupt Configuration # -# CONFIG_GPIO_IRQ is not set +CONFIG_GPIO_IRQ=y +# CONFIG_KINETIS_PORTAINTS is not set +# CONFIG_KINETIS_PORTBINTS is not set +# CONFIG_KINETIS_PORTCINTS is not set +# CONFIG_KINETIS_PORTDINTS is not set +CONFIG_KINETIS_PORTEINTS=y + +# +# Kinetis SDHC Configuration +# +# CONFIG_KINETIS_SDHC_ABSFREQ is not set # # Kinetis UART Configuration # +CONFIG_SDIO_DMA=y +# CONFIG_SDIO_WIDTH_D1_ONLY is not set # # Architecture Options @@ -267,7 +286,7 @@ CONFIG_ARCH_HAVE_RAMVECTORS=y # # Board Settings # -CONFIG_BOARD_LOOPSPERMSEC=9535 +CONFIG_BOARD_LOOPSPERMSEC=10016 # CONFIG_ARCH_CALIBRATION is not set # @@ -393,6 +412,7 @@ CONFIG_NAME_MAX=32 # CONFIG_SCHED_STARTHOOK is not set # CONFIG_SCHED_ATEXIT is not set # CONFIG_SCHED_ONEXIT is not set +# CONFIG_SIG_EVTHREAD is not set # # Signal Numbers @@ -401,6 +421,7 @@ CONFIG_SIG_SIGUSR1=1 CONFIG_SIG_SIGUSR2=2 CONFIG_SIG_SIGALARM=3 CONFIG_SIG_SIGCONDTIMEDOUT=16 +CONFIG_SIG_SIGWORK=17 # # POSIX Message Queue Options @@ -412,8 +433,11 @@ CONFIG_MQ_MAXMSGSIZE=32 # # Work queue support # -# CONFIG_SCHED_WORKQUEUE is not set -# CONFIG_SCHED_HPWORK is not set +CONFIG_SCHED_WORKQUEUE=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=224 +CONFIG_SCHED_HPWORKPERIOD=50000 +CONFIG_SCHED_HPWORKSTACKSIZE=2048 # CONFIG_SCHED_LPWORK is not set # @@ -479,7 +503,18 @@ CONFIG_DEV_NULL=y # CONFIG_RGBLED is not set # CONFIG_PCA9635PW is not set # CONFIG_NCP5623C is not set -# CONFIG_MMCSD is not set +CONFIG_MMCSD=y +CONFIG_MMCSD_NSLOTS=1 +# CONFIG_MMCSD_READONLY is not set +CONFIG_MMCSD_MULTIBLOCK_DISABLE=y +# CONFIG_MMCSD_MMCSUPPORT is not set +CONFIG_MMCSD_HAVECARDDETECT=y +CONFIG_ARCH_HAVE_SDIO=y +# CONFIG_ARCH_HAVE_SDIOWAIT_WRCOMPLETE is not set +CONFIG_MMCSD_SDIO=y +# CONFIG_SDIO_PREFLIGHT is not set +# CONFIG_SDIO_MUXBUS is not set +CONFIG_SDIO_BLOCKSETUP=y # CONFIG_MODEM is not set # CONFIG_MTD is not set # CONFIG_EEPROM is not set @@ -584,8 +619,9 @@ CONFIG_FS_WRITABLE=y CONFIG_FS_MQUEUE_MPATH="/var/mqueue" # CONFIG_FS_RAMMAP is not set CONFIG_FS_FAT=y -# CONFIG_FAT_LCNAMES is not set -# CONFIG_FAT_LFN is not set +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FAT_MAXFNAME=32 # CONFIG_FS_FATTIME is not set # CONFIG_FAT_FORCE_INDIRECT is not set # CONFIG_FAT_DMAMEMORY is not set @@ -864,6 +900,7 @@ CONFIG_NSH_DISABLE_LOSMART=y # CONFIG_NSH_DISABLE_WGET is not set # CONFIG_NSH_DISABLE_XD is not set CONFIG_NSH_MMCSDMINOR=0 +CONFIG_NSH_MMCSDSLOTNO=0 # # Configure Command Options diff --git a/configs/freedom-k64f/nsh/setenv.sh b/configs/freedom-k64f/nsh/setenv.sh index 45d7f9dd118..abb64617f41 100644 --- a/configs/freedom-k64f/nsh/setenv.sh +++ b/configs/freedom-k64f/nsh/setenv.sh @@ -61,7 +61,7 @@ fi # This is the location where I installed the ARM "GNU Tools for ARM Embedded Processors" # You can this free toolchain here https://launchpad.net/gcc-arm-embedded -#export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/GNU Tools ARM Embedded/4.9 2015q2/bin" +export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/GNU Tools ARM Embedded/4.9 2015q2/bin" # This is the path to the location where I installed the devkitARM toolchain # You can get this free toolchain from http://devkitpro.org/ or http://sourceforge.net/projects/devkitpro/ @@ -69,7 +69,7 @@ fi # This is the Cygwin path to the location where I build the buildroot # toolchain. -export TOOLCHAIN_BIN="${WD}/../buildroot/build_arm_nofpu/staging_dir/bin" +# export TOOLCHAIN_BIN="${WD}/../buildroot/build_arm_nofpu/staging_dir/bin" # Add the path to the toolchain to the PATH varialble export PATH="${TOOLCHAIN_BIN}:/sbin:/usr/sbin:${PATH_ORIG}" diff --git a/configs/freedom-k64f/src/Makefile b/configs/freedom-k64f/src/Makefile index 65cba8c536c..3538dc384be 100644 --- a/configs/freedom-k64f/src/Makefile +++ b/configs/freedom-k64f/src/Makefile @@ -54,6 +54,13 @@ else ifeq ($(CONFIG_BOARD_INITIALIZE),y) CSRCS += k64_bringup.c endif +ifeq ($(CONFIG_KINETIS_SDHC),y) +CSRCS += k64_sdhc.c +ifeq ($(CONFIG_FS_AUTOMOUNTER),y) +CSRCS += k64_automount.c +endif +endif + ifeq ($(CONFIG_USBDEV),y) CSRCS += k64_usbdev.c endif diff --git a/configs/freedom-k64f/src/freedom-k64f.h b/configs/freedom-k64f/src/freedom-k64f.h index a6758ebb0f6..aac232930bd 100644 --- a/configs/freedom-k64f/src/freedom-k64f.h +++ b/configs/freedom-k64f/src/freedom-k64f.h @@ -53,9 +53,10 @@ /* Assume we have everything */ -#define HAVE_PROC 1 -#define NSH_HAVEUSBDEV 1 -#define NSH_HAVEMMCSD 1 +#define HAVE_PROC 1 +#define HAVE_MMCSD 1 +#define HAVE_AUTOMOUNTER 1 +#define HAVE_USBDEV 1 /* Automount procfs */ @@ -83,12 +84,18 @@ */ #if defined(CONFIG_DISABLE_MOUNTPOINT) || !defined(CONFIG_KINETIS_SDHC) -# undef NSH_HAVEMMCSD +# undef HAVE_MMCSD #endif -#ifdef NSH_HAVEMMCSD +#ifdef HAVE_MMCSD # if defined(CONFIG_NSH_MMCSDSLOTNO) && CONFIG_NSH_MMCSDSLOTNO != 0 -# error "Only one MMC/SD slot, slot 0" +# error Only one MMC/SD slot, slot 0 +# endif + +# ifdef CONFIG_NSH_MMCSDMINOR +# define MMSCD_MINOR CONFIG_NSH_MMCSDMINOR +# else +# define MMSCD_MINOR 0 # endif /* We expect to receive GPIO interrupts for card insertion events */ @@ -100,12 +107,49 @@ # ifndef CONFIG_KINETIS_PORTEINTS # error "CONFIG_KINETIS_PORTEINTS required for card detect interrupt" # endif + #endif +/* Automounter */ + +#if !defined(CONFIG_FS_AUTOMOUNTER) || !defined(HAVE_MMCSD) +# undef HAVE_AUTOMOUNTER +# undef CONFIG_FRDMK64F_SDHC_AUTOMOUNT +#endif + +#ifndef CONFIG_FRDMK64F_SDHC_AUTOMOUNT +# undef HAVE_AUTOMOUNTER +#endif + +/* Automounter defaults */ + +#ifdef HAVE_AUTOMOUNTER + +# ifndef CONFIG_FRDMK64F_SDHC_AUTOMOUNT_FSTYPE +# define CONFIG_FRDMK64F_SDHC_AUTOMOUNT_FSTYPE "vfat" +# endif + +# ifndef CONFIG_FRDMK64F_SDHC_AUTOMOUNT_BLKDEV +# define CONFIG_FRDMK64F_SDHC_AUTOMOUNT_BLKDEV "/dev/mmcds0" +# endif + +# ifndef CONFIG_FRDMK64F_SDHC_AUTOMOUNT_MOUNTPOINT +# define CONFIG_FRDMK64F_SDHC_AUTOMOUNT_MOUNTPOINT "/mnt/sdcard" +# endif + +# ifndef CONFIG_FRDMK64F_SDHC_AUTOMOUNT_DDELAY +# define CONFIG_FRDMK64F_SDHC_AUTOMOUNT_DDELAY 1000 +# endif + +# ifndef CONFIG_FRDMK64F_SDHC_AUTOMOUNT_UDELAY +# define CONFIG_FRDMK64F_SDHC_AUTOMOUNT_UDELAY 2000 +# endif +#endif /* HAVE_AUTOMOUNTER */ + /* Can't support USB features if USB is not enabled */ #ifndef CONFIG_USBDEV -# undef NSH_HAVEUSBDEV +# undef HAVE_USBDEV #endif /* How many SPI modules does this chip support? The LM3S6918 supports 2 SPI @@ -126,6 +170,18 @@ * format SD memory cards. The SD card detect pin (PTE6) is an open switch that * shorts with VDD when card is inserted. * + * ------------ ------------- -------- + * SD Card Slot Board Signal K64F Pin + * ------------ ------------- -------- + * DAT0 SDHC0_D0 PTE0 + * DAT1 SDHC0_D1 PTE1 + * DAT2 SDHC0_D2 PTE5 + * CD/DAT3 SDHC0_D3 PTE4 + * CMD SDHC0_CMD PTE3 + * CLK SDHC0_DCLK PTE2 + * SWITCH D_CARD_DETECT PTE6 + * ------------ ------------- -------- + * * There is no Write Protect pin available to the K64F. */ @@ -200,5 +256,89 @@ void weak_function k64_usbinitialize(void); int k64_bringup(void); #endif +/**************************************************************************** + * Name: k64_sdhc_initialize + * + * Description: + * Inititialize the SDHC SD card slot + * + ****************************************************************************/ + +#ifdef HAVE_MMCSD +int k64_sdhc_initialize(void); +#else +# define k64_sdhc_initialize() (OK) +#endif + +/************************************************************************************ + * Name: k64_cardinserted + * + * Description: + * Check if a card is inserted into the SDHC slot + * + ************************************************************************************/ + +#ifdef HAVE_AUTOMOUNTER +bool k64_cardinserted(void); +#else +# define k64_cardinserted() (false) +#endif + +/************************************************************************************ + * Name: k64_writeprotected + * + * Description: + * Check if the card in the MMC/SD slot is write protected + * + ************************************************************************************/ + +#ifdef HAVE_AUTOMOUNTER +bool k64_writeprotected(void); +#else +# define k64_writeprotected() (false) +#endif + +/************************************************************************************ + * Name: k64_automount_initialize + * + * Description: + * Configure auto-mounter for the configured SDHC slot + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifdef HAVE_AUTOMOUNTER +void k64_automount_initialize(void); +#endif + +/************************************************************************************ + * Name: k64_automount_event + * + * Description: + * The SDHC card detection logic has detected an insertion or removal event. It + * has already scheduled the MMC/SD block driver operations. Now we need to + * schedule the auto-mount event which will occur with a substantial delay to make + * sure that everything has settle down. + * + * Input Parameters: + * inserted - True if the card is inserted in the slot. False otherwise. + * + * Returned Value: + * None + * + * Assumptions: + * Interrupts are disabled. + * + ************************************************************************************/ + +#ifdef HAVE_AUTOMOUNTER +void k64_automount_event(bool inserted); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __CONFIGS_FREEDOM_K64F_SRC_FREEDOM_K64F_H */ diff --git a/configs/freedom-k64f/src/k64_automount.c b/configs/freedom-k64f/src/k64_automount.c new file mode 100644 index 00000000000..8ec1be29ffe --- /dev/null +++ b/configs/freedom-k64f/src/k64_automount.c @@ -0,0 +1,322 @@ +/************************************************************************************ + * configs/freedom-k64f/src/k64_automount.c + * + * Copyright (C) 2016 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_FS_AUTOMOUNTER_DEBUG) && !defined(CONFIG_DEBUG_FS) +# define CONFIG_DEBUG_FS 1 +#endif + +#include + +#include +#include +#include + +#include "freedom-k64f.h" + +#ifdef HAVE_AUTOMOUNTER + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#ifndef NULL +# define NULL (FAR void *)0 +#endif + +#ifndef OK +# define OK 0 +#endif + +/************************************************************************************ + * Private Types + ************************************************************************************/ +/* This structure represents the changeable state of the automounter */ + +struct k64_automount_state_s +{ + volatile automount_handler_t handler; /* Upper half handler */ + FAR void *arg; /* Handler argument */ + bool enable; /* Fake interrupt enable */ + bool pending; /* Set if there an event while disabled */ +}; + +/* This structure represents the static configuration of an automounter */ + +struct k64_automount_config_s +{ + /* This must be first thing in structure so that we can simply cast from struct + * automount_lower_s to struct k64_automount_config_s + */ + + struct automount_lower_s lower; /* Publicly visible part */ + FAR struct k64_automount_state_s *state; /* Changeable state */ +}; + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ + +static int k64_attach(FAR const struct automount_lower_s *lower, + automount_handler_t isr, FAR void *arg); +static void k64_enable(FAR const struct automount_lower_s *lower, bool enable); +static bool k64_inserted(FAR const struct automount_lower_s *lower); + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +static struct k64_automount_state_s g_sdhc_state; +static const struct k64_automount_config_s g_sdhc_config = +{ + .lower = + { + .fstype = CONFIG_FRDMK64F_SDHC_AUTOMOUNT_FSTYPE, + .blockdev = CONFIG_FRDMK64F_SDHC_AUTOMOUNT_BLKDEV, + .mountpoint = CONFIG_FRDMK64F_SDHC_AUTOMOUNT_MOUNTPOINT, + .ddelay = MSEC2TICK(CONFIG_FRDMK64F_SDHC_AUTOMOUNT_DDELAY), + .udelay = MSEC2TICK(CONFIG_FRDMK64F_SDHC_AUTOMOUNT_UDELAY), + .attach = k64_attach, + .enable = k64_enable, + .inserted = k64_inserted + }, + .state = &g_sdhc_state +}; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: k64_attach + * + * Description: + * Attach a new SDHC event handler + * + * Input Parameters: + * lower - An instance of the auto-mounter lower half state structure + * isr - The new event handler to be attach + * arg - Client data to be provided when the event handler is invoked. + * + * Returned Value: + * Always returns OK + * + ************************************************************************************/ + +static int k64_attach(FAR const struct automount_lower_s *lower, + automount_handler_t isr, FAR void *arg) +{ + FAR const struct k64_automount_config_s *config; + FAR struct k64_automount_state_s *state; + + /* Recover references to our structure */ + + config = (FAR struct k64_automount_config_s *)lower; + DEBUGASSERT(config != NULL && config->state != NULL); + + state = config->state; + + /* Save the new handler info (clearing the handler first to eliminate race + * conditions). + */ + + state->handler = NULL; + state->pending = false; + state->arg = arg; + state->handler = isr; + return OK; +} + +/************************************************************************************ + * Name: k64_enable + * + * Description: + * Enable card insertion/removal event detection + * + * Input Parameters: + * lower - An instance of the auto-mounter lower half state structure + * enable - True: enable event detection; False: disable + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void k64_enable(FAR const struct automount_lower_s *lower, bool enable) +{ + FAR const struct k64_automount_config_s *config; + FAR struct k64_automount_state_s *state; + irqstate_t flags; + + /* Recover references to our structure */ + + config = (FAR struct k64_automount_config_s *)lower; + DEBUGASSERT(config != NULL && config->state != NULL); + + state = config->state; + + /* Save the fake enable setting */ + + flags = enter_critical_section(); + state->enable = enable; + + /* Did an interrupt occur while interrupts were disabled? */ + + if (enable && state->pending) + { + /* Yes.. perform the fake interrupt if the interrutp is attached */ + + if (state->handler) + { + bool inserted = k64_cardinserted(); + (void)state->handler(&config->lower, state->arg, inserted); + } + + state->pending = false; + } + + leave_critical_section(flags); +} + +/************************************************************************************ + * Name: k64_inserted + * + * Description: + * Check if a card is inserted into the slot. + * + * Input Parameters: + * lower - An instance of the auto-mounter lower half state structure + * + * Returned Value: + * True if the card is inserted; False otherwise + * + ************************************************************************************/ + +static bool k64_inserted(FAR const struct automount_lower_s *lower) +{ + return k64_cardinserted(); +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: k64_automount_initialize + * + * Description: + * Configure auto-mounters for each enable and so configured SDHC + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +void k64_automount_initialize(void) +{ + FAR void *handle; + + finfo("Initializing automounter(s)\n"); + + /* Initialize the SDHC0 auto-mounter */ + + handle = automount_initialize(&g_sdhc_config.lower); + if (!handle) + { + ferr("ERROR: Failed to initialize auto-mounter for SDHC0\n"); + } +} + +/************************************************************************************ + * Name: k64_automount_event + * + * Description: + * The SDHC card detection logic has detected an insertion or removal event. It + * has already scheduled the MMC/SD block driver operations. Now we need to + * schedule the auto-mount event which will occur with a substantial delay to make + * sure that everything has settle down. + * + * Input Parameters: + * slotno - Identifies the SDHC0 slot: SDHC0_SLOTNO or SDHC1_SLOTNO. There is a + * terminology problem here: Each SDHC supports two slots, slot A and slot B. + * Only slot A is used. So this is not a really a slot, but an HSCMI peripheral + * number. + * inserted - True if the card is inserted in the slot. False otherwise. + * + * Returned Value: + * None + * + * Assumptions: + * Interrupts are disabled. + * + ************************************************************************************/ + +void k64_automount_event(bool inserted) +{ + FAR const struct k64_automount_config_s *config = &g_sdhc_config; + FAR struct k64_automount_state_s *state = &g_sdhc_state; + + /* Is the auto-mounter interrupt attached? */ + + if (state->handler) + { + /* Yes.. Have we been asked to hold off interrupts? */ + + if (!state->enable) + { + /* Yes.. just remember the there is a pending interrupt. We will + * deliver the interrupt when interrupts are "re-enabled." + */ + + state->pending = true; + } + else + { + /* No.. forward the event to the handler */ + + (void)state->handler(&config->lower, state->arg, inserted); + } + } +} + +#endif /* HAVE_AUTOMOUNTER */ diff --git a/configs/freedom-k64f/src/k64_bringup.c b/configs/freedom-k64f/src/k64_bringup.c index 0cbbb1bb280..b307c7038ec 100644 --- a/configs/freedom-k64f/src/k64_bringup.c +++ b/configs/freedom-k64f/src/k64_bringup.c @@ -39,112 +39,27 @@ #include +#include #include -#include -#include #include #include +#include -#ifdef CONFIG_KINETIS_SDHC -# include -# include -#endif - -#include "kinetis.h" #include "freedom-k64f.h" #if defined(CONFIG_LIB_BOARDCTL) || defined(CONFIG_BOARD_INITIALIZE) -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/* This structure encapsulates the global variable used in this file and - * reduces the probability of name collistions. - */ - -#ifdef NSH_HAVEMMCSD -struct k64_nsh_s -{ - FAR struct sdio_dev_s *sdhc; /* SDIO driver handle */ - bool inserted; /* True: card is inserted */ -}; -#endif - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -#ifdef NSH_HAVEMMCSD -static struct k64_nsh_s g_nsh; -#endif - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: k64_mediachange - ****************************************************************************/ - -#ifdef NSH_HAVEMMCSD -static void k64_mediachange(void) -{ - bool inserted; - - /* Get the current value of the card detect pin. This pin is pulled up on - * board. So low means that a card is present. - */ - - inserted = !kinetis_gpioread(GPIO_SD_CARDDETECT); - - /* Has the pin changed state? */ - - if (inserted != g_nsh.inserted) - { - /* Yes.. perform the appropriate action (this might need some debounce). */ - - g_nsh.inserted = inserted; - sdhc_mediachange(g_nsh.sdhc, inserted); - - /* If the card has been inserted, then check if it is write protected - * as well. The pin is pulled up, but apparently logic high means - * write protected. - */ - - if (inserted) - { - sdhc_wrprotect(g_nsh.sdhc, kinetis_gpioread(GPIO_SD_WRPROTECT)); - } - } -} -#endif - -/**************************************************************************** - * Name: k64_cdinterrupt - ****************************************************************************/ - -#ifdef NSH_HAVEMMCSD -static int k64_cdinterrupt(int irq, FAR void *context) -{ - /* All of the work is done by k64_mediachange() */ - - k64_mediachange(); - return OK; -} -#endif - /**************************************************************************** * Public Functions ****************************************************************************/ -/************************************************************************************ +/**************************************************************************** * Name: k64_bringup * * Description: * Bring up board features * - ************************************************************************************/ + ****************************************************************************/ int k64_bringup(void) { @@ -165,52 +80,40 @@ int k64_bringup(void) } #endif -#ifdef NSH_HAVEMMCSD - /* Configure GPIO pins */ +#ifdef HAVE_MMCSD + /* Initialize the SDHC driver */ - /* Attached the card detect interrupt (but don't enable it yet) */ - - kinetis_pinconfig(GPIO_SD_CARDDETECT); - kinetis_pinirqattach(GPIO_SD_CARDDETECT, k64_cdinterrupt); - - /* Configure the write protect GPIO */ - - //kinetis_pinconfig(GPIO_SD_WRPROTECT); - - /* Mount the SDHC-based MMC/SD block driver */ - /* First, get an instance of the SDHC interface */ - - syslog(LOG_INFO, "Initializing SDHC slot %d\n", MMCSD_SLOTNO); - - g_nsh.sdhc = sdhc_initialize(MMCSD_SLOTNO); - if (!g_nsh.sdhc) + ret = k64_sdhc_initialize(); + if (ret < 0) { - syslog(LOG_ERR, "ERROR: Failed to initialize SDHC slot %d\n", - MMCSD_SLOTNO); - return -ENODEV; + mcerr("ERROR: k64_sdhc_initialize() failed: %d\n", ret); } - /* Now bind the SDHC interface to the MMC/SD driver */ - - syslog(LOG_INFO, "Bind SDHC to the MMC/SD driver, minor=%d\n", - CONFIG_NSH_MMCSDMINOR); - - ret = mmcsd_slotinitialize(CONFIG_NSH_MMCSDMINOR, g_nsh.sdhc); - if (ret != OK) +#ifdef CONFIG_FRDMK64F_SDHC_MOUNT + else { - syslog(LOG_ERR, "ERROR: Failed to bind SDHC to the MMC/SD driver: %d\n", ret); - return ret; + /* REVISIT: A delay seems to be required here or the mount will fail. */ + /* Mount the volume on HSMCI0 */ + + ret = mount(CONFIG_FRDMK64F_SDHC_MOUNT_BLKDEV, + CONFIG_FRDMK64F_SDHC_MOUNT_MOUNTPOINT, + CONFIG_FRDMK64F_SDHC_MOUNT_FSTYPE, + 0, NULL); + + if (ret < 0) + { + mcerr("ERROR: Failed to mount %s: %d\n", + CONFIG_FRDMK64F_SDHC_MOUNT_MOUNTPOINT, errno); + } } - syslog(LOG_INFO, "Successfully bound SDHC to the MMC/SD driver\n"); +#endif /* CONFIG_FRDMK64F_SDHC_MOUNT */ +#endif /* HAVE_MMCSD */ - /* Handle the initial card state */ +#ifdef HAVE_AUTOMOUNTER + /* Initialize the auto-mounter */ - k64_mediachange(); - - /* Enable CD interrupts to handle subsequent media changes */ - - kinetis_pinirqenable(GPIO_SD_CARDDETECT); + k64_automount_initialize(); #endif UNUSED(ret); diff --git a/configs/freedom-k64f/src/k64_sdhc.c b/configs/freedom-k64f/src/k64_sdhc.c new file mode 100644 index 00000000000..4083235048b --- /dev/null +++ b/configs/freedom-k64f/src/k64_sdhc.c @@ -0,0 +1,251 @@ +/**************************************************************************** + * config/freedom-k64f/src/k64_sdhc.c + * + * Copyright (C) 2016 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. + * + ****************************************************************************/ + +/* A micro Secure Digital (SD) card slot is available on the FRDM-K64F connected to + * the SD Host Controller (SDHC) signals of the MCU. This slot will accept micro + * format SD memory cards. The SD card detect pin (PTE6) is an open switch that + * shorts with VDD when card is inserted. + * + * ------------ ------------- -------- + * SD Card Slot Board Signal K64F Pin + * ------------ ------------- -------- + * DAT0 SDHC0_D0 PTE0 + * DAT1 SDHC0_D1 PTE1 + * DAT2 SDHC0_D2 PTE5 + * CD/DAT3 SDHC0_D3 PTE4 + * CMD SDHC0_CMD PTE3 + * CLK SDHC0_DCLK PTE2 + * SWITCH D_CARD_DETECT PTE6 + * ------------ ------------- -------- + * + * There is no Write Protect pin available to the K64F. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "kinetis.h" + +#include "freedom-k64f.h" + +#ifdef HAVE_MMCSD + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ +/* This structure holds static information unique to one SDHC peripheral */ + +struct k64_sdhc_state_s +{ + struct sdio_dev_s *sdhc; /* R/W device handle */ + bool inserted; /* TRUE: card is inserted */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* HSCMI device state */ + +static struct k64_sdhc_state_s g_sdhc; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: k64_mediachange + ****************************************************************************/ + +static void k64_mediachange(void) +{ + bool inserted; + + /* Get the current value of the card detect pin. This pin is pulled up on + * board. So low means that a card is present. + */ + + inserted = !kinetis_gpioread(GPIO_SD_CARDDETECT); + mcinfo("inserted: %s\n", inserted ? "Yes" : "No"); + + /* Has the pin changed state? */ + + if (inserted != g_sdhc.inserted) + { + mcinfo("Media change: %d->%d\n", g_sdhc.inserted, inserted); + + /* Yes.. perform the appropriate action (this might need some debounce). */ + + g_sdhc.inserted = inserted; + sdhc_mediachange(g_sdhc.sdhc, inserted); + +#ifdef CONFIG_FRDMK64F_SDHC_AUTOMOUNT + /* Let the automounter know about the insertion event */ + + k64_automount_event(k64_cardinserted()); +#endif + } +} + +/**************************************************************************** + * Name: k64_cdinterrupt + ****************************************************************************/ + +static int k64_cdinterrupt(int irq, FAR void *context) +{ + /* All of the work is done by k64_mediachange() */ + + k64_mediachange(); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: k64_sdhc_initialize + * + * Description: + * Inititialize the SDHC SD card slot + * + ****************************************************************************/ + +int k64_sdhc_initialize(void) +{ + int ret; + + /* Configure GPIO pins */ + + kinetis_pinconfig(GPIO_SD_CARDDETECT); + + /* Attached the card detect interrupt (but don't enable it yet) */ + + kinetis_pinirqattach(GPIO_SD_CARDDETECT, k64_cdinterrupt); + + /* Configure the write protect GPIO -- None */ + + /* Mount the SDHC-based MMC/SD block driver */ + /* First, get an instance of the SDHC interface */ + + mcinfo("Initializing SDHC slot %d\n", MMCSD_SLOTNO); + + g_sdhc.sdhc = sdhc_initialize(MMCSD_SLOTNO); + if (!g_sdhc.sdhc) + { + mcerr("ERROR: Failed to initialize SDHC slot %d\n", MMCSD_SLOTNO); + return -ENODEV; + } + + /* Now bind the SDHC interface to the MMC/SD driver */ + + mcinfo("Bind SDHC to the MMC/SD driver, minor=%d\n", MMSCD_MINOR); + + ret = mmcsd_slotinitialize(MMSCD_MINOR, g_sdhc.sdhc); + if (ret != OK) + { + syslog(LOG_ERR, "ERROR: Failed to bind SDHC to the MMC/SD driver: %d\n", ret); + return ret; + } + + syslog(LOG_INFO, "Successfully bound SDHC to the MMC/SD driver\n"); + + /* Handle the initial card state */ + + k64_mediachange(); + + /* Enable CD interrupts to handle subsequent media changes */ + + kinetis_pinirqenable(GPIO_SD_CARDDETECT); + return OK; +} + +/**************************************************************************** + * Name: k64_cardinserted + * + * Description: + * Check if a card is inserted into the SDHC slot + * + ****************************************************************************/ + +#ifdef HAVE_AUTOMOUNTER +bool k64_cardinserted(void) +{ + bool inserted; + + /* Get the current value of the card detect pin. This pin is pulled up on + * board. So low means that a card is present. + */ + + inserted = !kinetis_gpioread(GPIO_SD_CARDDETECT); + mcinfo("inserted: %s\n", inserted ? "Yes" : "No"); + return inserted; +} +#endif + +/**************************************************************************** + * Name: k64_writeprotected + * + * Description: + * Check if a card is inserted into the SDHC slot + * + ****************************************************************************/ + +#ifdef HAVE_AUTOMOUNTER +bool k64_writeprotected(void) +{ + /* There are no write protect pins */ + + return false; +} +#endif + +#endif /* HAVE_MMCSD */ diff --git a/configs/samv71-xult/src/sam_hsmci.c b/configs/samv71-xult/src/sam_hsmci.c index 85e66b048d5..2b4cb3295f8 100644 --- a/configs/samv71-xult/src/sam_hsmci.c +++ b/configs/samv71-xult/src/sam_hsmci.c @@ -129,7 +129,7 @@ bool sam_cardinserted_internal(struct sam_hsmci_state_s *state) /* Get the state of the PIO pin */ inserted = sam_gpioread(state->cdcfg); - finfo("Slot %d inserted: %s\n", state->slotno, inserted ? "NO" : "YES"); + mcinfo("Slot %d inserted: %s\n", state->slotno, inserted ? "NO" : "YES"); return !inserted; } @@ -221,12 +221,12 @@ int sam_hsmci_initialize(int slotno, int minor) struct sam_hsmci_state_s *state; int ret; - /* Get the static HSMI description */ + /* Get the static HSMCI description */ state = sam_hsmci_state(slotno); if (!state) { - ferr("ERROR: No state for slotno %d\n", slotno); + mcerr("ERROR: No state for slotno %d\n", slotno); return -EINVAL; } @@ -247,7 +247,7 @@ int sam_hsmci_initialize(int slotno, int minor) state->hsmci = sdio_initialize(slotno); if (!state->hsmci) { - ferr("ERROR: Failed to initialize SDIO slot %d\n", slotno); + mcerr("ERROR: Failed to initialize SDIO slot %d\n", slotno); return -ENODEV; } @@ -256,7 +256,7 @@ int sam_hsmci_initialize(int slotno, int minor) ret = mmcsd_slotinitialize(minor, state->hsmci); if (ret != OK) { - ferr("ERROR: Failed to bind SDIO to the MMC/SD driver: %d\n", ret); + mcerr("ERROR: Failed to bind SDIO to the MMC/SD driver: %d\n", ret); return ret; } @@ -293,7 +293,7 @@ bool sam_cardinserted(int slotno) state = sam_hsmci_state(slotno); if (!state) { - ferr("ERROR: No state for slotno %d\n", slotno); + mcerr("ERROR: No state for slotno %d\n", slotno); return false; } diff --git a/drivers/mmcsd/mmcsd_sdio.c b/drivers/mmcsd/mmcsd_sdio.c index be934950b9e..46ee65a9d54 100644 --- a/drivers/mmcsd/mmcsd_sdio.c +++ b/drivers/mmcsd/mmcsd_sdio.c @@ -171,7 +171,7 @@ static int mmcsd_getSCR(FAR struct mmcsd_state_s *priv, uint32_t scr[2]); static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4]); -#if defined(CONFIG_DEBUG_FEATURES) && defined (CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_DEBUG_FS_INFO static void mmcsd_decodeCID(FAR struct mmcsd_state_s *priv, uint32_t cid[4]); #else @@ -558,7 +558,7 @@ static int mmcsd_getSCR(FAR struct mmcsd_state_s *priv, uint32_t scr[2]) static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4]) { -#if defined(CONFIG_DEBUG_FEATURES) && defined (CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_DEBUG_FS_INFO struct mmcsd_csd_s decoded; #endif unsigned int readbllen; @@ -578,7 +578,7 @@ static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4]) * TRANSFER_RATE_UNIT 2:0 Rate mantissa */ -#if defined(CONFIG_DEBUG_FEATURES) && defined (CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_DEBUG_FS_INFO memset(&decoded, 0, sizeof(struct mmcsd_csd_s)); decoded.csdstructure = csd[0] >> 30; decoded.mmcspecvers = (csd[0] >> 26) & 0x0f; @@ -606,7 +606,7 @@ static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4]) priv->dsrimp = (csd[1] >> 12) & 1; readbllen = (csd[1] >> 16) & 0x0f; -#if defined(CONFIG_DEBUG_FEATURES) && defined (CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_DEBUG_FS_INFO decoded.ccc = (csd[1] >> 20) & 0x0fff; decoded.readbllen = (csd[1] >> 16) & 0x0f; decoded.readblpartial = (csd[1] >> 15) & 1; @@ -667,7 +667,7 @@ static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4]) priv->blocksize = 1 << 9; priv->nblocks = priv->capacity >> 9; -#if defined(CONFIG_DEBUG_FEATURES) && defined (CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_DEBUG_FS_INFO decoded.u.sdblock.csize = csize; decoded.u.sdblock.sderblen = (csd[2] >> 14) & 1; decoded.u.sdblock.sdsectorsize = (csd[2] >> 7) & 0x7f; @@ -703,7 +703,7 @@ static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4]) priv->blockshift = 9; } -#if defined(CONFIG_DEBUG_FEATURES) && defined (CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_DEBUG_FS_INFO if (IS_SD(priv->type)) { decoded.u.sdbyte.csize = csize; @@ -753,7 +753,7 @@ static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4]) tmpwriteprotect = (csd[3] >> 12) & 1; priv->wrprotect = (permwriteprotect || tmpwriteprotect); -#if defined(CONFIG_DEBUG_FEATURES) && defined (CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_DEBUG_FS_INFO decoded.wpgrpen = csd[3] >> 31; decoded.mmcdfltecc = (csd[3] >> 29) & 3; decoded.r2wfactor = (csd[3] >> 26) & 7; @@ -844,7 +844,7 @@ static void mmcsd_decodeCSD(FAR struct mmcsd_state_s *priv, uint32_t csd[4]) * ****************************************************************************/ -#if defined(CONFIG_DEBUG_FEATURES) && defined (CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_DEBUG_FS_INFO static void mmcsd_decodeCID(FAR struct mmcsd_state_s *priv, uint32_t cid[4]) { struct mmcsd_cid_s decoded; @@ -910,7 +910,7 @@ static void mmcsd_decodeCID(FAR struct mmcsd_state_s *priv, uint32_t cid[4]) static void mmcsd_decodeSCR(FAR struct mmcsd_state_s *priv, uint32_t scr[2]) { -#if defined(CONFIG_DEBUG_FEATURES) && defined (CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_DEBUG_FS_INFO struct mmcsd_scr_s decoded; #endif @@ -923,14 +923,14 @@ struct mmcsd_scr_s decoded; * Reserved 47:32 16-bit SD reserved space */ -#ifdef CONFIG_ENDIAN_BIG /* Card transfers SCR in big-endian order */ +#ifdef CONFIG_ENDIAN_BIG /* Card transfers SCR in big-endian order */ priv->buswidth = (scr[0] >> 16) & 15; #else priv->buswidth = (scr[0] >> 8) & 15; #endif -#if defined(CONFIG_DEBUG_FEATURES) && defined (CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS) -#ifdef CONFIG_ENDIAN_BIG /* Card SCR is big-endian order / CPU also big-endian +#ifdef CONFIG_DEBUG_FS_INFO +#ifdef CONFIG_ENDIAN_BIG /* Card SCR is big-endian order / CPU also big-endian * 60 56 52 48 44 40 36 32 * VVVV SSSS ESSS BBBB RRRR RRRR RRRR RRRR */ decoded.scrversion = scr[0] >> 28; @@ -952,7 +952,7 @@ struct mmcsd_scr_s decoded; * Reserved 31:0 32-bits reserved for manufacturing usage. */ -#if defined(CONFIG_DEBUG_FEATURES) && defined (CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_DEBUG_FS_INFO decoded.mfgdata = scr[1]; /* Might be byte reversed! */ finfo("SCR:\n"); diff --git a/drivers/mtd/smart.c b/drivers/mtd/smart.c index e763e6bcba3..bbd7be3cdd0 100644 --- a/drivers/mtd/smart.c +++ b/drivers/mtd/smart.c @@ -3,7 +3,7 @@ * * Sector Mapped Allocation for Really Tiny (SMART) Flash block driver. * - * Copyright (C) 2013-2015 Ken Pettit. All rights reserved. + * Copyright (C) 2013-2016 Ken Pettit. All rights reserved. * Author: Ken Pettit * * Redistribution and use in source and binary forms, with or without @@ -73,7 +73,7 @@ #define SMART_STATUS_COMMITTED 0x80 #define SMART_STATUS_RELEASED 0x40 #define SMART_STATUS_CRC 0x20 -#define SMART_STATUS_SIZEBITS 0x1C +#define SMART_STATUS_SIZEBITS 0x1c #define SMART_STATUS_VERBITS 0x03 #if defined(CONFIG_SMART_CRC_16) @@ -87,7 +87,7 @@ #define SMART_SECTSIZE_256 0x00 #define SMART_SECTSIZE_512 0x04 #define SMART_SECTSIZE_1024 0x08 -#define SMART_SECTSIZE_2048 0x0C +#define SMART_SECTSIZE_2048 0x0c #define SMART_SECTSIZE_4096 0x10 #define SMART_SECTSIZE_8192 0x14 #define SMART_SECTSIZE_16384 0x18 @@ -134,7 +134,7 @@ #define offsetof(type, member) ( (size_t) &( ( (type *) 0)->member)) #endif -#define SMART_MAX_ALLOCS 6 +#define SMART_MAX_ALLOCS 10 //#define CONFIG_MTD_SMART_PACK_COUNTS #ifndef CONFIG_MTD_SMART_ALLOC_DEBUG @@ -147,7 +147,7 @@ #define SMART_WEAR_MIN_LEVEL 5 #define SMART_WEAR_FORCE_REORG_THRESHOLD 1 #define SMART_WEAR_BIT_DIVIDE 1 -#define SMART_WEAR_ZERO_MASK 0x0F +#define SMART_WEAR_ZERO_MASK 0x0f #define SMART_WEAR_BLOCK_MASK 0x01 /* Bit mapping for wear level bits */ @@ -167,10 +167,10 @@ static const uint8_t gWearLevelToBitMap4[] = { - 0x0F, 0x0E, 0x0C, 0x08, /* Single bit erased (x3) */ + 0x0f, 0x0e, 0x0c, 0x08, /* Single bit erased (x3) */ 0x07, 0x06, 0x04, 0x00, /* Single bit erased (x3) */ - 0x0B, 0x0A, 0x02, /* Single bit erased (x2) */ - 0x0D, 0x09, 0x01, /* Single bit erased (x2) */ + 0x0b, 0x0a, 0x02, /* Single bit erased (x2) */ + 0x0d, 0x09, 0x01, /* Single bit erased (x2) */ 0x03, 0x05 }; @@ -473,6 +473,18 @@ FAR static void *smart_malloc(FAR struct smart_struct_s *dev, FAR void *ret = kmm_malloc(bytes); uint8_t x; + /* Test if we are allocating the dev struct */ + + if (dev == NULL) + { + dev = ret; + dev->bytesalloc = 0; + for (x = 0; x < SMART_MAX_ALLOCS; x++) + { + dev->alloc[x].ptr = NULL; + } + } + /* Keep track of the total allocation */ if (ret != NULL) @@ -545,11 +557,11 @@ static void smart_set_count(FAR struct smart_struct_s *dev, FAR uint8_t *pCount, if (block & 0x01) { - pCount[block >> 1] = (pCount[block >> 1] & 0xF0) | (count & 0x0F); + pCount[block >> 1] = (pCount[block >> 1] & 0xf0) | (count & 0x0f); } else { - pCount[block >> 1] = (pCount[block >> 1] & 0x0F) | ((count & 0x0F) << 4); + pCount[block >> 1] = (pCount[block >> 1] & 0x0f) | ((count & 0x0f) << 4); } /* If we have 16 sectors per block, then the upper bit (representing 16) @@ -595,7 +607,7 @@ static uint8_t smart_get_count(FAR struct smart_struct_s *dev, if (block & 0x01) { - count = pCount[block >> 1] & 0x0F; + count = pCount[block >> 1] & 0x0f; } else { @@ -999,6 +1011,9 @@ static int smart_setsectorsize(FAR struct smart_struct_s *dev, uint16_t size) dev->sectorsize = size; dev->mtdBlksPerSector = dev->sectorsize / dev->geo.blocksize; + DEBUGASSERT(dev->sectorsize >= dev->geo.blocksize); + DEBUGASSERT(erasesize / dev->sectorsize <= 256); + if (erasesize / dev->sectorsize > 256) { /* We can't throw a error message here becasue it is too early. @@ -1051,7 +1066,7 @@ static int smart_setsectorsize(FAR struct smart_struct_s *dev, uint16_t size) } dev->cache_entries = 0; - dev->cache_lastlog = 0xFFFF; + dev->cache_lastlog = 0xffff; dev->cache_nextbirth = 0; #endif @@ -1359,7 +1374,7 @@ static int smart_add_sector_to_cache(FAR struct smart_struct_s *dev, { /* Cache is full. We must find the least accessed entry and replace it */ - oldest = 0xFFFF; + oldest = 0xffff; for (x = 0; x < CONFIG_MTD_SMART_SECTOR_CACHE_SIZE; x++) { /* Never replace cache entries for system sectors */ @@ -1427,7 +1442,7 @@ static uint16_t smart_cache_lookup(FAR struct smart_struct_s *dev, uint16_t logi struct smart_sect_header_s header; size_t readaddress; - physical = 0xFFFF; + physical = 0xffff; /* Test if searching for the last sector used */ @@ -1453,7 +1468,7 @@ static uint16_t smart_cache_lookup(FAR struct smart_struct_s *dev, uint16_t logi * for it and add it to the cache. */ - if (physical == 0xFFFF) + if (physical == 0xffff) { /* Now scan the MTD device. Instead of scanning start to end, we * span the erase blocks and read one sector from each at a time. @@ -1462,7 +1477,7 @@ static uint16_t smart_cache_lookup(FAR struct smart_struct_s *dev, uint16_t logi * numbers in each erase block first. */ - for (sector = 0; sector < dev->sectorsPerBlk && physical == 0xFFFF; sector++) + for (sector = 0; sector < dev->availSectPerBlk && physical == 0xffff; sector++) { /* Now scan across each erase block */ @@ -1566,7 +1581,7 @@ static void smart_update_cache(FAR struct smart_struct_s *dev, uint16_t * the cache. */ - if (physical == 0xFFFF) + if (physical == 0xffff) { dev->sCache[x].logical = dev->sCache[dev->cache_entries-1].logical; dev->sCache[x].physical = dev->sCache[dev->cache_entries-1].physical; @@ -1615,7 +1630,7 @@ static uint8_t smart_get_wear_level(FAR struct smart_struct_s *dev, uint16_t blo { /* Use the lower nibble */ - bits &= 0x0F; + bits &= 0x0f; } /* Lookup and return the level using the BitToLevel map */ @@ -1732,14 +1747,14 @@ static int smart_set_wear_level(FAR struct smart_struct_s *dev, uint16_t block, { /* Use the upper nibble */ - dev->wearstatus[block >> SMART_WEAR_BIT_DIVIDE] &= 0x0F; + dev->wearstatus[block >> SMART_WEAR_BIT_DIVIDE] &= 0x0f; dev->wearstatus[block >> SMART_WEAR_BIT_DIVIDE] |= bits << 4; } else { /* Use the lower nibble */ - dev->wearstatus[block >> SMART_WEAR_BIT_DIVIDE] &= 0xF0; + dev->wearstatus[block >> SMART_WEAR_BIT_DIVIDE] &= 0xf0; dev->wearstatus[block >> SMART_WEAR_BIT_DIVIDE] |= bits; } @@ -1817,10 +1832,10 @@ static int smart_scan(FAR struct smart_struct_s *dev) * a header and not sector data. */ - sectorsize = 0xFFFF; + sectorsize = 0xffff; offset = 16384; - while (sectorsize == 0xFFFF) + while (sectorsize == 0xffff) { readaddress = 0; @@ -1845,7 +1860,7 @@ static int smart_scan(FAR struct smart_struct_s *dev) } offset >>= 1; - if (offset < 256 && sectorsize == 0xFFFF) + if (offset < 256 && sectorsize == 0xffff) { /* No valid sectors found on device. Default the * sector size to the CONFIG value @@ -2074,7 +2089,7 @@ static int smart_scan(FAR struct smart_struct_s *dev) /* Test for duplicate logical sectors on the device */ #ifndef CONFIG_MTD_SMART_MINIMIZE_RAM - if (dev->sMap[logicalsector] != 0xFFFF) + if (dev->sMap[logicalsector] != 0xffff) #else if (dev->sBitMap[logicalsector >> 3] & (1 << (logicalsector & 0x07))) #endif @@ -2184,7 +2199,7 @@ static int smart_scan(FAR struct smart_struct_s *dev) /* Now determine who wins */ - if ((seq1 > 0xFFF0 && seq2 < 10) || seq2 > seq1) + if ((seq1 > 0xfff0 && seq2 < 10) || seq2 > seq1) { /* Seq 2 is the winner ... bigger or it wrapped */ @@ -2212,7 +2227,7 @@ static int smart_scan(FAR struct smart_struct_s *dev) goto err_out; } -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff header.status &= ~SMART_STATUS_RELEASED; #else header.status |= SMART_STATUS_RELEASED; @@ -2248,7 +2263,7 @@ static int smart_scan(FAR struct smart_struct_s *dev) /* We need to check if we are converting an older format with incorrect * wear leveling data in sector zero to the new format. The old format * put all zeros in the wear level bit locations, but the new (better) - * way is to leave them 0xFF. + * way is to leave them 0xff. */ #ifndef CONFIG_MTD_SMART_MINIMIZE_RAM @@ -2259,7 +2274,7 @@ static int smart_scan(FAR struct smart_struct_s *dev) /* Validate the sector is valid ... may be an unformatted device */ - if (sector != 0xFFFF) + if (sector != 0xffff) { /* Read the sector data */ @@ -2276,11 +2291,11 @@ static int smart_scan(FAR struct smart_struct_s *dev) if (dev->rwbuffer[SMART_WEAR_LEVEL_FORMAT_SIG] == 0) { /* Old format detected. We must relocate sector zero and fill it - * in with 0xFF. + * in with 0xff. */ uint16_t newsector = smart_findfreephyssector(dev, FALSE); - if (newsector == 0xFFFF) + if (newsector == 0xffff) { /* Unable to find a free sector!!! */ @@ -2289,7 +2304,7 @@ static int smart_scan(FAR struct smart_struct_s *dev) goto err_out; } - memset(&dev->rwbuffer[SMART_WEAR_LEVEL_FORMAT_SIG], 0xFF, + memset(&dev->rwbuffer[SMART_WEAR_LEVEL_FORMAT_SIG], 0xff, dev->mtdBlksPerSector * dev->geo.blocksize - SMART_WEAR_LEVEL_FORMAT_SIG); @@ -2677,7 +2692,7 @@ static int smart_relocate_static_data(FAR struct smart_struct_s *dev, uint16_t b /* Get next sector from 'block' */ newsector = nextsector++; - if (newsector == 0xFFFF) + if (newsector == 0xffff) { /* Unable to find a free sector!!! */ @@ -2903,7 +2918,7 @@ static inline int smart_llformat(FAR struct smart_struct_s *dev, unsigned long a /* Set the sector logical sector to zero and setup the header status */ -#if ( CONFIG_SMARTFS_ERASEDSTATE == 0xFF ) +#if ( CONFIG_SMARTFS_ERASEDSTATE == 0xff ) *((FAR uint16_t *) sectorheader->logicalsector) = 0; sectorheader->status = (uint8_t) ~(SMART_STATUS_COMMITTED | SMART_STATUS_VERBITS | SMART_STATUS_SIZEBITS) | SMART_STATUS_VERSION | @@ -2912,14 +2927,14 @@ static inline int smart_llformat(FAR struct smart_struct_s *dev, unsigned long a sectorheader->status &= ~SMART_STATUS_CRC; #endif /* CONFIG_MTD_SMART_ENABLE_CRC */ -#else /* CONFIG_SMARTFS_ERASEDSTATE == 0xFF */ - *((FAR uint16_t *) sectorheader->logicalsector) = 0xFFFF; +#else /* CONFIG_SMARTFS_ERASEDSTATE == 0xff */ + *((FAR uint16_t *) sectorheader->logicalsector) = 0xffff; sectorheader->status = (uint8_t) (SMART_STATUS_COMMITTED | SMART_STATUS_VERSION | sectsize); #ifdef CONFIG_MTD_SMART_ENABLE_CRC sectorheader->status |= SMART_STATUS_CRC; #endif /* CONFIG_MTD_SMART_ENABLE_CRC */ -#endif /* CONFIG_SMARTFS_ERASEDSTATE == 0xFF */ +#endif /* CONFIG_SMARTFS_ERASEDSTATE == 0xff */ /* Now add the format signature to the sector */ @@ -2933,7 +2948,7 @@ static inline int smart_llformat(FAR struct smart_struct_s *dev, unsigned long a /* Record the number of root directory entries we have */ - dev->rwbuffer[SMART_FMT_ROOTDIRS_POS] = (uint8_t) (arg & 0xFF); + dev->rwbuffer[SMART_FMT_ROOTDIRS_POS] = (uint8_t) (arg & 0xff); #ifdef CONFIG_SMART_CRC_8 sectorheader->crc8 = smart_calc_sector_crc(dev); @@ -3059,7 +3074,7 @@ static int smart_relocate_sector(FAR struct smart_struct_s *dev, /* Using 8-bit sequence */ header->seq++; - if (header->seq == 0xFF) + if (header->seq == 0xff) { header->seq = 1; } @@ -3070,7 +3085,7 @@ static int smart_relocate_sector(FAR struct smart_struct_s *dev, /* Using 16-bit sequence and no CRC */ (*((FAR uint16_t *) &header->seq))++; - if (*((FAR uint16_t *) &header->seq) == 0xFFFF) + if (*((FAR uint16_t *) &header->seq) == 0xffff) { *((FAR uint16_t *) &header->seq) = 1; } @@ -3086,7 +3101,7 @@ static int smart_relocate_sector(FAR struct smart_struct_s *dev, /* First pre-commit the sector */ -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff header->status &= ~(SMART_STATUS_COMMITTED | SMART_STATUS_CRC); #else header->status |= SMART_STATUS_COMMITTED | SMART_STATUS_CRC; @@ -3109,7 +3124,7 @@ static int smart_relocate_sector(FAR struct smart_struct_s *dev, #else /* CONFIG_MTD_SMART_ENABLE_CRC */ -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff header->status |= SMART_STATUS_COMMITTED; #else header->status &= ~SMART_STATUS_COMMITTED; @@ -3124,7 +3139,7 @@ static int smart_relocate_sector(FAR struct smart_struct_s *dev, offset = newsector * dev->mtdBlksPerSector * dev->geo.blocksize + offsetof(struct smart_sect_header_s, status); -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff newstatus = header->status & ~SMART_STATUS_COMMITTED; #else newstatus = header->status | SMART_STATUS_COMMITTED; @@ -3139,7 +3154,7 @@ static int smart_relocate_sector(FAR struct smart_struct_s *dev, /* Release the old physical sector */ -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff newstatus = header->status & ~(SMART_STATUS_RELEASED | SMART_STATUS_COMMITTED); #else newstatus = header->status | SMART_STATUS_RELEASED | SMART_STATUS_COMMITTED; @@ -3267,7 +3282,7 @@ static int smart_relocate_block(FAR struct smart_struct_s *dev, uint16_t block) if (allocsector) { newsector = smart_findfreephyssector(dev, FALSE); - if (newsector == 0xFFFF) + if (newsector == 0xffff) { /* Unable to find a free sector!!! */ @@ -3299,7 +3314,7 @@ static int smart_relocate_block(FAR struct smart_struct_s *dev, uint16_t block) /* Find a new sector where it can live, NOT in this erase block */ newsector = smart_findfreephyssector(dev, FALSE); - if (newsector == 0xFFFF) + if (newsector == 0xffff) { /* Unable to find a free sector!!! */ @@ -3441,14 +3456,14 @@ static int smart_findfreephyssector(FAR struct smart_struct_s *dev, retry: #endif allocfreecount = 0; - allocblock = 0xFFFF; + allocblock = 0xffff; #ifdef CONFIG_MTD_SMART_WEAR_LEVEL wornfreecount = 0; - wornblock = 0xFFFF; + wornblock = 0xffff; wornlevel = 15; maxwearlevel = 0; #endif - physicalsector = 0xFFFF; + physicalsector = 0xffff; if (++dev->lastallocblock >= dev->neraseblocks) { dev->lastallocblock = 0; @@ -3514,7 +3529,7 @@ retry: /* Check if we found an allocblock. */ - if (allocblock == 0xFFFF) + if (allocblock == 0xffff) { /* No un-worn blocks with free sectors */ @@ -3558,7 +3573,7 @@ retry: /* Test if we found a worn block with free sectors */ - if (wornblock != 0xFFFF) + if (wornblock != 0xffff) { allocblock = wornblock; } @@ -3624,9 +3639,9 @@ retry: return -1; } - if ((*((FAR uint16_t *) header.logicalsector) == 0xFFFF) && + if ((*((FAR uint16_t *) header.logicalsector) == 0xffff) && #if SMART_STATUS_VERSION == 1 - (*((FAR uint16_t *) &header.seq) == 0xFFFF) && + (*((FAR uint16_t *) &header.seq) == 0xffff) && #else (header.seq == CONFIG_SMARTFS_ERASEDSTATE) && #endif @@ -3639,7 +3654,7 @@ retry: } } - if (physicalsector == 0xFFFF) + if (physicalsector == 0xffff) { ferr("ERROR: Program bug! Expected a free sector\n"); } @@ -3700,7 +3715,7 @@ static int smart_garbagecollect(FAR struct smart_struct_s *dev) { /* Find the block with the most released sectors */ - collectblock = 0xFFFF; + collectblock = 0xffff; releasemax = 0; for (x = 0; x < dev->neraseblocks; x++) { @@ -3731,7 +3746,7 @@ static int smart_garbagecollect(FAR struct smart_struct_s *dev) //releasemax = smart_get_count(dev, dev->releasecount, collectblock); - if (collectblock == 0xFFFF) + if (collectblock == 0xffff) { /* Need to collect, but no sectors with released blocks! */ @@ -3801,7 +3816,7 @@ static int smart_write_wearstatus(struct smart_struct_s *dev) sector = 0; remaining = dev->geo.neraseblocks >> 1; - memset(buffer, 0xFF, sizeof(buffer)); + memset(buffer, 0xff, sizeof(buffer)); #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS) if (dev->blockerases > 0) @@ -3932,8 +3947,8 @@ static inline int smart_read_wearstatus(FAR struct smart_struct_s *dev) /* Check for erased state */ -#if ( CONFIG_SMARTFS_ERASEDSTATE == 0xFF ) - if (dev->uneven_wearcount == 0xFFFFFFFF) +#if ( CONFIG_SMARTFS_ERASEDSTATE == 0xff ) + if (dev->uneven_wearcount == 0xffffffff) { dev->uneven_wearcount = 0; } @@ -3943,8 +3958,8 @@ static inline int smart_read_wearstatus(FAR struct smart_struct_s *dev) /* Get the block erases count */ dev->blockerases = *((uint32_t *) buffer); -#if ( CONFIG_SMARTFS_ERASEDSTATE == 0xFF ) - if (dev->blockerases == 0xFFFFFFFF) +#if ( CONFIG_SMARTFS_ERASEDSTATE == 0xff ) + if (dev->blockerases == 0xffffffff) { dev->blockerases = 0; } @@ -3979,7 +3994,7 @@ static inline int smart_read_wearstatus(FAR struct smart_struct_s *dev) #else physsector = smart_cache_lookup(dev, req.logsector); #endif - if ((sector != 0) && (physsector == 0xFFFF)) + if ((sector != 0) && (physsector == 0xffff)) { #ifdef CONFIG_FS_WRITABLE @@ -4073,7 +4088,7 @@ static int smart_write_alloc_sector(FAR struct smart_struct_s *dev, #endif sectsize = dev->sectorsize >> 7; -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff header->status = ~(SMART_STATUS_COMMITTED | SMART_STATUS_SIZEBITS | SMART_STATUS_VERBITS) | SMART_STATUS_VERSION | sectsize; #ifdef CONFIG_MTD_SMART_ENABLE_CRC @@ -4238,7 +4253,7 @@ static int smart_writesector(FAR struct smart_struct_s *dev, #else physsector = smart_cache_lookup(dev, req->logsector); #endif - if (physsector == 0xFFFF) + if (physsector == 0xffff) { ferr("ERROR: Logical sector %d not allocated\n", req->logsector); ret = -EINVAL; @@ -4294,7 +4309,7 @@ static int smart_writesector(FAR struct smart_struct_s *dev, /* Test if the next byte can be written to the flash */ byte = dev->rwbuffer[sizeof(struct smart_sect_header_s) + req->offset + x]; -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff if (((byte ^ req->buffer[x]) | byte) != byte) { needsrelocate = TRUE; @@ -4322,7 +4337,7 @@ static int smart_writesector(FAR struct smart_struct_s *dev, oldphyssector = physsector; physsector = smart_findfreephyssector(dev, FALSE); - if (physsector == 0xFFFF) + if (physsector == 0xffff) { ferr("ERROR: Error relocating sector %d\n", req->logsector); ret = -EIO; @@ -4336,7 +4351,7 @@ static int smart_writesector(FAR struct smart_struct_s *dev, { #endif header->seq++; - if (header->seq == 0xFF) + if (header->seq == 0xff) { header->seq = 0; } @@ -4345,13 +4360,13 @@ static int smart_writesector(FAR struct smart_struct_s *dev, else { (*((FAR uint16_t *) &header->seq))++; - if (*((FAR uint16_t *) &header->seq) == 0xFFFF) + if (*((FAR uint16_t *) &header->seq) == 0xffff) *((FAR uint16_t *) &header->seq) = 1; } #else header->seq++; #endif -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff header->status |= SMART_STATUS_COMMITTED; #else header->status &= SMART_STATUS_COMMITTED; @@ -4409,7 +4424,7 @@ static int smart_writesector(FAR struct smart_struct_s *dev, /* Commit the sector ahead of time. The CRC will protect us */ -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff header->status &= ~(SMART_STATUS_COMMITTED | SMART_STATUS_CRC); #else header->status |= SMART_STATUS_COMMITTED | SMART_STATUS_CRC; @@ -4453,7 +4468,7 @@ static int smart_writesector(FAR struct smart_struct_s *dev, #ifndef CONFIG_MTD_SMART_ENABLE_CRC -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff byte = header->status & ~SMART_STATUS_COMMITTED; #else byte = header->status | SMART_STATUS_COMMITTED; @@ -4471,7 +4486,7 @@ static int smart_writesector(FAR struct smart_struct_s *dev, /* Release the old physical sector */ -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff byte = header->status & ~(SMART_STATUS_RELEASED | SMART_STATUS_COMMITTED); #else byte = header->status | SMART_STATUS_RELEASED | SMART_STATUS_COMMITTED; @@ -4614,7 +4629,7 @@ static int smart_readsector(FAR struct smart_struct_s *dev, #else physsector = smart_cache_lookup(dev, req->logsector); #endif - if (physsector == 0xFFFF) + if (physsector == 0xffff) { ferr("ERROR: Logical sector %d not allocated\n", req->logsector); ret = -EINVAL; @@ -4729,7 +4744,7 @@ errout: static inline int smart_allocsector(FAR struct smart_struct_s *dev, unsigned long requested) { - uint16_t logsector = 0xFFFF; /* Logical sector number selected */ + uint16_t logsector = 0xffff; /* Logical sector number selected */ uint16_t physicalsector; /* The selected physical sector */ #ifndef CONFIG_MTD_SMART_ENABLE_CRC int ret; @@ -4745,7 +4760,7 @@ static inline int smart_allocsector(FAR struct smart_struct_s *dev, { /* Do a garbage collect and then test freesectors again */ - if (dev->releasesectors + dev->freesectors > dev->availSectPerBlk + 4) + if (dev->releasesectors + dev->freesectors > dev->sectorsPerBlk + 4) { for (x = 0; x < dev->availSectPerBlk; x++) @@ -4814,7 +4829,7 @@ static inline int smart_allocsector(FAR struct smart_struct_s *dev, /* Check if we need to scan for an available logical sector */ - if (logsector == 0xFFFF) + if (logsector == 0xffff) { /* Loop through all sectors and find one to allocate */ @@ -4865,7 +4880,7 @@ static inline int smart_allocsector(FAR struct smart_struct_s *dev, /* Test for an error allocating a sector */ - if (logsector == 0xFFFF) + if (logsector == 0xffff) { /* Hmmm. We think we had enough logical sectors, but * something happened and we didn't find any free @@ -4896,6 +4911,11 @@ static inline int smart_allocsector(FAR struct smart_struct_s *dev, logsector, physicalsector, physicalsector / dev->sectorsPerBlk, dev->freesectors, dev->releasecount); + if (physicalsector == 0xffff) + { + return -ENOSPC; + } + #ifdef CONFIG_MTD_SMART_ENABLE_CRC /* When CRC is enabled, we don't write the header to the device until @@ -5023,7 +5043,7 @@ static inline int smart_freesector(FAR struct smart_struct_s *dev, /* Mark the sector as released */ -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF +#if CONFIG_SMARTFS_ERASEDSTATE == 0xff header.status &= ~SMART_STATUS_RELEASED; #else header.status |= SMART_STATUS_RELEASED; @@ -5055,7 +5075,7 @@ static inline int smart_freesector(FAR struct smart_struct_s *dev, dev->sMap[logicalsector] = (uint16_t) -1; #else dev->sBitMap[logicalsector >> 3] &= ~(1 << (logicalsector & 0x07)); - smart_update_cache(dev, logicalsector, 0xFFFF); + smart_update_cache(dev, logicalsector, 0xffff); #endif /* If this block has only released blocks, then erase it */ @@ -5291,19 +5311,13 @@ int smart_initialize(int minor, FAR struct mtd_dev_s *mtd, FAR const char *partn /* Allocate a SMART device structure */ - dev = (FAR struct smart_struct_s *)kmm_malloc(sizeof(struct smart_struct_s)); + dev = (FAR struct smart_struct_s *)smart_malloc(NULL, sizeof(struct smart_struct_s), + "Dev struct"); if (dev) { /* Initialize the SMART device structure */ dev->mtd = mtd; -#ifdef CONFIG_MTD_SMART_ALLOC_DEBUG - dev->bytesalloc = 0; - for (totalsectors = 0; totalsectors < SMART_MAX_ALLOCS; totalsectors++) - { - dev->alloc[totalsectors].ptr = NULL; - } -#endif /* Get the device geometry. (casting to uintptr_t first eliminates * complaints on some architectures where the sizeof long is different @@ -5380,6 +5394,15 @@ int smart_initialize(int minor, FAR struct mtd_dev_s *mtd, FAR const char *partn dev->minor = minor; #endif + /* Do a scan of the device */ + + ret = smart_scan(dev); + if (ret < 0) + { + ferr("ERROR: smart_scan failed: %d\n", -ret); + goto errout; + } + /* Create a MTD block device name */ #ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS @@ -5431,15 +5454,6 @@ int smart_initialize(int minor, FAR struct mtd_dev_s *mtd, FAR const char *partn ferr("ERROR: register_blockdriver failed: %d\n", -ret); goto errout; } - - /* Do a scan of the device */ - - ret = smart_scan(dev); - if (ret < 0) - { - ferr("ERROR: smart_scan failed: %d\n", -ret); - goto errout; - } } #ifdef CONFIG_SMART_DEV_LOOP diff --git a/drivers/serial/ptmx.c b/drivers/serial/ptmx.c new file mode 100644 index 00000000000..d0439c14f31 --- /dev/null +++ b/drivers/serial/ptmx.c @@ -0,0 +1,330 @@ +/**************************************************************************** + * drivers/serial/ptmx.c + * + * Copyright (C) 2016 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 +#include +#include + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifndef CONFIG_PTY_MAXPTY +# define CONFIG_PTY_MAXPTY 32 +#endif + +#if CONFIG_PTY_MAXPTY > 256 +# define CONFIG_PTY_MAXPTY 256 +#endif + +#define PTY_MAX ((CONFIG_PTY_MAXPTY + 31) & ~31) +#define INDEX_MAX (PTY_MAX >> 5) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* PTMX device state */ + +struct ptmx_dev_s +{ + uint8_t px_next; /* Next minor number to allocate */ + sem_t px_exclsem; /* Supports mutual exclusion */ + uint32_t px_alloctab[INDEX_MAX]; /* Set of allocated PTYs */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int ptmx_open(FAR struct file *filep); +static ssize_t ptmx_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t ptmx_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_ptmx_fops = +{ + ptmx_open, /* open */ + NULL, /* close */ + ptmx_read, /* read */ + ptmx_write, /* write */ + NULL, /* seek */ + NULL /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , NULL /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL /* unlink */ +#endif +}; + +static struct ptmx_dev_s g_ptmx; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ptmx_semtake and ptmx_semgive + * + * Description: + * This is just a wrapper to handle the annoying behavior of semaphore + * waits that return due to the receipt of a signal. + * + ****************************************************************************/ + +static void ptmx_semtake(void) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&g_ptmx.px_exclsem) != 0) + { + /* The only case that an error should occur here is if the wait was + * awakened by a signal. + */ + + DEBUGASSERT(errno == EINTR); + } +} + +#define ptmx_semgive() sem_post(&g_ptmx.px_exclsem) + +/**************************************************************************** + * Name: ptmx_minor_allocate + * + * Description: + * Allocate a new unique PTY minor number. + * + * Assumptions: + * Caller hold the px_exclsem + * + ****************************************************************************/ + +static int ptmx_minor_allocate(FAR struct ptmx_dev_s *ptmx) +{ + uint8_t startaddr = g_ptmx.px_next; + uint8_t minor; + int index; + int bitno; + + /* Loop until we find a valid device address */ + + for (; ; ) + { + /* Try the next device address */ + + minor = g_ptmx.px_next; + if (g_ptmx.px_next >= PTY_MAX) + { + g_ptmx.px_next = 0; + } + else + { + g_ptmx.px_next++; + } + + /* Is this address already allocated? */ + + index = minor >> 5; + bitno = minor & 31; + if ((g_ptmx.px_alloctab[index] & (1 << bitno)) == 0) + { + /* No... allocate it now */ + + g_ptmx.px_alloctab[index] |= (1 << bitno); + return (int)minor; + } + + /* This address has already been allocated. The following logic will + * prevent (unexpected) infinite loops. + */ + + if (startaddr == minor) + { + /* We are back where we started... the are no free device address */ + + return -ENOMEM; + } + } +} + +/**************************************************************************** + * Name: ptmx_minor_free + * + * Description: + * De-allocate a PTY minor number. + * + * Assumptions: + * Caller hold the px_exclsem + * + ****************************************************************************/ + +static void ptmx_minor_free(uint8_t minor) +{ + int index; + int bitno; + + /* Free the address by clearing the associated bit in the px_alloctab[]; */ + + index = minor >> 5; + bitno = minor & 31; + + DEBUGASSERT((g_ptmx.px_alloctab[index] |= (1 << bitno)) != 0); + g_ptmx.px_alloctab[index] &= ~(1 << bitno); + + /* Reset the next pointer if the one just released has a lower value */ + + if (minor < g_ptmx.px_next) + { + g_ptmx.px_next = minor; + } +} + +/**************************************************************************** + * Name: ptmx_open + ****************************************************************************/ + +static int ptmx_open(FAR struct file *filep) +{ + char devname[16]; + int minor; + int fd; + int ret; + + /* Get exclusive access */ + + ptmx_semtake(); + + /* Allocate a PTY minor */ + + minor = ptmx_minor_allocate(); + if (minor < 0) + { + ret = minor; + goto errout_with_sem; + } + + /* Create the master slave pair */ + + ret = pty_register(minor); + if (ret < 0) + { + goto errout_with_minor; + } + + /* Open the master side */ + + snprintf(devname, 16, "/dev/ttyp%d", minor); + fd = open(devname, O_RDWR); + DEBUGASSERT(fd >= 0); /* open() should never fail */ + + /* No unlink the master. This will remove it from the VFS namespace, + * the the driver will still persist because of the open count on the + * driver. + */ + + ret = unlink(devname); + DEBUGASSERT(ret >= 0); /* unlink() should never fail */ + UNUSED(ret); + + /* Return the master file descriptor */ + + ptmx_semgive(); + return fd; + +errout_with_minor: + ptmx_minor_free(minor); + +errout_with_sem: + ptmx_semgive(); + return ret; +} + +/**************************************************************************** + * Name: ptmx_read + ****************************************************************************/ + +static ssize_t ptmx_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + return 0; /* Return EOF */ +} + +/**************************************************************************** + * Name: ptmx_write + ****************************************************************************/ + +static ssize_t ptmx_write(FAR struct file *filep, FAR const char *buffer, size_t len) +{ + return len; /* Say that everything was written */ +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ptmx_register + * + * Description: + * Register /dev/null + * + ****************************************************************************/ + +void ptmx_register(void) +{ + FAR struct ptmx_dev_s *ptmx; + + /* Initialize driver state */ + + sem_init(&g_ptmx.px_exclsem, 0, 1); + + /* Register the PTMX driver */ + + (void)register_driver("/dev/ptmx", &g_ptmx_fops, 0666, NULL); +} diff --git a/drivers/serial/pty.c b/drivers/serial/pty.c new file mode 100644 index 00000000000..2719d6c35df --- /dev/null +++ b/drivers/serial/pty.c @@ -0,0 +1,559 @@ +/**************************************************************************** + * drivers/serial/pty.c + * + * Copyright (C) 2016 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 +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int pty_open(FAR struct file *filep); +static int pty_close(FAR struct file *filep); +static ssize_t pty_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t pty_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static int pty_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +#ifndef CONFIG_DISABLE_POLL +static int pty_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int pty_unlink(FAR struct inode *inode); +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This device structure describes on memory of the PTY device pair */ + +struct pty_devpair_s; +struct pty_dev_s +{ + FAR struct pty_common_s *pd_devpair; + struct file pd_src; /* Provides data to read() method (pipe output) */ + struct file pd_sink; /* Accepts data from write() method (pipe input) */ +}; + +/* This structure describes the pipe pair */ + +struct pty_devpair_s +{ + struct pty_dev_s pp_ptyp; /* /dev/ptypN device */ + struct pty_dev_s pp_ttyp; /* /dev/ttypN device */ + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + uint8_t pp_minor; /* Minor device number */ + uint16_t pp_nopen; /* Open file count */ + sem_t pp_exclsem; /* Mutual exclusion */ + bool pp_unlinked; /* File has been unlinked */ +#endif +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations pty_fops = +{ +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + pty_open, /* open */ + pty_close, /* close */ +#else + NULL, /* open */ + NULL, /* close */ +#endif + pty_read, /* read */ + pty_write, /* write */ + NULL, /* seek */ + pty_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , pty_poll /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , pty_unlink /* unlink */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pty_semtake + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static void pty_semtake(FAR struct pty_common_s *devpair) +{ + while (sem_wait(&devpair->pp_exclsem) < 0) + { + DEBUGASSERT(errno == EINTR); + } +} +#endif + +/**************************************************************************** + * Name: pty_semgive + ****************************************************************************/ + +#define pty_semgive(c) sem_post(&(c)->pp_exclsem) + +/**************************************************************************** + * Name: pty_destroy + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static void pty_destroy(FAR struct pty_common_s *devpair) +{ + char devname[16]; + + /* Un-register /dev/ptypN */ + + snprintf(devname, 16, "/dev/pp_ptyp%d", (int)devpair->pp_minor); + (void)unregister_driver(devname); + + /* Un-register /dev/ptypN */ + + snprintf(devname, 16, "/dev/ttyp%d", (int)devpair->pp_minor); + (void)unregister_driver(devname); + + /* Close the contained file structures */ + + (void)file_close_detached(&devpair->pp_ptyp.pd_src); + (void)file_close_detached(&devpair->pp_ptyp.pd_sink); + (void)file_close_detached(&devpair->pp_ttyp.pd_src); + (void)file_close_detached(&devpair->pp_ttyp.pd_sink); + + /* And free the device structure */ + + sem_destroy(&devpair->pp_exclsem); + kmm_free(upper); +} +#endif + +/**************************************************************************** + * Name: pty_open + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int pty_open(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct pty_dev_s *dev; + FAR struct pty_common_s *devpair; + int ret; + + DEBUGASSERT(filep != NULL && file->f_inode != NULL); + inode = filep->f_inode; + dev = inode->i_private; + DEBUGASSERT(dev != NULL && dev->pd_devpair != NULL); + devpair = dev->pd_devpair; + + /* Get exclusive access */ + + pty_semtake(devpair); + + /* If one side of the driver has been unlinked, then refuse further + * opens. + */ + + if (cmd->pp_unlinked) + { + ret = -EIDRAM + } + else + { + /* Increment the count of open references on the driver */ + + devpair->pp_nopen++; + DEBUGASSERT(devpair->pp_nopen > 0); + + ret = OK; + } + + pty_semgive(devpair); + return ret; +} +#endif + +/**************************************************************************** + * Name: pty_open + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int pty_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct pty_dev_s *dev; + FAR struct pty_common_s *devpair; + + DEBUGASSERT(filep != NULL && file->f_inode != NULL); + inode = filep->f_inode; + dev = inode->i_private; + DEBUGASSERT(dev != NULL && dev->pd_devpair != NULL); + devpair = dev->pd_devpair; + + /* Get exclusive access */ + + pty_semtake(devpair); + + /* Is this the last open reference? */ + + DEBUGASSERT(devpair->pp_nopen > 0); + if (devpair->pp_nopen <= 1 && devpair->pp_unlinked) + { + /* Free the device pair now (without freeing the semaphore) */ + + pty_destroy(devpair); + return OK; + } + else + { + /* Otherwise just decrement the open count */ + + devpair->pp_nopen--; + } + + pty_semgive(devpair); + return OK; +} +#endif + +/**************************************************************************** + * Name: pty_read + ****************************************************************************/ + +static ssize_t pty_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct pty_dev_s *dev; + + DEBUGASSERT(filep != NULL && file->f_inode != NULL); + inode = filep->f_inode; + dev = inode->i_private; + DEBUGASSERT(dev != NULL); + + return file_read(&dev->src, buffer, len); +} + +/**************************************************************************** + * Name: pty_write + ****************************************************************************/ + +static ssize_t pty_write(FAR struct file *filep, FAR const char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct pty_dev_s *dev; + + DEBUGASSERT(filep != NULL && file->f_inode != NULL); + inode = filep->f_inode; + dev = inode->i_private; + DEBUGASSERT(dev != NULL); + + return file_write(&dev->src, buffer, len); +} + +/**************************************************************************** + * Name: pty_ioctl + * + * Description: + * The standard ioctl method. This is where ALL of the PWM work is done. + * + ****************************************************************************/ + +static int pty_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct pty_dev_s *dev; + int ret; + + DEBUGASSERT(filep != NULL && file->f_inode != NULL); + inode = filep->f_inode; + dev = inode->i_private; + DEBUGASSERT(dev != NULL); + + /* Handle IOCTL commands */ + + switch (cmd) + { + /* PTY IOCTL commands would be handled here */ + /* There aren't any yet */ + + /* Any unrecognized IOCTL commands will be passed to the contained + * pipe driver. + */ + + default: + { + ret = file_ioctl(dev->pd_src, cmd, arg); + if (ret >= 0 || ret == -ENOTTY) + { + ret = file_ioctl(dev->pd_sink, cmd, arg); + } + } + break; + } + + sem_post(&upper->exclsem); + return ret; +} + +/**************************************************************************** + * Name: pty_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int pty_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ +#warning Missing logic +} +#endif + +/**************************************************************************** + * Name: pty_unlink + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int pty_unlink(FAR struct inode *inode) +{ + FAR struct inode *inode; + FAR struct pty_dev_s *dev; + FAR struct pty_common_s *devpair; + + DEBUGASSERT(filep != NULL && file->f_inode != NULL); + inode = filep->f_inode; + dev = inode->i_private; + DEBUGASSERT(dev != NULL && dev->pd_devpair != NULL); + devpair = dev->pd_devpair; + + /* Get exclusive access */ + + pty_semtake(devpair); + + /* Indicate that the driver has been unlinked */ + + devpair->pp_unlinked = true; + + /* If there are no further open references to the driver, then commit + * Hara-Kiri now. + */ + + if (devpair->pp_nopen == 0) + { + pty_destroy(devpair); + return OK; + } + + pty_semgive(devpair); + return OK; +} +#endif +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pty_register + * + * Input Parameters: + * + * Description: + * Register /dev/ttypN and /dev/ptpN where N=minor number + * + ****************************************************************************/ + +int pty_register(int minor) +{ + FAR struct pty_devpair_s *devpair; + int pipe_a[2]; + int pipe_b[2]; + char devname[16]; + + /* Allocate a device instance */ + + devpair = kmm_zalloc(sizeof(struct pty_devpair_s)); + if (devpair == NULL) + { + return -ENOMEM; + } + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + sem_init(&devpair->pp_exclsem, 0, 1); + devpair->pp_minor = minor; +#endif + devpair->pp_ptyp.pd_devpair = devpair; + devpair->pp_ttyp.pd_devpair = devpair; + + /* Create two pipes */ + + ret = pipe(pipe_a); + if (ret < 0) + { + goto errout_with_devpair; + } + + ret = pipe(pipe_b); + if (ret < 0) + { + goto errout_with_pipea; + } + + /* Detach the pipe file descriptors (closing them in the process) + * + * fd[0] is for reading; + * fd[1] is for writing. + */ + + ret = file_detach(pipe_a[0], &devpair->pp_ptyp.pd_src); + if (ret < 0) + { + goto errout_with_pipeb; + } + + pipe_a[0] = -1; + + ret = file_detach(pipe_a[1], &devpair->pp_ttyp.pd_sink); + if (ret < 0) + { + goto errout_with_pipeb; + } + + pipe_a[1] = -1; + + ret = file_detach(pipe_b[0], &devpair->pp_ttyp.pd_src); + if (ret < 0) + { + goto errout_with_pipeb; + } + + pipe_b[0] = -1; + + ret = file_detach(pipe_b[1], &devpair->pp_ptyp.pd_sink); + if (ret < 0) + { + goto errout_with_pipeb; + } + + pipe_b[1] = -1; + + /* Register /dev/ptypN */ + + snprintf(devname, 16, "/dev/pts/%d", minor); + + ret = register_driver(devname, &pty_fops, 0666, &devpair->pp_ptyp); + if (ret < 0) + { + goto errout_with_pipeb; + } + + /* Register /dev/ptypN */ + + snprintf(devname, 16, "/dev/ttyp%d", minor); + + ret = register_driver(devname, &pty_fops, 0666, &devpair->pp_ttyp); + if (ret < 0) + { + goto errout_with_ptyp; + } + + return OK; + +errout_with_ptyp: + snprintf(devname, 16, "/dev/ptyp%d", minor); + (void)unregister_driver(devname) + +errout_with_pipeb: + if (pipe_b[0] >= 0) + { + close(pipe_b[0]); + } + else + { + (void)file_close_detached(&devpair->pp_ptyp.pd_src); + } + + if (pipe_b[1] >= 0) + { + close(pipe_b[1]); + } + else + { + (void)file_close_detached(&devpair->pp_ttyp.pd_sink); + } + +errout_with_pipea: + if (pipe_a[0] >= 0) + { + close(pipe_a[0]); + } + else + { + (void)file_close_detached(&devpair->pp_ttyp.pd_src); + } + + if (pipe_a[1] >= 0) + { + close(pipe_a[1]); + } + else + { + (void)file_close_detached(&devpair->pp_ptyp.pd_sink); + } + +errout_with_devpair: +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + sem_destroy(&devpair->pp_exclsem); +#endif + kmm_free(devpair); + return ret; +} diff --git a/include/nuttx/analog/adc.h b/include/nuttx/analog/adc.h index 0044c03364d..a566f2a0ded 100644 --- a/include/nuttx/analog/adc.h +++ b/include/nuttx/analog/adc.h @@ -72,6 +72,12 @@ # define CONFIG_ADC_FIFOSIZE 255 #endif +#define ADC_RESET(dev) ((dev)->ad_ops->ao_reset((dev))) +#define ADC_SETUP(dev) ((dev)->ad_ops->ao_setup((dev))) +#define ADC_SHUTDOWN(dev) ((dev)->ad_ops->ao_shutdown((dev))) +#define ADC_RXINT(dev) ((dev)->ad_ops->ao_rxint((dev))) +#define ADC_IOCTL(dev,cmd,arg) ((dev)->ad_ops->ao_ioctl((dev),(cmd),(arg))) + /************************************************************************************ * Public Types ************************************************************************************/ diff --git a/libc/math/lib_erf.c b/libc/math/lib_erf.c index 1923638dbad..215c1017204 100644 --- a/libc/math/lib_erf.c +++ b/libc/math/lib_erf.c @@ -67,6 +67,7 @@ double erf(double x) sign = (x >= 0 ? 1 : -1); t = 1.0/(1.0 + p*x); - return sign * (1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * expf(-x * x)); + return sign * (1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * + (double)expf(-x * x)); } #endif diff --git a/libc/math/lib_logf.c b/libc/math/lib_logf.c index 2d097d228e3..9abc5eff986 100644 --- a/libc/math/lib_logf.c +++ b/libc/math/lib_logf.c @@ -32,6 +32,8 @@ #include #include +#define FLT_MAX_EXP_X 88.0F + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -50,25 +52,25 @@ float logf(float x) ey = exp(y); y -= (ey - x) / ey; - if (y > 700.0F) + if (y > FLT_MAX_EXP_X) { - y = 700.0F; + y = FLT_MAX_EXP_X; } - if (y < -700.0F) + if (y < -FLT_MAX_EXP_X) { - y = -700.0F; + y = -FLT_MAX_EXP_X; } epsilon = (fabsf(y) > 1.0F) ? fabsf(y) * FLT_EPSILON : FLT_EPSILON; } - if (y == 700.0F) + if (y == FLT_MAX_EXP_X) { return INFINITY; } - if (y == -700.0F) + if (y == -FLT_MAX_EXP_X) { return INFINITY; }