@ -1,35 +1,35 @@
/*
/*
* Copyright ( c ) 2006 - 2018 , RT - Thread Development Team
* Copyright ( c ) 2006 - 2020 , RT - Thread Development Team
*
*
* SPDX - License - Identifier : Apache - 2.0
* SPDX - License - Identifier : Apache - 2.0
*
*
* Change Logs :
* Change Logs :
* Date Author Notes
* Date Author Notes
* 2018 - 06 - 22 tyx first
* 2020 - 05 - 23 liuduanfei first version
* 2018 - 12 - 12 balanceTWK first version
* 2019 - 06 - 11 WillianChan Add SD card hot plug detection
*/
*/
# include "board.h"
# include "board.h"
# include "drv_sdio.h"
# include "drv_config.h"
# include <rtthread.h>
# include <rtdevice.h>
# ifdef BSP _USING_SDIO
# ifdef RT_USING_SDIO
//#define DRV_DEBUG
# if !defined(BSP_USING_SDIO1) && !defined(BSP_USING_SDIO2)
# define LOG_TAG "drv.sdio "
# error "Please define at least one BSP_USING_SDIOx "
# include <drv_log.h>
# endif
static struct stm32_sdio_config sdio_config = SDIO_BUS_CONFIG ;
# include "drv_sdio.h"
static struct stm32_sdio_class sdio_obj ;
static struct rt_mmcsd_host * host ;
//#define DRV_DEBUG
# define DBG_TAG "drv.sdio"
# ifdef DRV_DEBUG
# define DBG_LVL DBG_LOG
# else
# define DBG_LVL DBG_INFO
# endif /* DRV_DEBUG */
# include <rtdbg.h>
# define SDIO_TX_RX_COMPLETE_TIMEOUT_LOOPS (100000)
static struct rt_mmcsd_host * host1 ;
static struct rt_mmcsd_host * host2 ;
# define RTHW_SDIO_LOCK(_sdio) rt_mutex_take(&_sdio->mutex, RT_WAITING_FOREVER)
# define SDIO_TX_RX_COMPLETE_TIMEOUT_LOOPS (1000000)
# define RTHW_SDIO_UNLOCK(_sdio) rt_mutex_release(&_sdio->mutex);
struct sdio_pkg
struct sdio_pkg
{
{
@ -43,18 +43,13 @@ struct rthw_sdio
struct rt_mmcsd_host * host ;
struct rt_mmcsd_host * host ;
struct stm32_sdio_des sdio_des ;
struct stm32_sdio_des sdio_des ;
struct rt_event event ;
struct rt_event event ;
struct rt_mutex mutex ;
struct sdio_pkg * pkg ;
struct sdio_pkg * pkg ;
} ;
} ;
# ifndef ALIGN
ALIGN ( SDIO_ALIGN_LEN )
# define ALIGN(SDIO_ALIGN_LEN) __attribute__((aligned(SDIO_ALIGN_LEN)))
static rt_uint8_t cache_buf [ SDIO_BUFF_SIZE ] ;
//ALIGN(SDIO_ALIGN_LEN)
static __attribute__ ( ( section ( " .ram_d1 " ) ) ) rt_uint8_t cache_buf [ SDIO_BUFF_SIZE ] __attribute__ ( ( aligned ( 32 ) ) ) ;
static rt_uint32_t stm32_sdio_clk_get ( struct stm32_sdio * hw_sdio )
//static rt_uint8_t cache_buf[SDIO_BUFF_SIZE];
{
return SDIO_CLOCK_FREQ ;
}
/**
/**
* @ brief This function get order from sdio .
* @ brief This function get order from sdio .
* @ param data
* @ param data
@ -115,12 +110,11 @@ static int get_order(rt_uint32_t data)
order = 0 ;
order = 0 ;
break ;
break ;
}
}
return order ;
return order ;
}
}
/**
/**
* @ brief This function wait sdio completed .
* @ brief This function wait sdio cmd c ompleted .
* @ param sdio rthw_sdio
* @ param sdio rthw_sdio
* @ retval None
* @ retval None
*/
*/
@ -128,30 +122,27 @@ static void rthw_sdio_wait_completed(struct rthw_sdio *sdio)
{
{
rt_uint32_t status ;
rt_uint32_t status ;
struct rt_mmcsd_cmd * cmd = sdio - > pkg - > cmd ;
struct rt_mmcsd_cmd * cmd = sdio - > pkg - > cmd ;
struct rt_mmcsd_data * data = cmd - > data ;
struct stm32_sdio * hw_sdio = sdio - > sdio_des . hw_sdio ;
struct stm32_sdio * hw_sdio = sdio - > sdio_des . hw_sdio ;
if ( rt_event_recv ( & sdio - > event , 0xffffffff , RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR ,
if ( rt_event_recv ( & sdio - > event , 0xffffffff , RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR ,
rt_tick_from_millisecond ( 5000 ) , & status ) ! = RT_EOK )
rt_tick_from_millisecond ( 5000 ) , & status ) ! = RT_EOK )
{
{
LOG_E ( " wait completed timeout " ) ;
LOG_E ( " wait cmd c ompleted timeout " ) ;
cmd - > err = - RT_ETIMEOUT ;
cmd - > err = - RT_ETIMEOUT ;
return ;
return ;
}
}
if ( sdio - > pkg = = RT_NULL )
{
return ;
}
cmd - > resp [ 0 ] = hw_sdio - > resp1 ;
cmd - > resp [ 0 ] = hw_sdio - > resp1 ;
if ( resp_type ( cmd ) = = RESP_R2 )
{
cmd - > resp [ 1 ] = hw_sdio - > resp2 ;
cmd - > resp [ 1 ] = hw_sdio - > resp2 ;
cmd - > resp [ 2 ] = hw_sdio - > resp3 ;
cmd - > resp [ 2 ] = hw_sdio - > resp3 ;
cmd - > resp [ 3 ] = hw_sdio - > resp4 ;
cmd - > resp [ 3 ] = hw_sdio - > resp4 ;
}
if ( status & HW_ SDIO_ERRORS)
if ( status & SDIO_ERRORS )
{
{
if ( ( status & HW_SDIO_IT _CCRCFAIL) & & ( resp_type ( cmd ) & ( RESP_R3 | RESP_R4 ) ) )
if ( ( status & SDMMC_STA _CCRCFAIL) & & ( resp_type ( cmd ) & ( RESP_R3 | RESP_R4 ) ) )
{
{
cmd - > err = RT_EOK ;
cmd - > err = RT_EOK ;
}
}
@ -159,21 +150,12 @@ static void rthw_sdio_wait_completed(struct rthw_sdio *sdio)
{
{
cmd - > err = - RT_ERROR ;
cmd - > err = - RT_ERROR ;
}
}
if ( status & HW_SDIO_IT_CTIMEOUT )
{
cmd - > err = - RT_ETIMEOUT ;
}
}
else
if ( status & HW_SDIO_IT_DCRCFAIL )
{
{
data - > err = - RT_ERROR ;
cmd - > err = RT_EOK ;
}
}
if ( status & HW_SDIO_IT_DTIMEOUT )
{
data - > err = - RT_ETIMEOUT ;
}
if ( cmd - > err = = RT_EOK )
if ( cmd - > err = = RT_EOK )
{
{
@ -181,74 +163,7 @@ static void rthw_sdio_wait_completed(struct rthw_sdio *sdio)
}
}
else
else
{
{
LOG_D ( " err:0x%08x, %s%s%s%s%s%s%s cmd:%d arg:0x%08x rw:%c len:%d blksize:%d " ,
LOG_D ( " send command error = %d " , cmd - > err ) ;
status ,
status & HW_SDIO_IT_CCRCFAIL ? " CCRCFAIL " : " " ,
status & HW_SDIO_IT_DCRCFAIL ? " DCRCFAIL " : " " ,
status & HW_SDIO_IT_CTIMEOUT ? " CTIMEOUT " : " " ,
status & HW_SDIO_IT_DTIMEOUT ? " DTIMEOUT " : " " ,
status & HW_SDIO_IT_TXUNDERR ? " TXUNDERR " : " " ,
status & HW_SDIO_IT_RXOVERR ? " RXOVERR " : " " ,
status = = 0 ? " NULL " : " " ,
cmd - > cmd_code ,
cmd - > arg ,
data ? ( data - > flags & DATA_DIR_WRITE ? ' w ' : ' r ' ) : ' - ' ,
data ? data - > blks * data - > blksize : 0 ,
data ? data - > blksize : 0
) ;
}
}
else
{
cmd - > err = RT_EOK ;
LOG_D ( " sta:0x%08X [%08X %08X %08X %08X] " , status , cmd - > resp [ 0 ] , cmd - > resp [ 1 ] , cmd - > resp [ 2 ] , cmd - > resp [ 3 ] ) ;
}
}
/**
* @ brief This function transfer data by dma .
* @ param sdio rthw_sdio
* @ param pkg sdio package
* @ retval None
*/
static void rthw_sdio_transfer_by_dma ( struct rthw_sdio * sdio , struct sdio_pkg * pkg )
{
struct rt_mmcsd_data * data ;
int size ;
void * buff ;
struct stm32_sdio * hw_sdio ;
if ( ( RT_NULL = = pkg ) | | ( RT_NULL = = sdio ) )
{
LOG_E ( " rthw_sdio_transfer_by_dma invalid args " ) ;
return ;
}
data = pkg - > cmd - > data ;
if ( RT_NULL = = data )
{
LOG_E ( " rthw_sdio_transfer_by_dma invalid args " ) ;
return ;
}
buff = pkg - > buff ;
if ( RT_NULL = = buff )
{
LOG_E ( " rthw_sdio_transfer_by_dma invalid args " ) ;
return ;
}
hw_sdio = sdio - > sdio_des . hw_sdio ;
size = data - > blks * data - > blksize ;
if ( data - > flags & DATA_DIR_WRITE )
{
sdio - > sdio_des . txconfig ( ( rt_uint32_t * ) buff , ( rt_uint32_t * ) & hw_sdio - > fifo , size ) ;
hw_sdio - > dctrl | = HW_SDIO_DMA_ENABLE ;
}
else if ( data - > flags & DATA_DIR_READ )
{
sdio - > sdio_des . rxconfig ( ( rt_uint32_t * ) & hw_sdio - > fifo , ( rt_uint32_t * ) buff , size ) ;
hw_sdio - > dctrl | = HW_SDIO_DMA_ENABLE | HW_SDIO_DPSM_ENABLE ;
}
}
}
}
@ -265,10 +180,11 @@ static void rthw_sdio_send_command(struct rthw_sdio *sdio, struct sdio_pkg *pkg)
struct stm32_sdio * hw_sdio = sdio - > sdio_des . hw_sdio ;
struct stm32_sdio * hw_sdio = sdio - > sdio_des . hw_sdio ;
rt_uint32_t reg_cmd ;
rt_uint32_t reg_cmd ;
rt_event_control ( & sdio - > event , RT_IPC_CMD_RESET , RT_NULL ) ;
/* save pkg */
/* save pkg */
sdio - > pkg = pkg ;
sdio - > pkg = pkg ;
LOG_D ( " CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c len:%d blksize:%d " ,
LOG_D ( " CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c len:%d blksize:%d \n " ,
cmd - > cmd_code ,
cmd - > cmd_code ,
cmd - > arg ,
cmd - > arg ,
resp_type ( cmd ) = = RESP_NONE ? " NONE " : " " ,
resp_type ( cmd ) = = RESP_NONE ? " NONE " : " " ,
@ -285,47 +201,30 @@ static void rthw_sdio_send_command(struct rthw_sdio *sdio, struct sdio_pkg *pkg)
data ? data - > blksize : 0
data ? data - > blksize : 0
) ;
) ;
/* config cmd reg */
hw_sdio - > mask | = SDIO_MASKR_ALL ;
reg_cmd = cmd - > cmd_code | HW_SDIO_CPSM_ENABLE ;
reg_cmd = cmd - > cmd_code | SDMMC_CMD_CPSMEN ;
if ( resp_type ( cmd ) = = RESP_NONE )
reg_cmd | = HW_SDIO_RESPONSE_NO ;
else if ( resp_type ( cmd ) = = RESP_R2 )
reg_cmd | = HW_SDIO_RESPONSE_LONG ;
else
reg_cmd | = HW_SDIO_RESPONSE_SHORT ;
/* config data reg */
/* data pre configuration */
if ( data ! = RT_NULL )
if ( data ! = RT_NULL )
{
{
rt_uint32_t dir = 0 ;
SCB_CleanInvalidateDCache ( ) ;
rt_uint32_t size = data - > blks * data - > blksize ;
int order ;
hw_sdio - > dctrl = 0 ;
reg_cmd | = SDMMC_CMD_CMDTRANS ;
hw_sdio - > mask & = ~ ( SDMMC_MASK_CMDRENDIE | SDMMC_MASK_CMDSENTIE ) ;
hw_sdio - > dtimer = HW_SDIO_DATATIMEOUT ;
hw_sdio - > dtimer = HW_SDIO_DATATIMEOUT ;
hw_sdio - > dlen = size ;
hw_sdio - > dlen = data - > blks * data - > blk size;
order = get_order ( data - > blksize ) ;
hw_sdio - > dctrl = ( get_order ( data - > blksize ) < < 4 ) | ( data - > flags & DATA_DIR_READ ? SDMMC_DCTRL_DTDIR : 0 ) ;
dir = ( data - > flags & DATA_DIR_READ ) ? HW_SDIO_TO_HOST : 0 ;
hw_s dio - > idmabase0r = ( rt_uint32_t ) cache_buf ;
hw_sdio - > dctrl = HW_SDIO_IO_ENABLE | ( order < < 4 ) | dir ;
hw_sdio - > idmatrlr = SDMMC_IDMA_IDMAEN ;
}
}
/* transfer config */
if ( resp_type ( cmd ) = = RESP_R2 )
if ( data ! = RT_NULL )
reg_cmd | = SDMMC_CMD_WAITRESP ;
{
else if ( resp_type ( cmd ) ! = RESP_NONE )
rthw_sdio_transfer_by_dma ( sdio , pkg ) ;
reg_cmd | = SDMMC_CMD_WAITRESP_0 ;
}
/* open irq */
hw_sdio - > mask | = HW_SDIO_IT_CMDSENT | HW_SDIO_IT_CMDREND | HW_SDIO_ERRORS ;
if ( data ! = RT_NULL )
{
hw_sdio - > mask | = HW_SDIO_IT_DATAEND ;
}
/* send cmd */
hw_sdio - > arg = cmd - > arg ;
hw_sdio - > arg = cmd - > arg ;
hw_sdio - > cmd = reg_cmd ;
hw_sdio - > cmd = reg_cmd ;
/* wait completed */
/* wait completed */
rthw_sdio_wait_completed ( sdio ) ;
rthw_sdio_wait_completed ( sdio ) ;
@ -334,22 +233,26 @@ static void rthw_sdio_send_command(struct rthw_sdio *sdio, struct sdio_pkg *pkg)
{
{
volatile rt_uint32_t count = SDIO_TX_RX_COMPLETE_TIMEOUT_LOOPS ;
volatile rt_uint32_t count = SDIO_TX_RX_COMPLETE_TIMEOUT_LOOPS ;
while ( count & & ( hw_sdio - > sta & ( HW_SDIO_IT_TXACT | HW_SDIO_IT_RXACT ) ) )
while ( count & & ( hw_sdio - > sta & SDMMC_STA_DPSMACT ) )
{
{
count - - ;
count - - ;
}
}
if ( ( count = = 0 ) | | ( hw_sdio - > sta & SDIO_ERRORS ) )
if ( ( count = = 0 ) | | ( hw_sdio - > sta & HW_SDIO_ERRORS ) )
{
{
cmd - > err = - RT_ERROR ;
cmd - > err = - RT_ERROR ;
}
}
}
}
/* close irq, keep sdio irq */
/* data post configuration */
hw_sdio - > mask = hw_sdio - > mask & HW_SDIO_IT_SDIOIT ? HW_SDIO_IT_SDIOIT : 0x00 ;
if ( data ! = RT_NULL )
{
if ( data - > flags & DATA_DIR_READ )
{
rt_memcpy ( data - > buf , cache_buf , data - > blks * data - > blksize ) ;
SCB_CleanInvalidateDCache ( ) ;
/* clear pkg */
}
sdio - > pkg = RT_NULL ;
}
}
}
/**
/**
@ -364,11 +267,9 @@ static void rthw_sdio_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *r
struct rthw_sdio * sdio = host - > private_data ;
struct rthw_sdio * sdio = host - > private_data ;
struct rt_mmcsd_data * data ;
struct rt_mmcsd_data * data ;
RTHW_SDIO_LOCK ( sdio ) ;
if ( req - > cmd ! = RT_NULL )
if ( req - > cmd ! = RT_NULL )
{
{
memset ( & pkg , 0 , sizeof ( pkg ) ) ;
rt_ memset( & pkg , 0 , sizeof ( pkg ) ) ;
data = req - > cmd - > data ;
data = req - > cmd - > data ;
pkg . cmd = req - > cmd ;
pkg . cmd = req - > cmd ;
@ -378,236 +279,94 @@ static void rthw_sdio_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *r
RT_ASSERT ( size < = SDIO_BUFF_SIZE ) ;
RT_ASSERT ( size < = SDIO_BUFF_SIZE ) ;
pkg . buff = data - > buf ;
if ( ( rt_uint32_t ) data - > buf & ( SDIO_ALIGN_LEN - 1 ) )
{
pkg . buff = cache_buf ;
if ( data - > flags & DATA_DIR_WRITE )
if ( data - > flags & DATA_DIR_WRITE )
{
{
memcpy ( cache_buf , data - > buf , size ) ;
rt_memcpy ( cache_buf , data - > buf , size ) ;
}
}
}
}
}
rthw_sdio_send_command ( sdio , & pkg ) ;
rthw_sdio_send_command ( sdio , & pkg ) ;
if ( ( data ! = RT_NULL ) & & ( data - > flags & DATA_DIR_READ ) & & ( ( rt_uint32_t ) data - > buf & ( SDIO_ALIGN_LEN - 1 ) ) )
{
memcpy ( data - > buf , cache_buf , data - > blksize * data - > blks ) ;
}
}
}
if ( req - > stop ! = RT_NULL )
if ( req - > stop ! = RT_NULL )
{
{
memset ( & pkg , 0 , sizeof ( pkg ) ) ;
rt_memset ( & pkg , 0 , sizeof ( pkg ) ) ;
pkg . cmd = req - > stop ;
pkg . cmd = req - > stop ;
rthw_sdio_send_command ( sdio , & pkg ) ;
rthw_sdio_send_command ( sdio , & pkg ) ;
}
}
RTHW_SDIO_UNLOCK ( sdio ) ;
mmcsd_req_complete ( sdio - > host ) ;
mmcsd_req_complete ( sdio - > host ) ;
}
}
/**
* @ brief This function config sdio .
* @ param host rt_mmcsd_host
* @ param io_cfg rt_mmcsd_io_cfg
* @ retval None
*/
static void rthw_sdio_iocfg ( struct rt_mmcsd_host * host , struct rt_mmcsd_io_cfg * io_cfg )
{
rt_uint32_t clkcr , div , clk_src ;
rt_uint32_t clk = io_cfg - > clock ;
struct rthw_sdio * sdio = host - > private_data ;
struct stm32_sdio * hw_sdio = sdio - > sdio_des . hw_sdio ;
clk_src = sdio - > sdio_des . clk_get ( sdio - > sdio_des . hw_sdio ) ;
if ( clk_src < 400 * 1000 )
{
LOG_E ( " The clock rate is too low! rata:%d " , clk_src ) ;
return ;
}
if ( clk > host - > freq_max ) clk = host - > freq_max ;
if ( clk > clk_src )
{
LOG_W ( " Setting rate is greater than clock source rate. " ) ;
clk = clk_src ;
}
LOG_D ( " clk:%d width:%s%s%s power:%s%s%s " ,
clk ,
io_cfg - > bus_width = = MMCSD_BUS_WIDTH_8 ? " 8 " : " " ,
io_cfg - > bus_width = = MMCSD_BUS_WIDTH_4 ? " 4 " : " " ,
io_cfg - > bus_width = = MMCSD_BUS_WIDTH_1 ? " 1 " : " " ,
io_cfg - > power_mode = = MMCSD_POWER_OFF ? " OFF " : " " ,
io_cfg - > power_mode = = MMCSD_POWER_UP ? " UP " : " " ,
io_cfg - > power_mode = = MMCSD_POWER_ON ? " ON " : " "
) ;
RTHW_SDIO_LOCK ( sdio ) ;
div = clk_src / clk ;
if ( ( clk = = 0 ) | | ( div = = 0 ) )
{
clkcr = 0 ;
}
else
{
if ( div < 2 )
{
div = 2 ;
}
else if ( div > 0xFF )
{
div = 0xFF ;
}
div - = 2 ;
clkcr = div | HW_SDIO_CLK_ENABLE ;
}
if ( io_cfg - > bus_width = = MMCSD_BUS_WIDTH_8 )
{
clkcr | = HW_SDIO_BUSWIDE_8B ;
}
else if ( io_cfg - > bus_width = = MMCSD_BUS_WIDTH_4 )
{
clkcr | = HW_SDIO_BUSWIDE_4B ;
}
else
{
clkcr | = HW_SDIO_BUSWIDE_1B ;
}
hw_sdio - > clkcr = clkcr ;
switch ( io_cfg - > power_mode )
{
case MMCSD_POWER_OFF :
hw_sdio - > power = HW_SDIO_POWER_OFF ;
break ;
case MMCSD_POWER_UP :
hw_sdio - > power = HW_SDIO_POWER_UP ;
break ;
case MMCSD_POWER_ON :
hw_sdio - > power = HW_SDIO_POWER_ON ;
break ;
default :
LOG_W ( " unknown power_mode %d " , io_cfg - > power_mode ) ;
break ;
}
RTHW_SDIO_UNLOCK ( sdio ) ;
}
/**
/**
* @ brief This function upda te sdio interrupt .
* @ brief This function interrupt process function .
* @ param host rt_mmcsd_host
* @ param host rt_mmcsd_host
* @ param enable
* @ retval None
* @ retval None
*/
*/
void rthw_sdio_irq_update ( struct rt_mmcsd_host * host , rt_int32_t enable )
void rthw_sdio_irq_process ( struct rt_mmcsd_host * host )
{
{
struct rthw_sdio * sdio = host - > private_data ;
struct rthw_sdio * sdio = host - > private_data ;
struct stm32_sdio * hw_sdio = sdio - > sdio_des . hw_sdio ;
struct stm32_sdio * hw_sdio = sdio - > sdio_des . hw_sdio ;
rt_uint32_t intstatus = hw_sdio - > sta ;
if ( enable )
/* clear irq flag*/
{
hw_sdio - > icr = intstatus ;
LOG_D ( " enable sdio irq " ) ;
hw_sdio - > mask | = HW_SDIO_IT_SDIOIT ;
}
else
{
LOG_D ( " disable sdio irq " ) ;
hw_sdio - > mask & = ~ HW_SDIO_IT_SDIOIT ;
}
}
/**
rt_event_send ( & sdio - > event , intstatus ) ;
* @ brief This function delect sdcard .
* @ param host rt_mmcsd_host
* @ retval 0x01
*/
static rt_int32_t rthw_sd_delect ( struct rt_mmcsd_host * host )
{
LOG_D ( " try to detect device " ) ;
return 0x01 ;
}
}
/**
/**
* @ brief This function interrupt process function .
* @ brief This function config sdio .
* @ param host rt_mmcsd_host
* @ param host rt_mmcsd_host
* @ param io_cfg rt_mmcsd_io_cfg
* @ retval None
* @ retval None
*/
*/
void rthw_sdio_irq_process ( struct rt_mmcsd_host * host )
static void rthw_sdio_iocfg ( struct rt_mmcsd_host * host , struct rt_mmcsd_io_cfg * io_cfg )
{
{
int complete = 0 ;
rt_uint32_t temp , clk_src ;
rt_uint32_t clk = io_cfg - > clock ;
struct rthw_sdio * sdio = host - > private_data ;
struct rthw_sdio * sdio = host - > private_data ;
struct stm32_sdio * hw_sdio = sdio - > sdio_des . hw_sdio ;
struct stm32_sdio * hw_sdio = sdio - > sdio_des . hw_sdio ;
rt_uint32_t intstatus = hw_sdio - > sta ;
if ( intstatus & HW_SDIO_ERRORS )
LOG_D ( " clk:%dK width:%s%s%s power:%s%s%s " ,
{
clk / 1000 ,
hw_sdio - > icr = HW_SDIO_ERRORS ;
io_cfg - > bus_width = = MMCSD_BUS_WIDTH_8 ? " 8 " : " " ,
complete = 1 ;
io_cfg - > bus_width = = MMCSD_BUS_WIDTH_4 ? " 4 " : " " ,
}
io_cfg - > bus_width = = MMCSD_BUS_WIDTH_1 ? " 1 " : " " ,
else
io_cfg - > power_mode = = MMCSD_POWER_OFF ? " OFF " : " " ,
{
io_cfg - > power_mode = = MMCSD_POWER_UP ? " UP " : " " ,
if ( intstatus & HW_SDIO_IT_CMDREND )
io_cfg - > power_mode = = MMCSD_POWER_ON ? " ON " : " "
{
) ;
hw_sdio - > icr = HW_SDIO_IT_CMDREND ;
if ( sdio - > pkg ! = RT_NULL )
{
if ( ! sdio - > pkg - > cmd - > data )
{
complete = 1 ;
}
else if ( ( sdio - > pkg - > cmd - > data - > flags & DATA_DIR_WRITE ) )
{
hw_sdio - > dctrl | = HW_SDIO_DPSM_ENABLE ;
}
}
}
if ( intstatus & HW_SDIO_IT_CMDSENT )
clk_src = SDIO_CLOCK_FREQ ;
{
hw_sdio - > icr = HW_SDIO_IT_CMDSENT ;
if ( resp_type ( sdio - > pkg - > cmd ) = = RESP_NONE )
if ( clk > 0 )
{
{
complete = 1 ;
if ( clk > host - > freq_max )
}
clk = host - > freq_max ;
temp = DIV_ROUND_UP ( clk_src , 2 * clk ) ;
if ( temp > 0x3FF )
temp = 0x3FF ;
}
}
if ( intstatus & HW_SDIO_IT_DATAEND )
if ( io_cfg - > bus_width = = MMCSD_BUS_WIDTH_4 )
{
temp | = SDMMC_CLKCR_WIDBUS_0 ;
hw_sdio - > icr = HW_SDIO_IT_DATAEND ;
else if ( io_cfg - > bus_width = = MMCSD_BUS_WIDTH_8 )
complete = 1 ;
temp | = SDMMC_CLKCR_WIDBUS_1 ;
}
}
if ( ( intstatus & HW_SDIO_IT_SDIOIT ) & & ( hw_sdio - > mask & HW_SDIO_IT_SDIOIT ) )
hw_sdio - > clkcr = temp ;
{
hw_sdio - > icr = HW_SDIO_IT_SDIOIT ;
sdio_irq_wakeup ( host ) ;
}
if ( complete )
if ( io_cfg - > power_mode = = MMCSD_POWER_ON )
{
hw_sdio - > power | = SDMMC_POWER_PWRCTRL ;
hw_sdio - > mask & = ~ HW_SDIO_ERRORS ;
rt_event_send ( & sdio - > event , intstatus ) ;
}
}
}
static const struct rt_mmcsd_host_ops ops =
static const struct rt_mmcsd_host_ops ops =
{
{
rthw_sdio_request ,
rthw_sdio_request ,
rthw_sdio_iocfg ,
rthw_sdio_iocfg ,
rthw_sd_delect ,
RT_NULL ,
rthw_sdio_irq_update ,
RT_NULL ,
} ;
} ;
/**
/**
@ -620,20 +379,15 @@ struct rt_mmcsd_host *sdio_host_create(struct stm32_sdio_des *sdio_des)
struct rt_mmcsd_host * host ;
struct rt_mmcsd_host * host ;
struct rthw_sdio * sdio = RT_NULL ;
struct rthw_sdio * sdio = RT_NULL ;
if ( ( sdio_des = = RT_NULL ) | | ( sdio_des - > txconfig = = RT_NULL ) | | ( sdio_des - > rxconfig = = RT_NULL ) )
if ( sdio_des = = RT_NULL )
{
{
LOG_E ( " L:%d F:%s %s %s %s " ,
( sdio_des = = RT_NULL ? " sdio_des is NULL " : " " ) ,
( sdio_des ? ( sdio_des - > txconfig ? " txconfig is NULL " : " " ) : " " ) ,
( sdio_des ? ( sdio_des - > rxconfig ? " rxconfig is NULL " : " " ) : " " )
) ;
return RT_NULL ;
return RT_NULL ;
}
}
sdio = rt_malloc ( sizeof ( struct rthw_sdio ) ) ;
sdio = rt_malloc ( sizeof ( struct rthw_sdio ) ) ;
if ( sdio = = RT_NULL )
if ( sdio = = RT_NULL )
{
{
LOG_E ( " L:%d F:%s malloc rthw_sdio fail" ) ;
LOG_E ( " malloc rthw_sdio fail " ) ;
return RT_NULL ;
return RT_NULL ;
}
}
rt_memset ( sdio , 0 , sizeof ( struct rthw_sdio ) ) ;
rt_memset ( sdio , 0 , sizeof ( struct rthw_sdio ) ) ;
@ -641,28 +395,33 @@ struct rt_mmcsd_host *sdio_host_create(struct stm32_sdio_des *sdio_des)
host = mmcsd_alloc_host ( ) ;
host = mmcsd_alloc_host ( ) ;
if ( host = = RT_NULL )
if ( host = = RT_NULL )
{
{
LOG_E ( " L:%d F:%s mmcsd alloc host fail " ) ;
LOG_E ( " alloc host fail " ) ;
rt_free ( sdio ) ;
goto err ;
return RT_NULL ;
}
}
rt_memcpy ( & sdio - > sdio_des , sdio_des , sizeof ( struct stm32_sdio_des ) ) ;
rt_memcpy ( & sdio - > sdio_des , sdio_des , sizeof ( struct stm32_sdio_des ) ) ;
sdio - > sdio_des . hw_sdio = ( sdio_des - > hw_sdio = = RT_NULL ? ( struct stm32_sdio * ) SDIO_BASE_ADDRESS : sdio_des - > hw_sdio ) ;
sdio - > sdio_des . clk_get = ( sdio_des - > clk_get = = RT_NULL ? stm32_sdio_clk_get : sdio_des - > clk_get ) ;
if ( sdio_des - > hsd . Instance = = SDMMC1 ) {
sdio - > sdio_des . hw_sdio = ( struct stm32_sdio * ) SDIO1_BASE_ADDRESS ;
rt_event_init ( & sdio - > event , " sdio " , RT_IPC_FLAG_FIFO ) ;
rt_event_init ( & sdio - > event , " sdio " , RT_IPC_FLAG_FIFO ) ;
rt_mutex_init ( & sdio - > mutex , " sdio " , RT_IPC_FLAG_FIFO ) ;
}
/* set host defautl attributes */
if ( sdio_des - > hsd . Instance = = SDMMC2 ) {
sdio - > sdio_des . hw_sdio = ( struct stm32_sdio * ) SDIO2_BASE_ADDRESS ;
rt_event_init ( & sdio - > event , " sdio2 " , RT_IPC_FLAG_FIFO ) ;
}
/* set host default attributes */
host - > ops = & ops ;
host - > ops = & ops ;
host - > freq_min = 400 * 1000 ;
host - > freq_min = 400 * 1000 ;
host - > freq_max = SDIO_MAX_FREQ ;
host - > freq_max = SDIO_MAX_FREQ ;
host - > valid_ocr = 0 X00FFFF80 ; /* The voltage range supported is 1.65v-3.6v */
host - > valid_ocr = VDD_32_33 | VDD_33_34 ; /* The voltage range supported is 3.2v-3.4v */
# ifndef SDIO_USING_1_BIT
//#ifndef SDIO_USING_1_BIT
host - > flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ ;
host - > flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED ;
# else
//#else
host - > flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ ;
// host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED;
# endif
//#endif
host - > max_seg_size = SDIO_BUFF_SIZE ;
host - > max_seg_size = SDIO_BUFF_SIZE ;
host - > max_dma_segs = 1 ;
host - > max_dma_segs = 1 ;
host - > max_blk_size = 512 ;
host - > max_blk_size = 512 ;
@ -672,218 +431,75 @@ struct rt_mmcsd_host *sdio_host_create(struct stm32_sdio_des *sdio_des)
sdio - > host = host ;
sdio - > host = host ;
host - > private_data = sdio ;
host - > private_data = sdio ;
rthw_sdio_irq_update ( host , 1 ) ;
/* ready to change */
/* ready to change */
mmcsd_change ( host ) ;
mmcsd_change ( host ) ;
return host ;
return host ;
}
/**
* @ brief This function configures the DMATX .
* @ param BufferSRC : pointer to the source buffer
* @ param BufferSize : buffer size
* @ retval None
*/
void SD_LowLevel_DMA_TxConfig ( uint32_t * src , uint32_t * dst , uint32_t BufferSize )
{
# if defined(SOC_SERIES_STM32F1)
static uint32_t size = 0 ;
size + = BufferSize * 4 ;
sdio_obj . cfg = & sdio_config ;
sdio_obj . dma . handle_tx . Instance = sdio_config . dma_tx . Instance ;
sdio_obj . dma . handle_tx . Init . Direction = DMA_MEMORY_TO_PERIPH ;
sdio_obj . dma . handle_tx . Init . MemDataAlignment = DMA_MDATAALIGN_WORD ;
sdio_obj . dma . handle_tx . Init . MemInc = DMA_MINC_ENABLE ;
sdio_obj . dma . handle_tx . Init . PeriphDataAlignment = DMA_PDATAALIGN_WORD ;
sdio_obj . dma . handle_tx . Init . PeriphInc = DMA_PINC_DISABLE ;
sdio_obj . dma . handle_tx . Init . Priority = DMA_PRIORITY_MEDIUM ;
/* DMA_PFCTRL */
HAL_DMA_DeInit ( & sdio_obj . dma . handle_tx ) ;
HAL_DMA_Init ( & sdio_obj . dma . handle_tx ) ;
HAL_DMA_Start ( & sdio_obj . dma . handle_tx , ( uint32_t ) src , ( uint32_t ) dst , BufferSize ) ;
# elif defined(SOC_SERIES_STM32L4)
static uint32_t size = 0 ;
size + = BufferSize * 4 ;
sdio_obj . cfg = & sdio_config ;
sdio_obj . dma . handle_tx . Instance = sdio_config . dma_tx . Instance ;
sdio_obj . dma . handle_tx . Init . Request = sdio_config . dma_tx . request ;
sdio_obj . dma . handle_tx . Init . Direction = DMA_MEMORY_TO_PERIPH ;
sdio_obj . dma . handle_tx . Init . PeriphInc = DMA_PINC_DISABLE ;
sdio_obj . dma . handle_tx . Init . MemInc = DMA_MINC_ENABLE ;
sdio_obj . dma . handle_tx . Init . PeriphDataAlignment = DMA_PDATAALIGN_WORD ;
sdio_obj . dma . handle_tx . Init . MemDataAlignment = DMA_MDATAALIGN_WORD ;
sdio_obj . dma . handle_tx . Init . Mode = DMA_NORMAL ;
sdio_obj . dma . handle_tx . Init . Priority = DMA_PRIORITY_MEDIUM ;
HAL_DMA_DeInit ( & sdio_obj . dma . handle_tx ) ;
HAL_DMA_Init ( & sdio_obj . dma . handle_tx ) ;
HAL_DMA_Start ( & sdio_obj . dma . handle_tx , ( uint32_t ) src , ( uint32_t ) dst , BufferSize ) ;
# else
static uint32_t size = 0 ;
size + = BufferSize * 4 ;
sdio_obj . cfg = & sdio_config ;
sdio_obj . dma . handle_tx . Instance = sdio_config . dma_tx . Instance ;
sdio_obj . dma . handle_tx . Init . Channel = sdio_config . dma_tx . channel ;
sdio_obj . dma . handle_tx . Init . Direction = DMA_MEMORY_TO_PERIPH ;
sdio_obj . dma . handle_tx . Init . PeriphInc = DMA_PINC_DISABLE ;
sdio_obj . dma . handle_tx . Init . MemInc = DMA_MINC_ENABLE ;
sdio_obj . dma . handle_tx . Init . PeriphDataAlignment = DMA_PDATAALIGN_WORD ;
sdio_obj . dma . handle_tx . Init . MemDataAlignment = DMA_MDATAALIGN_WORD ;
sdio_obj . dma . handle_tx . Init . Mode = DMA_PFCTRL ;
sdio_obj . dma . handle_tx . Init . Priority = DMA_PRIORITY_MEDIUM ;
sdio_obj . dma . handle_tx . Init . FIFOMode = DMA_FIFOMODE_ENABLE ;
sdio_obj . dma . handle_tx . Init . FIFOThreshold = DMA_FIFO_THRESHOLD_FULL ;
sdio_obj . dma . handle_tx . Init . MemBurst = DMA_MBURST_INC4 ;
sdio_obj . dma . handle_tx . Init . PeriphBurst = DMA_PBURST_INC4 ;
/* DMA_PFCTRL */
HAL_DMA_DeInit ( & sdio_obj . dma . handle_tx ) ;
HAL_DMA_Init ( & sdio_obj . dma . handle_tx ) ;
HAL_DMA_Start ( & sdio_obj . dma . handle_tx , ( uint32_t ) src , ( uint32_t ) dst , BufferSize ) ;
# endif
}
/**
* @ brief This function configures the DMARX .
* @ param BufferDST : pointer to the destination buffer
* @ param BufferSize : buffer size
* @ retval None
*/
void SD_LowLevel_DMA_RxConfig ( uint32_t * src , uint32_t * dst , uint32_t BufferSize )
{
# if defined(SOC_SERIES_STM32F1)
sdio_obj . cfg = & sdio_config ;
sdio_obj . dma . handle_rx . Instance = sdio_config . dma_tx . Instance ;
sdio_obj . dma . handle_rx . Init . Direction = DMA_PERIPH_TO_MEMORY ;
sdio_obj . dma . handle_rx . Init . MemDataAlignment = DMA_MDATAALIGN_WORD ;
sdio_obj . dma . handle_rx . Init . MemInc = DMA_MINC_ENABLE ;
sdio_obj . dma . handle_rx . Init . PeriphDataAlignment = DMA_PDATAALIGN_WORD ;
sdio_obj . dma . handle_rx . Init . PeriphInc = DMA_PINC_DISABLE ;
sdio_obj . dma . handle_rx . Init . Priority = DMA_PRIORITY_MEDIUM ;
HAL_DMA_DeInit ( & sdio_obj . dma . handle_rx ) ;
HAL_DMA_Init ( & sdio_obj . dma . handle_rx ) ;
HAL_DMA_Start ( & sdio_obj . dma . handle_rx , ( uint32_t ) src , ( uint32_t ) dst , BufferSize ) ;
# elif defined(SOC_SERIES_STM32L4)
sdio_obj . cfg = & sdio_config ;
sdio_obj . dma . handle_rx . Instance = sdio_config . dma_tx . Instance ;
sdio_obj . dma . handle_rx . Init . Request = sdio_config . dma_tx . request ;
sdio_obj . dma . handle_rx . Init . Direction = DMA_PERIPH_TO_MEMORY ;
sdio_obj . dma . handle_rx . Init . PeriphInc = DMA_PINC_DISABLE ;
sdio_obj . dma . handle_rx . Init . MemInc = DMA_MINC_ENABLE ;
sdio_obj . dma . handle_rx . Init . PeriphDataAlignment = DMA_PDATAALIGN_WORD ;
sdio_obj . dma . handle_rx . Init . MemDataAlignment = DMA_MDATAALIGN_WORD ;
sdio_obj . dma . handle_rx . Init . Mode = DMA_NORMAL ;
sdio_obj . dma . handle_rx . Init . Priority = DMA_PRIORITY_LOW ;
HAL_DMA_DeInit ( & sdio_obj . dma . handle_rx ) ;
HAL_DMA_Init ( & sdio_obj . dma . handle_rx ) ;
HAL_DMA_Start ( & sdio_obj . dma . handle_rx , ( uint32_t ) src , ( uint32_t ) dst , BufferSize ) ;
# else
sdio_obj . cfg = & sdio_config ;
sdio_obj . dma . handle_rx . Instance = sdio_config . dma_tx . Instance ;
sdio_obj . dma . handle_rx . Init . Channel = sdio_config . dma_tx . channel ;
sdio_obj . dma . handle_rx . Init . Direction = DMA_PERIPH_TO_MEMORY ;
sdio_obj . dma . handle_rx . Init . PeriphInc = DMA_PINC_DISABLE ;
sdio_obj . dma . handle_rx . Init . MemInc = DMA_MINC_ENABLE ;
sdio_obj . dma . handle_rx . Init . PeriphDataAlignment = DMA_PDATAALIGN_WORD ;
sdio_obj . dma . handle_rx . Init . MemDataAlignment = DMA_MDATAALIGN_WORD ;
sdio_obj . dma . handle_rx . Init . Mode = DMA_PFCTRL ;
sdio_obj . dma . handle_rx . Init . Priority = DMA_PRIORITY_MEDIUM ;
sdio_obj . dma . handle_rx . Init . FIFOMode = DMA_FIFOMODE_ENABLE ;
sdio_obj . dma . handle_rx . Init . FIFOThreshold = DMA_FIFO_THRESHOLD_FULL ;
sdio_obj . dma . handle_rx . Init . MemBurst = DMA_MBURST_INC4 ;
sdio_obj . dma . handle_rx . Init . PeriphBurst = DMA_PBURST_INC4 ;
HAL_DMA_DeInit ( & sdio_obj . dma . handle_rx ) ;
HAL_DMA_Init ( & sdio_obj . dma . handle_rx ) ;
HAL_DMA_Start ( & sdio_obj . dma . handle_rx , ( uint32_t ) src , ( uint32_t ) dst , BufferSize ) ;
# endif
}
err :
if ( sdio ) rt_free ( sdio ) ;
/**
* @ brief This function get stm32 sdio clock .
* @ param hw_sdio : stm32_sdio
* @ retval PCLK2Freq
*/
static rt_uint32_t stm32_sdio_clock_get ( struct stm32_sdio * hw_sdio )
{
return HAL_RCC_GetPCLK2Freq ( ) ;
}
static rt_err_t DMA_TxConfig ( rt_uint32_t * src , rt_uint32_t * dst , int Size )
return RT_NULL ;
{
SD_LowLevel_DMA_TxConfig ( ( uint32_t * ) src , ( uint32_t * ) dst , Size / 4 ) ;
return RT_EOK ;
}
}
static rt_err_t DMA_RxConfig ( rt_uint32_t * src , rt_uint32_t * dst , int Size )
void SDMMC1_IRQHandler ( void )
{
{
SD_LowLevel_DMA_RxConfig ( ( uint32_t * ) src , ( uint32_t * ) dst , Size / 4 ) ;
/* enter interrupt */
return RT_EOK ;
rt_interrupt_enter ( ) ;
/* Process All SDIO Interrupt Sources */
if ( host1 ) rthw_sdio_irq_process ( host1 ) ;
/* leave interrupt */
rt_interrupt_leave ( ) ;
}
}
void SDIO_IRQHandler ( void )
void SDMMC2_IRQHandler ( void )
{
{
/* enter interrupt */
/* enter interrupt */
rt_interrupt_enter ( ) ;
rt_interrupt_enter ( ) ;
/* Process All SDIO Interrupt Sources */
/* Process All SDIO Interrupt Sources */
rthw_sdio_irq_process ( host ) ;
if ( host2 ) rthw_sdio_irq_process ( host2 ) ;
/* leave interrupt */
/* leave interrupt */
rt_interrupt_leave ( ) ;
rt_interrupt_leave ( ) ;
}
}
int rt_hw_sdio_init ( void )
int rt_hw_sdio_init ( void )
{
{
struct stm32_sdio_des sdio_des ;
# ifdef BSP_USING_SDIO1
SD_HandleTypeDef hsd ;
struct stm32_sdio_des sdio_des1 ;
hsd . Instance = SDCARD_INSTANCE ;
sdio_des1 . hsd . Instance = SDMMC1 ;
{
HAL_SD_MspInit ( & sdio_des1 . hsd ) ;
rt_uint32_t tmpreg = 0x00U ;
# if defined(SOC_SERIES_STM32F1)
host1 = sdio_host_create ( & sdio_des1 ) ;
/* enable DMA clock && Delay after an RCC peripheral clock enabling*/
if ( host1 = = RT_NULL )
SET_BIT ( RCC - > AHBENR , sdio_config . dma_rx . dma_rcc ) ;
{
tmpreg = READ_BIT ( RCC - > AHBENR , sdio_config . dma_rx . dma_rcc ) ;
LOG_E ( " host create fail " ) ;
# elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4)
return RT_NULL ;
SET_BIT ( RCC - > AHB1ENR , sdio_config . dma_rx . dma_rcc ) ;
/* Delay after an RCC peripheral clock enabling */
tmpreg = READ_BIT ( RCC - > AHB1ENR , sdio_config . dma_rx . dma_rcc ) ;
# endif
UNUSED ( tmpreg ) ; /* To avoid compiler warnings */
}
}
HAL_NVIC_SetPriority ( SDIO_IRQn , 2 , 0 ) ;
# endif
HAL_NVIC_EnableIRQ ( SDIO_IRQn ) ;
HAL_SD_MspInit ( & hsd ) ;
sdio_des . clk_get = stm32_sdio_clock_get ;
# ifdef BSP_USING_SDIO2
sdio_des . hw_sdio = ( struct stm32_sdio * ) SDCARD_INSTANCE ;
//sdmmc2 wifi
sdio_des . rxconfig = DMA_RxConfig ;
struct stm32_sdio_des sdio_des2 ;
sdio_des . txconfig = DMA_TxConfig ;
sdio_des2 . hsd . Instance = SDMMC2 ;
HAL_SD_MspInit ( & sdio_des2 . hsd ) ;
host = sdio_host_create ( & sdio_des ) ;
host2 = sdio_host_create ( & sdio_des2 ) ;
if ( host = = RT_NULL )
if ( host2 = = RT_NULL )
{
{
LOG_E ( " host create fail " ) ;
LOG_E ( " host2 create fail " ) ;
return - 1 ;
return RT_NULL ;
}
}
# endif
return 0 ;
return 0 ;
}
}
INIT_DEVICE_EXPORT ( rt_hw_sdio_init ) ;
INIT_DEVICE_EXPORT ( rt_hw_sdio_init ) ;
void stm32_mmcs d_change ( void )
void sdcard_change ( void )
{
{
mmcsd_change ( host ) ;
mmcsd_change ( host1 ) ;
}
}
# endif /* RT_USING_SDIO */
# endif
# endif