updating lib *.c
This commit is contained in:
401
demos/bsp/lpc43xx/CMSIS_LPC43xx_DriverLib/src/lpc43xx_sdif.c
Normal file
401
demos/bsp/lpc43xx/CMSIS_LPC43xx_DriverLib/src/lpc43xx_sdif.c
Normal file
@@ -0,0 +1,401 @@
|
||||
/**********************************************************************
|
||||
* $Id$ lpc43xx_sdif.c 2012-Aug-15
|
||||
*//**
|
||||
* @file lpc43xx_sdif.c
|
||||
* @brief LPC43xx SD interface driver
|
||||
* @version 1.0
|
||||
* @date 15. Aug. 2012
|
||||
* @author NXP MCU SW Application Team
|
||||
*
|
||||
* Copyright(C) 2011, NXP Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
***********************************************************************
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* products. This software is supplied "AS IS" without any warranties.
|
||||
* NXP Semiconductors assumes no responsibility or liability for the
|
||||
* use of the software, conveys no license or title under any patent,
|
||||
* copyright, or mask work right to the product. NXP Semiconductors
|
||||
* reserves the right to make changes in the software without
|
||||
* notification. NXP Semiconductors also make no representation or
|
||||
* warranty that such application will be suitable for the specified
|
||||
* use without further testing or modification.
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors'
|
||||
* relevant copyright in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
**********************************************************************/
|
||||
|
||||
/* Peripheral group ----------------------------------------------------------- */
|
||||
/** @addtogroup SDIF
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------- */
|
||||
#include "LPC43xx.h" /* LPC43xx definitions */
|
||||
#include "system_LPC43xx.h"
|
||||
#include "lpc_sdmmc.h"
|
||||
#include "lpc43xx_sdif.h"
|
||||
#include "lpc43xx_cgu.h"
|
||||
|
||||
/* If this source file built with example, the lpc43xx FW library configuration
|
||||
* file in each example directory ("lpc43xx_libcfg.h") must be included,
|
||||
* otherwise the default FW library configuration file must be included instead
|
||||
*/
|
||||
#ifdef __BUILD_WITH_EXAMPLE__
|
||||
#include "lpc43xx_libcfg.h"
|
||||
#else
|
||||
#include "lpc43xx_libcfg_default.h"
|
||||
#endif /* __BUILD_WITH_EXAMPLE__ */
|
||||
|
||||
#ifdef _SDIF
|
||||
|
||||
/* Local data structure for the SDIF driver */
|
||||
struct _sdif_device {
|
||||
MCI_IRQ_CB_FUNC_T irq_cb;
|
||||
LPC_SDMMC_DMA_Type mci_dma_dd[1 + (0x10000 / MCI_DMADES1_MAXTR)];
|
||||
uint32_t sdio_clk_rate;
|
||||
uint32_t sdif_slot_clk_rate;
|
||||
int32_t clock_enabled;
|
||||
};
|
||||
static struct _sdif_device sdif_dev;
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Enables the SDIO controller clock
|
||||
* @param[in] None
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
static void sdif_enable_clock(void)
|
||||
{
|
||||
if (!sdif_dev.clock_enabled)
|
||||
{
|
||||
/* Enable SD MMC clock */
|
||||
CGU_ConfigPWR(CGU_PERIPHERAL_SDIO, ENABLE);
|
||||
sdif_dev.clock_enabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Disables the SDIO controller clock
|
||||
* @param[in] None
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
static void sdif_disable_clock(void)
|
||||
{
|
||||
if (!sdif_dev.clock_enabled)
|
||||
{
|
||||
/* Disable SD MMC clock */
|
||||
CGU_ConfigPWR(CGU_PERIPHERAL_SDIO, (FunctionalState)FALSE);
|
||||
sdif_dev.clock_enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Public Functions ----------------------------------------------------------- */
|
||||
/** @defgroup SDIF_Public_Functions
|
||||
* @ingroup SDIF
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Setup DMA descriptors
|
||||
* @param[in] addr Address of buffer (source or destination)
|
||||
* @param[in] size size of buffer in bytes (64K max)
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
void sdif_dma_setup(uint32_t addr, uint32_t size)
|
||||
{
|
||||
int i = 0;
|
||||
uint32_t ctrl, maxs;
|
||||
|
||||
/* Reset DMA */
|
||||
LPC_SDMMC->CTRL |= MCI_CTRL_DMA_RESET | MCI_CTRL_FIFO_RESET;
|
||||
while (LPC_SDMMC->CTRL & MCI_CTRL_DMA_RESET);
|
||||
|
||||
/* Build a descriptor list using the chained DMA method */
|
||||
while (size > 0)
|
||||
{
|
||||
/* Limit size of the transfer to maximum buffer size */
|
||||
maxs = size;
|
||||
if (maxs > MCI_DMADES1_MAXTR)
|
||||
maxs = MCI_DMADES1_MAXTR;
|
||||
size -= maxs;
|
||||
|
||||
/* Set buffer size */
|
||||
sdif_dev.mci_dma_dd[i].des1 = MCI_DMADES1_BS1(maxs);
|
||||
|
||||
/* Setup buffer address (chained) */
|
||||
sdif_dev.mci_dma_dd[i].des2 = addr + (i * MCI_DMADES1_MAXTR);
|
||||
|
||||
/* Setup basic control */
|
||||
ctrl = MCI_DMADES0_OWN | MCI_DMADES0_CH;
|
||||
if (i == 0)
|
||||
ctrl |= MCI_DMADES0_FS; /* First DMA buffer */
|
||||
|
||||
/* No more data? Then this is the last descriptor */
|
||||
if (!size)
|
||||
ctrl |= MCI_DMADES0_LD;
|
||||
else
|
||||
ctrl |= MCI_DMADES0_DIC;
|
||||
|
||||
/* Another descriptor is needed */
|
||||
sdif_dev.mci_dma_dd[i].des3 = (uint32_t) &sdif_dev.mci_dma_dd[i + 1];
|
||||
sdif_dev.mci_dma_dd[i].des0 = ctrl;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Set DMA derscriptor base address */
|
||||
LPC_SDMMC->DBADDR = (uint32_t) &sdif_dev.mci_dma_dd[0];
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Function to send command to Card interface unit (CIU)
|
||||
* @param[in] cmd Command with all flags set
|
||||
* @param[in] arg Argument for the command
|
||||
* @return TRUE on times-out, otherwise FALSE
|
||||
**********************************************************************/
|
||||
int32_t sdif_send_cmd(uint32_t cmd, uint32_t arg)
|
||||
{
|
||||
volatile int32_t tmo = 50;
|
||||
volatile int delay;
|
||||
|
||||
/* set command arg reg*/
|
||||
LPC_SDMMC->CMDARG = arg;
|
||||
LPC_SDMMC->CMD = MCI_CMD_START | cmd;
|
||||
|
||||
/* poll untill command is accepted by the CIU */
|
||||
while (--tmo && (LPC_SDMMC->CMD & MCI_CMD_START))
|
||||
{
|
||||
if (tmo & 1)
|
||||
delay = 50;
|
||||
else
|
||||
delay = 18000;
|
||||
|
||||
while (--delay > 1);
|
||||
}
|
||||
|
||||
return (tmo < 1) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Function to retrieve command response
|
||||
* @param[in] pdev Pointer to card info structure
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
void sdif_get_response(uint32_t *resp)
|
||||
{
|
||||
/* on this chip response is not a fifo so read all 4 regs */
|
||||
resp[0] = LPC_SDMMC->RESP0;
|
||||
resp[1] = LPC_SDMMC->RESP1;
|
||||
resp[2] = LPC_SDMMC->RESP2;
|
||||
resp[3] = LPC_SDMMC->RESP3;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Function to set speed of the clock going to card
|
||||
* @param[in] speed Desired clock speed to the card
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
void sdif_set_clock(uint32_t speed)
|
||||
{
|
||||
/* compute SD/MMC clock dividers */
|
||||
uint32_t div;
|
||||
|
||||
/* Exit if the clock is already set at the passed speed */
|
||||
if (sdif_dev.sdif_slot_clk_rate == speed)
|
||||
return;
|
||||
|
||||
div = ((sdif_dev.sdio_clk_rate / speed) + 2) >> 1;
|
||||
sdif_dev.sdif_slot_clk_rate = speed;
|
||||
|
||||
if ((div == LPC_SDMMC->CLKDIV) && LPC_SDMMC->CLKENA)
|
||||
return; /* Closest speed is already set */
|
||||
|
||||
/* disable clock */
|
||||
LPC_SDMMC->CLKENA = 0;
|
||||
|
||||
/* User divider 0 */
|
||||
LPC_SDMMC->CLKSRC = MCI_CLKSRC_CLKDIV0;
|
||||
|
||||
/* inform CIU */
|
||||
sdif_send_cmd(MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
|
||||
|
||||
/* set divider 0 to desired value */
|
||||
LPC_SDMMC->CLKDIV = MCI_CLOCK_DIVIDER(0, div);
|
||||
|
||||
/* inform CIU */
|
||||
sdif_send_cmd(MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
|
||||
|
||||
/* enable clock */
|
||||
LPC_SDMMC->CLKENA = MCI_CLKEN_ENABLE;
|
||||
|
||||
/* inform CIU */
|
||||
sdif_send_cmd(MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Detect if an SD card is inserted
|
||||
* @param[in] None
|
||||
* @return Returns 0 if a card is detected, otherwise 1
|
||||
**********************************************************************/
|
||||
int32_t sdif_card_ndetect(void)
|
||||
{
|
||||
/* No card = high state in regsiter */
|
||||
if (LPC_SDMMC->CDETECT & 1)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Detect if write protect is enabled
|
||||
* @param[in] None
|
||||
* @return Returns 1 if card is write protected, otherwise 0
|
||||
**********************************************************************/
|
||||
int32_t sdif_card_wp_on(void)
|
||||
{
|
||||
if (LPC_SDMMC->WRTPRT & 1)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Enable or disable slot power
|
||||
* @param[in] enable !0 to enable, or 0 to disable
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
void sdif_power_onoff(int32_t enable)
|
||||
{
|
||||
if (enable)
|
||||
LPC_SDMMC->PWREN = 1;
|
||||
else
|
||||
LPC_SDMMC->PWREN = 0;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Reset card in slot
|
||||
* @param[in] reset Sets SD_RST to passed state
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
void sdif_reset(int32_t reset)
|
||||
{
|
||||
if (reset)
|
||||
LPC_SDMMC->RST_N = 1;
|
||||
else
|
||||
LPC_SDMMC->RST_N = 0;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Set block size for transfer
|
||||
* @param[in] bytes Lock size in bytes
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
void sdif_set_blksize(uint32_t bytes)
|
||||
{
|
||||
LPC_SDMMC->BLKSIZ = bytes;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Enter or exit low power mode (disables clocking)
|
||||
* @param[in] lpmode !0 to enable low power mode, 0 = exit
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
void sdif_set_lowpower_mode(int32_t lpmode)
|
||||
{
|
||||
/* Once in low power mode, no SDIF functions should ever be
|
||||
called, as it can hang the chip. Always exit low power mode
|
||||
prior to resuming SDIF functions */
|
||||
if (lpmode)
|
||||
sdif_disable_clock();
|
||||
else
|
||||
sdif_enable_clock();
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Initializes the MCI card controller
|
||||
* @param[in] waitfunc Pointer to wait function to be used during for poll command status
|
||||
* @param[in] irq_callback Pointer to IRQ callback function
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
void sdif_init(uint32_t sdio_clock, MCI_IRQ_CB_FUNC_T irq_callback)
|
||||
{
|
||||
volatile uint32_t i;
|
||||
|
||||
sdif_dev.sdio_clk_rate = sdio_clock;
|
||||
sdif_dev.irq_cb = irq_callback;
|
||||
|
||||
/* enable SD/MMC clock */
|
||||
sdif_enable_clock();
|
||||
|
||||
/* Software reset */
|
||||
LPC_SDMMC->BMOD = MCI_BMOD_SWR;
|
||||
|
||||
/* reset all blocks */
|
||||
LPC_SDMMC->CTRL = MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET |
|
||||
MCI_CTRL_DMA_RESET;
|
||||
while (LPC_SDMMC->CTRL &
|
||||
(MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET | MCI_CTRL_DMA_RESET));
|
||||
|
||||
/* Internal DMA setup for control register */
|
||||
LPC_SDMMC->CTRL = MCI_CTRL_USE_INT_DMAC | MCI_CTRL_INT_ENABLE;
|
||||
LPC_SDMMC->INTMASK = 0;
|
||||
|
||||
/* Clear the interrupts for the host controller */
|
||||
LPC_SDMMC->RINTSTS = 0xFFFFFFFF;
|
||||
|
||||
/* Put in max timeout */
|
||||
LPC_SDMMC->TMOUT = 0xFFFFFFFF;
|
||||
|
||||
/* FIFO threshold settings for DMA, DMA burst of 4,
|
||||
FIFO watermark at 16 */
|
||||
LPC_SDMMC->FIFOTH = MCI_FIFOTH_DMA_MTS_4 |
|
||||
MCI_FIFOTH_RX_WM((SD_FIFO_SZ / 2) - 1) |
|
||||
MCI_FIFOTH_TX_WM(SD_FIFO_SZ / 2);
|
||||
|
||||
/* Enable internal DMA, burst size of 4, fixed burst */
|
||||
LPC_SDMMC->BMOD = MCI_BMOD_DE | MCI_BMOD_PBL4 | MCI_BMOD_DSL(4);
|
||||
|
||||
/* disable clock to CIU (needs latch) */
|
||||
LPC_SDMMC->CLKENA = 0;
|
||||
LPC_SDMMC->CLKSRC = 0;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief Close the MCI
|
||||
* @param[in] None
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
void sdif_deinit(void)
|
||||
{
|
||||
/* clear mmc structure*/
|
||||
sdif_disable_clock();
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
* @brief SDIO controller interrupt handler
|
||||
* @param[in] None
|
||||
* @return None
|
||||
**********************************************************************/
|
||||
void SDIO_IRQHandler(void)
|
||||
{
|
||||
/* All SD based register handling is done in the callback
|
||||
function. The SDIO interrupt is not enabled as part of this
|
||||
driver and needs to be enabled/disabled in the callbacks or
|
||||
application as needed. This is to allow flexibility with IRQ
|
||||
handling for applicaitons and RTOSes. */
|
||||
sdif_dev.irq_cb(LPC_SDMMC->RINTSTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* _SDIF */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
Reference in New Issue
Block a user