Merged nuttx/nuttx into master

This commit is contained in:
Young 2016-07-15 11:02:10 +08:00
commit 426dac3747
33 changed files with 2268 additions and 420 deletions

View File

@ -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).

View File

@ -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()

View File

@ -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();

View File

@ -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"

View File

@ -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 */

View File

@ -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 <gnutt@nuttx.org>
*
* 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

View File

@ -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.
*/

View File

@ -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 <gnutt@nuttx.org>
*
* 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
}

View File

@ -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 <gnutt@nuttx.org>
*
* 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 */

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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()

View File

@ -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;

View File

@ -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];

View File

@ -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

View File

@ -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 <subdir> 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 <subdir> 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 <subdir> 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.

View File

@ -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
#

View File

@ -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

View File

@ -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}"

View File

@ -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

View File

@ -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 */

View File

@ -0,0 +1,322 @@
/************************************************************************************
* configs/freedom-k64f/src/k64_automount.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#if defined(CONFIG_FS_AUTOMOUNTER_DEBUG) && !defined(CONFIG_DEBUG_FS)
# define CONFIG_DEBUG_FS 1
#endif
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/clock.h>
#include <nuttx/fs/automount.h>
#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 */

View File

@ -39,112 +39,27 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <stdbool.h>
#include <stdio.h>
#include <syslog.h>
#include <errno.h>
#include <debug.h>
#ifdef CONFIG_KINETIS_SDHC
# include <nuttx/sdio.h>
# include <nuttx/mmcsd.h>
#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);

View File

@ -0,0 +1,251 @@
/****************************************************************************
* config/freedom-k64f/src/k64_sdhc.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <stdbool.h>
#include <stdio.h>
#include <debug.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/sdio.h>
#include <nuttx/mmcsd.h>
#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 */

View File

@ -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;
}

View File

@ -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");

View File

@ -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 <pettitkd@gmail.com>
*
* 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

330
drivers/serial/ptmx.c Normal file
View File

@ -0,0 +1,330 @@
/****************************************************************************
* drivers/serial/ptmx.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <sys/types.h>
#include <stdbool.h>
#include <string.h>
#include <poll.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
/****************************************************************************
* 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);
}

559
drivers/serial/pty.c Normal file
View File

@ -0,0 +1,559 @@
/****************************************************************************
* drivers/serial/pty.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <sys/types.h>
#include <stdbool.h>
#include <unistd.h>
#include <semaphore.h>
#include <string.h>
#include <poll.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
/****************************************************************************
* 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;
}

View File

@ -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
************************************************************************************/

View File

@ -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

View File

@ -32,6 +32,8 @@
#include <math.h>
#include <float.h>
#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;
}