You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/03/03 14:53:06 UTC
[incubator-nuttx] branch pr423 updated: NXP Freedom K28F Board
SD-Card support (#423)
This is an automated email from the ASF dual-hosted git repository.
gnutt pushed a commit to branch pr423
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/pr423 by this push:
new e9b3fcd NXP Freedom K28F Board SD-Card support (#423)
e9b3fcd is described below
commit e9b3fcdde2a77f884293bba98ba2097c58d37952
Author: johannes-nivus <jo...@nivus.com>
AuthorDate: Tue Mar 3 15:52:55 2020 +0100
NXP Freedom K28F Board SD-Card support (#423)
* Adds SDHC support for NXP Freedom-K28F
---
arch/arm/src/kinetis/kinetis_sdhc.c | 44 +++
boards/arm/kinetis/freedom-k28f/Kconfig | 30 +-
boards/arm/kinetis/freedom-k28f/include/board.h | 11 +
boards/arm/kinetis/freedom-k28f/src/Makefile | 7 +
boards/arm/kinetis/freedom-k28f/src/freedom-k28f.h | 171 ++++++++++++
.../arm/kinetis/freedom-k28f/src/k28_automount.c | 310 +++++++++++++++++++++
boards/arm/kinetis/freedom-k28f/src/k28_bringup.c | 37 +++
boards/arm/kinetis/freedom-k28f/src/k28_sdhc.c | 240 ++++++++++++++++
8 files changed, 849 insertions(+), 1 deletion(-)
diff --git a/arch/arm/src/kinetis/kinetis_sdhc.c b/arch/arm/src/kinetis/kinetis_sdhc.c
index 81be303..f6c6f7c 100644
--- a/arch/arm/src/kinetis/kinetis_sdhc.c
+++ b/arch/arm/src/kinetis/kinetis_sdhc.c
@@ -307,12 +307,19 @@ static int kinetis_attach(FAR struct sdio_dev_s *dev);
static int kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t arg);
+
+#ifdef CONFIG_SDIO_BLOCKSETUP
+static void kinetis_blocksetup(FAR struct sdio_dev_s *dev,
+ unsigned int blocksize, unsigned int nblocks);
+#endif
+
#ifndef CONFIG_KINETIS_SDHC_DMA
static int kinetis_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
size_t nbytes);
static int kinetis_sendsetup(FAR struct sdio_dev_s *dev,
FAR const uint8_t *buffer, uint32_t nbytes);
#endif
+
static int kinetis_cancel(FAR struct sdio_dev_s *dev);
static int kinetis_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd);
@@ -367,6 +374,9 @@ struct kinetis_dev_s g_sdhcdev =
.clock = kinetis_clock,
.attach = kinetis_attach,
.sendcmd = kinetis_sendcmd,
+#ifdef CONFIG_SDIO_BLOCKSETUP
+ .blocksetup = kinetis_blocksetup,
+#endif
#ifndef CONFIG_KINETIS_SDHC_DMA
.recvsetup = kinetis_recvsetup,
.sendsetup = kinetis_sendsetup,
@@ -1871,6 +1881,40 @@ static int kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
}
/****************************************************************************
+ * Name: kinetis_blocksetup
+ *
+ * Description:
+ * Configure block size and the number of blocks for next transfer
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * blocksize - The selected block size.
+ * nblocklen - The number of blocks to transfer
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_BLOCKSETUP
+static void kinetis_blocksetup(FAR struct sdio_dev_s *dev,
+ unsigned int blocksize,
+ unsigned int nblocks)
+{
+ uint32_t regval;
+
+ mcinfo("blocksize=%ld, total transfer=%ld (%ld blocks)\n", blocksize,
+ blocksize * nblocks, nblocks);
+
+ /* Configure block size for next transfer */
+
+ regval = blocksize << SDHC_BLKATTR_SIZE_SHIFT |
+ nblocks << SDHC_BLKATTR_CNT_SHIFT;
+ putreg32(regval, KINETIS_SDHC_BLKATTR);
+}
+#endif
+
+/****************************************************************************
* Name: kinetis_recvsetup
*
* Description:
diff --git a/boards/arm/kinetis/freedom-k28f/Kconfig b/boards/arm/kinetis/freedom-k28f/Kconfig
index 8a8ba84..928307b 100644
--- a/boards/arm/kinetis/freedom-k28f/Kconfig
+++ b/boards/arm/kinetis/freedom-k28f/Kconfig
@@ -5,4 +5,32 @@
if ARCH_BOARD_FREEDOM_K28F
-endif
+config FRDMK28F_SDHC_AUTOMOUNT
+ bool "SDHC automounter"
+ default n
+ depends on FS_AUTOMOUNTER && KINETIS_SDHC
+
+if FRDMK28F_SDHC_AUTOMOUNT
+
+config FRDMK28F_SDHC_AUTOMOUNT_FSTYPE
+ string "SDHC file system type"
+ default "vfat"
+
+config FRDMK28F_SDHC_AUTOMOUNT_BLKDEV
+ string "SDHC block device"
+ default "/dev/mmcsd0"
+
+config FRDMK28F_SDHC_AUTOMOUNT_MOUNTPOINT
+ string "SDHC mount point"
+ default "/mnt/sdcard"
+
+config FRDMK28F_SDHC_AUTOMOUNT_DDELAY
+ int "SDHC debounce delay (milliseconds)"
+ default 1000
+
+config FRDMK28F_SDHC_AUTOMOUNT_UDELAY
+ int "SDHC unmount retry delay (milliseconds)"
+ default 2000
+
+endif # FRDMK28F_SDHC_AUTOMOUNT
+endif # ARCH_BOARD_FREEDOM_K28F
diff --git a/boards/arm/kinetis/freedom-k28f/include/board.h b/boards/arm/kinetis/freedom-k28f/include/board.h
index a17c39d..8dcee67 100644
--- a/boards/arm/kinetis/freedom-k28f/include/board.h
+++ b/boards/arm/kinetis/freedom-k28f/include/board.h
@@ -415,6 +415,17 @@
#endif
#endif
+/* SDHC */
+
+#ifdef CONFIG_KINETIS_SDHC
+# define PIN_SDHC0_CMD PIN_SDHC0_CMD_1
+# define PIN_SDHC0_D0 PIN_SDHC0_D0_1
+# define PIN_SDHC0_D1 PIN_SDHC0_D1_1
+# define PIN_SDHC0_D2 PIN_SDHC0_D2_1
+# define PIN_SDHC0_D3 PIN_SDHC0_D3_1
+# define PIN_SDHC0_DCLK PIN_SDHC0_DCLK_1
+#endif
+
/* LED definitions **********************************************************/
/* The Freedom K28F has a single RGB LED driven by the K28F as follows:
diff --git a/boards/arm/kinetis/freedom-k28f/src/Makefile b/boards/arm/kinetis/freedom-k28f/src/Makefile
index c2c6c0f..8b7b793 100644
--- a/boards/arm/kinetis/freedom-k28f/src/Makefile
+++ b/boards/arm/kinetis/freedom-k28f/src/Makefile
@@ -52,6 +52,13 @@ CSRCS += k28_userleds.c
endif
endif
+ifeq ($(CONFIG_KINETIS_SDHC),y)
+CSRCS += k28_sdhc.c
+ifeq ($(CONFIG_FS_AUTOMOUNTER),y)
+CSRCS += k28_automount.c
+endif
+endif
+
ifeq ($(CONFIG_PWM),y)
CSRCS += k28_pwm.c
endif
diff --git a/boards/arm/kinetis/freedom-k28f/src/freedom-k28f.h b/boards/arm/kinetis/freedom-k28f/src/freedom-k28f.h
index 0554a43..d1a5856 100644
--- a/boards/arm/kinetis/freedom-k28f/src/freedom-k28f.h
+++ b/boards/arm/kinetis/freedom-k28f/src/freedom-k28f.h
@@ -47,8 +47,95 @@
* Pre-processor Definitions
****************************************************************************/
+/* Application Configuration ************************************************/
+
+/* Assume we have everything */
+
+#define HAVE_MMCSD 1
+#define HAVE_AUTOMOUNTER 1
+
+
+/* SD card support */
+
+#define MMCSD_SLOTNO 0
+
+/* Can't support MMC/SD features if mountpoints are disabled or if SDHC
+ * support is not enabled.
+ */
+
+#if defined(CONFIG_DISABLE_MOUNTPOINT) || !defined(CONFIG_KINETIS_SDHC)
+# undef HAVE_MMCSD
+#endif
+
+#ifdef HAVE_MMCSD
+# if defined(CONFIG_NSH_MMCSDSLOTNO) && CONFIG_NSH_MMCSDSLOTNO != 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 */
+
+# ifndef CONFIG_KINETIS_GPIOIRQ
+# error "CONFIG_KINETIS_GPIOIRQ required for card detect interrupt"
+# endif
+
+# ifndef CONFIG_KINETIS_PORTBINTS
+# error "CONFIG_KINETIS_PORTBINTS required for card detect interrupt"
+# endif
+
+#endif
+
+/* Automounter */
+
+#if !defined(CONFIG_FS_AUTOMOUNTER) || !defined(HAVE_MMCSD)
+# undef HAVE_AUTOMOUNTER
+# undef CONFIG_FRDMK28F_SDHC_AUTOMOUNT
+#endif
+
+#ifndef CONFIG_FRDMK28F_SDHC_AUTOMOUNT
+# undef HAVE_AUTOMOUNTER
+#endif
+
+/* Automounter defaults */
+
+#ifdef HAVE_AUTOMOUNTER
+
+# ifndef CONFIG_FRDMK28F_SDHC_AUTOMOUNT_FSTYPE
+# define CONFIG_FRDMK28F_SDHC_AUTOMOUNT_FSTYPE "vfat"
+# endif
+
+# ifndef CONFIG_FRDMK28F_SDHC_AUTOMOUNT_BLKDEV
+# define CONFIG_FRDMK28F_SDHC_AUTOMOUNT_BLKDEV "/dev/mmcds0"
+# endif
+
+# ifndef CONFIG_FRDMK28F_SDHC_AUTOMOUNT_MOUNTPOINT
+# define CONFIG_FRDMK28F_SDHC_AUTOMOUNT_MOUNTPOINT "/mnt/sdcard"
+# endif
+
+# ifndef CONFIG_FRDMK28F_SDHC_AUTOMOUNT_DDELAY
+# define CONFIG_FRDMK28F_SDHC_AUTOMOUNT_DDELAY 1000
+# endif
+
+# ifndef CONFIG_FRDMK28F_SDHC_AUTOMOUNT_UDELAY
+# define CONFIG_FRDMK28F_SDHC_AUTOMOUNT_UDELAY 2000
+# endif
+#endif /* HAVE_AUTOMOUNTER */
+
/* Freedom-K28F GPIOs *******************************************************/
+/* A micro Secure Digital (SD) card slot is available on the FRDM-K28F
+ * 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 (PTB5) is an open switch that shorts with VDD when
+ * card is inserted.
+ */
+#define GPIO_SD_CARDDETECT (GPIO_INPUT | PIN_INT_BOTH | PIN_PORTB | PIN5)
+
/* An RGB LED is connected through GPIO as shown below:
*
* LED K28
@@ -148,6 +235,90 @@ void k28_i2cdev_initialize(void);
extern void weak_function k28_usbdev_initialize(void);
/****************************************************************************
+ * Name: k28_sdhc_initialize
+ *
+ * Description:
+ * Inititialize the SDHC SD card slot
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_MMCSD
+int k28_sdhc_initialize(void);
+#else
+# define k28_sdhc_initialize() (OK)
+#endif
+
+/****************************************************************************
+ * Name: k28_cardinserted
+ *
+ * Description:
+ * Check if a card is inserted into the SDHC slot
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_AUTOMOUNTER
+bool k28_cardinserted(void);
+#else
+# define k28_cardinserted() (false)
+#endif
+
+/****************************************************************************
+ * Name: k28_writeprotected
+ *
+ * Description:
+ * Check if the card in the MMC/SD slot is write protected
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_AUTOMOUNTER
+bool k28_writeprotected(void);
+#else
+# define k28_writeprotected() (false)
+#endif
+
+/****************************************************************************
+ * Name: k28_automount_initialize
+ *
+ * Description:
+ * Configure auto-mounter for the configured SDHC slot
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_AUTOMOUNTER
+void k28_automount_initialize(void);
+#endif
+
+/****************************************************************************
+ * Name: k28_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 k28_automount_event(bool inserted);
+#endif
+
+/****************************************************************************
* Name: k28_pwm_setup
*
* Description:
diff --git a/boards/arm/kinetis/freedom-k28f/src/k28_automount.c b/boards/arm/kinetis/freedom-k28f/src/k28_automount.c
new file mode 100644
index 0000000..cf996a5
--- /dev/null
+++ b/boards/arm/kinetis/freedom-k28f/src/k28_automount.c
@@ -0,0 +1,310 @@
+/****************************************************************************
+ * boards/arm/kinetis/freedom-k28f/src/k28_automount.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#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-k28f.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 k28_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 k28_automount_config_s
+{
+ /* This must be first thing in structure so that we can simply cast from
+ * struct automount_lower_s to struct k28_automount_config_s
+ */
+
+ struct automount_lower_s lower; /* Publicly visible part */
+ FAR struct k28_automount_state_s *state; /* Changeable state */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int k28_attach(FAR const struct automount_lower_s *lower,
+ automount_handler_t isr, FAR void *arg);
+static void k28_enable(FAR const struct automount_lower_s *lower,
+ bool enable);
+static bool k28_inserted(FAR const struct automount_lower_s *lower);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct k28_automount_state_s g_sdhc_state;
+static const struct k28_automount_config_s g_sdhc_config =
+{
+ .lower =
+ {
+ .fstype = CONFIG_FRDMK28F_SDHC_AUTOMOUNT_FSTYPE,
+ .blockdev = CONFIG_FRDMK28F_SDHC_AUTOMOUNT_BLKDEV,
+ .mountpoint = CONFIG_FRDMK28F_SDHC_AUTOMOUNT_MOUNTPOINT,
+ .ddelay = MSEC2TICK(CONFIG_FRDMK28F_SDHC_AUTOMOUNT_DDELAY),
+ .udelay = MSEC2TICK(CONFIG_FRDMK28F_SDHC_AUTOMOUNT_UDELAY),
+ .attach = k28_attach,
+ .enable = k28_enable,
+ .inserted = k28_inserted
+ },
+ .state = &g_sdhc_state
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: k28_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 k28_attach(FAR const struct automount_lower_s *lower,
+ automount_handler_t isr, FAR void *arg)
+{
+ FAR const struct k28_automount_config_s *config;
+ FAR struct k28_automount_state_s *state;
+
+ /* Recover references to our structure */
+
+ config = (FAR struct k28_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: k28_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 k28_enable(FAR const struct automount_lower_s *lower,
+ bool enable)
+{
+ FAR const struct k28_automount_config_s *config;
+ FAR struct k28_automount_state_s *state;
+ irqstate_t flags;
+
+ /* Recover references to our structure */
+
+ config = (FAR struct k28_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 = k28_cardinserted();
+ state->handler(&config->lower, state->arg, inserted);
+ }
+
+ state->pending = false;
+ }
+
+ leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: k28_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 k28_inserted(FAR const struct automount_lower_s *lower)
+{
+ return k28_cardinserted();
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: k28_automount_initialize
+ *
+ * Description:
+ * Configure auto-mounters for each enable and so configured SDHC
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void k28_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: k28_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 k28_automount_event(bool inserted)
+{
+ FAR const struct k28_automount_config_s *config = &g_sdhc_config;
+ FAR struct k28_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 that 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 */
+
+ state->handler(&config->lower, state->arg, inserted);
+ }
+ }
+}
+
+#endif /* HAVE_AUTOMOUNTER */
diff --git a/boards/arm/kinetis/freedom-k28f/src/k28_bringup.c b/boards/arm/kinetis/freedom-k28f/src/k28_bringup.c
index 108e6b0..d7d9f65 100644
--- a/boards/arm/kinetis/freedom-k28f/src/k28_bringup.c
+++ b/boards/arm/kinetis/freedom-k28f/src/k28_bringup.c
@@ -45,6 +45,8 @@
#include <debug.h>
#include <errno.h>
+#include "freedom-k28f.h"
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -93,6 +95,41 @@ int k28_bringup(void)
k28_i2cdev_initialize();
#endif
+#ifdef HAVE_MMCSD
+ /* Initialize the SDHC driver */
+
+ ret = k28_sdhc_initialize();
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: k28_sdhc_initialize() failed: %d\n", ret);
+ }
+
+#ifdef CONFIG_FRDMK28F_SDHC_MOUNT
+ else
+ {
+ /* Mount the volume on HSMCI0 */
+
+ ret = mount(CONFIG_FRDMK28F_SDHC_MOUNT_BLKDEV,
+ CONFIG_FRDMK28F_SDHC_MOUNT_MOUNTPOINT,
+ CONFIG_FRDMK28F_SDHC_MOUNT_FSTYPE,
+ 0, NULL);
+
+ if (ret < 0)
+ {
+ syslog(LOG_ERR,"ERROR: Failed to mount %s: %d\n",
+ CONFIG_FRDMK28F_SDHC_MOUNT_MOUNTPOINT, errno);
+ }
+ }
+
+#endif /* CONFIG_FRDMK28F_SDHC_MOUNT */
+#endif /* HAVE_MMCSD */
+
+#ifdef HAVE_AUTOMOUNTER
+ /* Initialize the auto-mounter */
+
+ k28_automount_initialize();
+#endif
+
UNUSED(ret);
return OK;
}
diff --git a/boards/arm/kinetis/freedom-k28f/src/k28_sdhc.c b/boards/arm/kinetis/freedom-k28f/src/k28_sdhc.c
new file mode 100644
index 0000000..356c912
--- /dev/null
+++ b/boards/arm/kinetis/freedom-k28f/src/k28_sdhc.c
@@ -0,0 +1,240 @@
+/****************************************************************************
+ * boards/arm/kinetis/freedom-k28f/src/k28_sdhc.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* 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 (PTB5) is an open switch that shorts with VDD when
+ * card is inserted.
+ *
+ * ------------ ------------- --------
+ * SD Card Slot Board Signal K64F Pin
+ * ------------ ------------- --------
+ * DAT0 SDHC0_D0 PTA25
+ * DAT1 SDHC0_D1 PTA24
+ * DAT2 SDHC0_D2 PTA29
+ * CD/DAT3 SDHC0_D3 PTA28
+ * CMD SDHC0_CMD PTA27
+ * CLK SDHC0_DCLK PTA26
+ * SWITCH D_CARD_DETECT PTB5
+ * ------------ ------------- --------
+ *
+ * There is no Write Protect pin available to the K28F.
+ */
+
+/****************************************************************************
+ * 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-k28f.h"
+
+#ifdef HAVE_MMCSD
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure holds static information unique to one SDHC peripheral */
+
+struct k28_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 k28_sdhc_state_s g_sdhc;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: k28_mediachange
+ ****************************************************************************/
+
+static void k28_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_FRDMK28F_SDHC_AUTOMOUNT
+ /* Let the automounter know about the insertion event */
+
+ k28_automount_event(k28_cardinserted());
+#endif
+ }
+}
+
+/****************************************************************************
+ * Name: k28_cdinterrupt
+ ****************************************************************************/
+
+static int k28_cdinterrupt(int irq, FAR void *context, FAR void *arg)
+{
+ /* All of the work is done by k28_mediachange() */
+
+ k28_mediachange();
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: k28_sdhc_initialize
+ *
+ * Description:
+ * Inititialize the SDHC SD card slot
+ *
+ ****************************************************************************/
+
+int k28_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, k28_cdinterrupt, NULL);
+
+ /* 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 */
+
+ k28_mediachange();
+
+ /* Enable CD interrupts to handle subsequent media changes */
+
+ kinetis_pinirqenable(GPIO_SD_CARDDETECT);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: k28_cardinserted
+ *
+ * Description:
+ * Check if a card is inserted into the SDHC slot
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_AUTOMOUNTER
+bool k28_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: k28_writeprotected
+ *
+ * Description:
+ * Check if a card is inserted into the SDHC slot
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_AUTOMOUNTER
+bool k28_writeprotected(void)
+{
+ /* There are no write protect pins */
+
+ return false;
+}
+#endif
+
+#endif /* HAVE_MMCSD */