/**
* @file         dev_sdc_init.c
* @brief        对sd卡的初始化函数
* @details      初始化dma和sdc
*               读取sd卡的一些寄存器信息
* @author       涂龙
* @date         2021-12-07 17:01
* @version      V0.2
* @copyright    Copyright (c) 2017-2021  SpaceTouch Inc.
* +v0.1
*   添加错误码
*   添加等待超时
*   修改函数名
*
* +v0.1a
*   将等待超时由mtime的中断方式修改为mtime的查询方式
* +v0.2
*   将函数需要全局变量经量修改为参数需求
* +v0.2a
*   将mtime作为超时检测的机制改为mcycle
*  +v0.3a
*   sdc模块根据读写的长度，使用单块或多块读写命令
*   使用misra规则，修改代码风格
*  +v0.3b
*   为了适应emmc模块的添加，修改代码封装
*
*/

#include "platform.h"
#include "hal_sd_card.h"

/**
* @brief        设置存储卡的工作时钟
* @details
* @param        @arg div ：时钟的分频数
*               @arg mcycle_ms_freq ：mcycle每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CAED_ErrorCodeEnum
* @note         无
*/
uint32_t hal_sdc_set_clock(uint32_t div, uint64_t mcycle_ms_freq)
{
    return hal_memory_card_clock(div, mcycle_ms_freq);
}

/**
* @brief        发送cmd0使卡复位
* @details
* @param        @arg argument ：cmd的参数
*               @arg sd_response ：cmd的响应存放
*               @arg mcycle_ms_freq ：mcycle每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CAED_ErrorCodeEnum
* @note         cmd0 参数为0 ，无响应
*/
uint32_t hal_sdc_go_idle(uint32_t argument, uint32_t *sd_response, uint64_t mcycle_ms_freq)
{
    uint32_t sd_cmd, sd_arg;
    uint32_t ret = 0;
    sd_arg = argument;
    sd_cmd = SD_CMD(0)
             | DEV_SDC_CMD_WAIT_PRVDATA_COMPLETE //等待前面的数据转换完成在发送此命令
             | DEV_SDC_CMD_SEND_INITIALIZATION //发送初始化80个时钟
             | DEV_SDC_CMD_START_CMD //开始发送命令，命令发送后硬件清零
             ;
    ret = hal_sdc_send_cmd(sd_cmd, sd_arg, sd_response, mcycle_ms_freq);
    return ret;
}

/**
* @brief        发送cmd8使卡的电压和容量匹配
* @details
* @param        @arg argument ：cmd的参数
*               @arg sd_response ：cmd的响应存放
*               @arg mcycle_ms_freq ：mcycle每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CAED_ErrorCodeEnum
* @note
*/
uint32_t hal_sdc_send_interface_condition(uint32_t argument, uint32_t *sd_response, uint64_t mcycle_ms_freq)
{
    uint32_t sd_cmd, sd_arg;
    uint32_t ret = 0;
    //电压配置错位，acmd41会超时
    sd_arg = argument;//2.7-3.6V
    sd_cmd = SD_CMD(8)
             | DEV_SDC_CMD_RESPONSE_EXPECT //期望响应
             | DEV_SDC_CMD_CHECK_RESPONSE_CRC //检测响应crc
             | DEV_SDC_CMD_WAIT_PRVDATA_COMPLETE //等待前面的数据转换完成在发送此命令
             | DEV_SDC_CMD_START_CMD //开始发送命令，命令发送后硬件清零
             ;
    ret = hal_sdc_send_cmd(sd_cmd, sd_arg, sd_response, mcycle_ms_freq);
    return ret;
}


/**
* @brief        发送cmd55为下一个辅助命令准备
* @details
* @param        @arg argument ：cmd的参数
*                       0或卡的相对地址
*               @arg sd_response ：cmd的响应存放
*               @arg mcycle_ms_freq ：mcycle每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CAED_ErrorCodeEnum
* @note
*/
uint32_t hal_sdc_app_cmd(uint32_t argument, uint32_t *sd_response, uint64_t mcycle_ms_freq)
{
    uint32_t sd_cmd, sd_arg;
    uint32_t ret = 0;
    sd_arg = argument;
    sd_cmd =  SD_CMD(55)
              | DEV_SDC_CMD_RESPONSE_EXPECT //期望响应
              | DEV_SDC_CMD_CHECK_RESPONSE_CRC //检测响应crc
              | DEV_SDC_CMD_WAIT_PRVDATA_COMPLETE //等待前面的数据转换完成在发送此命令
              | DEV_SDC_CMD_START_CMD //开始发送命令，命令发送后硬件清零
              ;
    ret = hal_sdc_send_cmd(sd_cmd, sd_arg, sd_response, mcycle_ms_freq);
    return ret;
}


/**
* @brief        发送acmd41使卡初始匹配
* @details
* @param        @arg argument ：cmd的参数
*               @arg sd_response ：cmd的响应存放
*               @arg mcycle_ms_freq ：mcycle每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CAED_ErrorCodeEnum
* @note         函数需要一段时间，直到响应为非busy为止
*/
uint32_t hal_sdc_send_operating_condition(uint32_t argument, uint32_t *sd_response, uint64_t mcycle_ms_freq)
{
    uint32_t sd_cmd, sd_arg;
    uint32_t ret = 0;
#if DEV_SDC_TIME_OUT_CHECK == 1
    //卡初始化应在发送第一个acmd41一秒内完成
    uint64_t time_out_value = sdc_read_mcycle() + mcycle_ms_freq * 10 * DEV_SDC_TIME_OUT_TIME;
#endif

    do
    {
#if DEV_SDC_TIME_OUT_CHECK == 1

        if (sdc_read_mcycle() >= time_out_value)
        {
            return ERR_CARD_READ_CARD_READY_TIMEOUT;
        }

#endif
        ret = hal_sdc_app_cmd(0, sd_response, mcycle_ms_freq);

        if (ret != 0)
        {
            if ((ret & ERR_CARD_RESPONSE_TIMEOUT) == ERR_CARD_RESPONSE_TIMEOUT)
            {
                return ret | ERR_CARD_NOT_CARD;
            }
            else
            {
                return ret | ERR_CARD_HARDWARE_ERROR;
            }
        }

        sd_arg = argument;
        sd_cmd = SD_ACMD(41)
                 | DEV_SDC_CMD_RESPONSE_EXPECT //期望响应
                 | DEV_SDC_CMD_WAIT_PRVDATA_COMPLETE //等待前面的数据转换完成在发送此命令
                 | DEV_SDC_CMD_START_CMD //开始发送命令，命令发送后硬件清零
                 ;
        ret = hal_sdc_send_cmd(sd_cmd, sd_arg, sd_response, mcycle_ms_freq);

        if (ret != 0)
        {
            return ret | ERR_CARD_INVALID_CARD;
        }
    }
    while ((sd_response[0]&DEV_SDC_ACMD41_RESPONSE_BUSY) == 0);

    return ret;
}

/**
* @brief        发送cmd2获取卡cid寄存器信息
* @details
* @param        @arg argument ：cmd的参数
*                       0
*               @arg sd_response ：cmd的响应存放
*               @arg mcycle_ms_freq ：mcycle每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CAED_ErrorCodeEnum
* @note
*/
uint32_t hal_sdc_send_CID(uint32_t argument, uint32_t *sd_response, uint64_t mcycle_ms_freq)
{
    uint32_t sd_cmd, sd_arg;
    uint32_t ret = 0;
    sd_arg = argument;
    sd_cmd =  SD_CMD(2)
              | DEV_SDC_CMD_RESPONSE_EXPECT //期望响应
              | DEV_SDC_CMD_RESPONSE_LENGTH //长响应
              | DEV_SDC_CMD_CHECK_RESPONSE_CRC //检测响应crc
              | DEV_SDC_CMD_WAIT_PRVDATA_COMPLETE //等待前面的数据转换完成在发送此命令
              | DEV_SDC_CMD_START_CMD //开始发送命令，命令发送后硬件清零
              ;
    ret = hal_sdc_send_cmd(sd_cmd, sd_arg, sd_response, mcycle_ms_freq);
    return ret;
}

/**
* @brief        发送cmd3获取卡相对地址
* @details
* @param        @arg argument ：cmd的参数
*                       0
*               @arg sd_response ：cmd的响应存放
*               @arg mcycle_ms_freq ：mcycle每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CAED_ErrorCodeEnum
* @note
*/
uint32_t hal_sdc_ask_RCA(uint32_t argument, uint32_t *sd_response, uint64_t mcycle_ms_freq)
{
    uint32_t sd_cmd, sd_arg;
    uint32_t ret = 0;
    sd_arg = argument;
    sd_cmd =  SD_CMD(3)
              | DEV_SDC_CMD_RESPONSE_EXPECT //期望响应
              | DEV_SDC_CMD_CHECK_RESPONSE_CRC //检测响应crc
              | DEV_SDC_CMD_WAIT_PRVDATA_COMPLETE //等待前面的数据转换完成在发送此命令
              | DEV_SDC_CMD_START_CMD //开始发送命令，命令发送后硬件清零
              ;
    ret = hal_sdc_send_cmd(sd_cmd, sd_arg, sd_response, mcycle_ms_freq);
    return ret;
}
/**
* @brief        发送cmd9获取卡csd寄存器信息
* @details
* @param        @arg argument ：cmd的参数
*                       卡的相对地址
*               @arg sd_response ：cmd的响应存放
*               @arg mcycle_ms_freq ：mcycle每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CAED_ErrorCodeEnum
* @note
*/
uint32_t hal_sdc_send_CSD(uint32_t argument, uint32_t *sd_response, uint64_t mcycle_ms_freq)
{
    uint32_t sd_cmd, sd_arg;
    uint32_t ret = 0;
    sd_arg = argument;
    sd_cmd =  SD_CMD(9)
              | DEV_SDC_CMD_RESPONSE_EXPECT //期望响应
              | DEV_SDC_CMD_RESPONSE_LENGTH //长响应
              | DEV_SDC_CMD_CHECK_RESPONSE_CRC //检测响应crc
              | DEV_SDC_CMD_WAIT_PRVDATA_COMPLETE //等待前面的数据转换完成在发送此命令
              | DEV_SDC_CMD_START_CMD //开始发送命令，命令发送后硬件清零
              ;
    ret = hal_sdc_send_cmd(sd_cmd, sd_arg, sd_response, mcycle_ms_freq);
    return ret;
}
/**
* @brief        发送cmd7获取卡将卡状态切换在standby和transfer之间
* @details
* @param        @arg argument ：cmd的参数
*                       卡的相对地址
*               @arg sd_response ：cmd的响应存放
*               @arg mcycle_ms_freq ：mcycle每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CAED_ErrorCodeEnum
* @note
*/
uint32_t hal_sdc_toggle_standby_transfer(uint32_t argument, uint32_t *sd_response, uint64_t mcycle_ms_freq)
{
    uint32_t sd_cmd, sd_arg;
    uint32_t ret = 0;
    sd_arg = argument;
    sd_cmd =  SD_CMD(7)
              | DEV_SDC_CMD_RESPONSE_EXPECT //期望响应
              | DEV_SDC_CMD_CHECK_RESPONSE_CRC //检测响应crc
              | DEV_SDC_CMD_WAIT_PRVDATA_COMPLETE //等待前面的数据转换完成在发送此命令
              | DEV_SDC_CMD_START_CMD //开始发送命令，命令发送后硬件清零
              ;
    ret = hal_sdc_send_cmd(sd_cmd, sd_arg, sd_response, mcycle_ms_freq);
    return ret;
}


/**
* @brief        发送acmd6修改卡的bus宽度
* @details
* @param        @arg argument ：cmd的参数
*                       0：单线
*                       2：四线
*               @arg sd_response ：cmd的响应存放
*               @arg mcycle_ms_freq ：mcycle每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CAED_ErrorCodeEnum
* @note
*/
uint32_t hal_sdc_set_bus_width(uint32_t argument, uint32_t *sd_response, uint64_t mcycle_ms_freq)
{
    uint32_t sd_cmd, sd_arg;
    uint32_t ret = 0;
    sd_arg = argument;
    sd_cmd = SD_ACMD(6)
             | DEV_SDC_CMD_RESPONSE_EXPECT //期望响应
             | DEV_SDC_CMD_CHECK_RESPONSE_CRC //检测响应crc
             | DEV_SDC_CMD_WAIT_PRVDATA_COMPLETE //等待前面的数据转换完成在发送此命令
             | DEV_SDC_CMD_START_CMD //开始发送命令，命令发送后硬件清零
             ;
    ret = hal_sdc_send_cmd(sd_cmd, sd_arg, sd_response, mcycle_ms_freq);
    return ret;
}
/**
* @brief        初始化sd卡
* @details      对sdsc hc xc卡的初始化
* @param        @arg bus_width sdc通信的数据线
*               @arg clk sdc通信的时钟频率
*               @arg sd_info 用于保留卡信息参数
* @return       @arg ret: 错误码 @ MEMORY_CARD_ErrorCodeEnum
* @note         无
*/
uint32_t hal_sdc_init(uint32_t bus_width, uint32_t clk, SDC_Info sd_info)
{
    uint32_t sd_arg;
    uint32_t sd_response[4];
    uint32_t ret = 0;
    uint32_t card_type = 0;
    uint64_t mcycle_ms_freq = sd_info->mcycle_ms_freq;
    DEV_GPIO->CTL[sd_info->clk_gpio] = 7 | DEV_GPIO_CTL_PE_ENABLE | DEV_GPIO_CTL_PS_PULLUP; //clk
    DEV_GPIO->CTL[sd_info->cmd_gpio] = 7 | DEV_GPIO_CTL_PE_ENABLE | DEV_GPIO_CTL_PS_PULLUP; //cmd
    DEV_GPIO->CTL[sd_info->d0_gpio] = 7 | DEV_GPIO_CTL_PE_ENABLE | DEV_GPIO_CTL_PS_PULLUP; //d0

    if (bus_width == 4)
    {
        DEV_GPIO->CTL[sd_info->d1_gpio] = 7 | DEV_GPIO_CTL_PE_ENABLE | DEV_GPIO_CTL_PS_PULLUP; //d1
        DEV_GPIO->CTL[sd_info->d2_gpio] = 7 | DEV_GPIO_CTL_PE_ENABLE | DEV_GPIO_CTL_PS_PULLUP; //d2
        DEV_GPIO->CTL[sd_info->d3_gpio] = 7 | DEV_GPIO_CTL_PE_ENABLE | DEV_GPIO_CTL_PS_PULLUP; //d3
    }

    DEV_RMU->RSTEN0 &= ~DEV_RMU_RSTEN0_SDC;
    DEV_CMU->CLKEN0 |= DEV_CMU_CLKEN0_SDC;
    DEV_RMU->RSTEN0 |= DEV_RMU_RSTEN0_SDC;
    DEV_CMU->SDCCLK = DEV_CMU_SDCCLK_SEL_PLL_CORE | DEV_CMU_SDCCLK_DIV_MASK;
    ret = hal_sdc_set_clock(64UL, mcycle_ms_freq); //时钟到400khz以下

    if (ret != 0)
    {
        return ERR_CARD_SET_CLOCK_FAIL;
    }

    DEV_SDC->UHSREGEXT = (0x10UL << 23UL) | (0x10UL << 16UL) | (1UL << 21UL);
    DEV_SDC->PWREN = DEV_SDC_CLKENA_ENABLE;
    DEV_SDC->TMOUT = 0xffffff64UL;
    //进入idle状态 cmd0
    ret = hal_sdc_go_idle(0, sd_response, mcycle_ms_freq);

    if (ret != 0)
    {
        return ret | ERR_CARD_HARDWARE_ERROR;
    }

    //查询电压支持信息 cmd8
    ret = hal_sdc_send_interface_condition(DEV_SDC_CMD8_HIGHT_V, sd_response, mcycle_ms_freq);

    if (ret != 0)
    {
        if ((ret & ERR_CARD_RESPONSE_TIMEOUT) == ERR_CARD_RESPONSE_TIMEOUT)
        {
            card_type = SDC_CARD_TYPE_VER1;
        }
        else
        {
            return ret | ERR_CARD_NOT_CARD;
        }
    }
    else
    {
        card_type = SDC_CARD_TYPE_VER2;
    }

    if (card_type == SDC_CARD_TYPE_VER1)
    {
        sd_arg = DEV_SDC_ACMD41_XPC | DEV_SDC_ACMD41_VOLTAGE_MASK; //hcs=0
    }
    else
    {
        sd_arg = DEV_SDC_ACMD41_HCS | DEV_SDC_ACMD41_XPC | DEV_SDC_ACMD41_VOLTAGE_MASK; //hcs=1
    }

    //发送主机支持的容量信息，获取卡的操作信息 acmd41
    ret = hal_sdc_send_operating_condition(sd_arg, sd_response, mcycle_ms_freq);

    if (ret != 0)
    {
        return ret;
    }

    if (card_type == SDC_CARD_TYPE_VER1)
    {
        card_type = SDC_CARD_TYPE_VER1_SDSC;
        sd_info->capacity = 0;  //SDSC
    }
    else
    {
        if ((sd_response[0] & DEV_SDC_ACMD41_RESPONSE_CCS) != 0)
        {
            sd_info->capacity = 1;  //SDHC/SDXC
            card_type = SDC_CARD_TYPE_VER2_SDHC;
        }
        else
        {
            sd_info->capacity = 0;  //SDSC
            card_type = SDC_CARD_TYPE_VER2_SDSC;
        }
    }

    sd_info->card_type = card_type;
    //查询CID寄存器信息 cmd2
    ret = hal_sdc_send_CID(0, sd_response, mcycle_ms_freq);

    if (ret != 0)
    {
        return ret | ERR_CARD_READ_CID_FAIL;
    }

    for (int i = 0; i < CARD_CID_LEN; i++)
    {
        sd_info->cid[i] = sd_response[i / 4] >> (8 * (i % 4));
    }

    //查询卡的相对地址 cmd3
    ret = hal_sdc_ask_RCA(0, sd_response, mcycle_ms_freq);

    if (ret != 0)
    {
        return ret | ERR_CARD_ASK_RELATIVE_ADDR_FAIL;
    }

    sd_info->relative_addr = sd_response[0] & 0xffff0000UL;
    //回去卡CSD寄存器 cmd9
    ret = hal_sdc_send_CSD(sd_info->relative_addr, sd_response, mcycle_ms_freq);

    if (ret != 0)
    {
        return ret | ERR_CARD_READ_CSD_FAIL;
    }

    for (int i = 0; i < CARD_CSD_LEN; i++)
    {
        sd_info->csd[i] = sd_response[i / 4UL] >> (8UL * (i % 4UL));
    }

    //翻转卡状态到transfer cmd7
    ret = hal_sdc_toggle_standby_transfer(sd_info->relative_addr, sd_response, mcycle_ms_freq);

    if (ret != 0)
    {
        return ret | ERR_CARD_TOGGLES_CARD_STATES_FAIL;
    }

    //发送辅助命令 cmd55
    ret = hal_sdc_app_cmd(sd_info->relative_addr, sd_response, mcycle_ms_freq);

    if (ret != 0)
    {
        return ret | ERR_CARD_SET_BUS_WIDTH_FAIL;
    }

    if (bus_width == 1)
    {
        sd_arg = 0;
        DEV_SDC->CTYPE = 0;
    }
    else if (bus_width == 4UL)
    {
        sd_arg = 2UL;
        DEV_SDC->CTYPE = 1;
    }
    else
    {
        ;
    }

    //切换bus宽度 acmd6
    ret = hal_sdc_set_bus_width(sd_arg, sd_response, mcycle_ms_freq);

    if (ret != 0)
    {
        return ret | ERR_CARD_SET_BUS_WIDTH_FAIL;
    }

    ret = hal_sdc_set_clock(DEV_SDC_CLOCK_HZ / clk, mcycle_ms_freq);

    if (ret != 0)
    {
        return ERR_CARD_SET_CLOCK_FAIL;
    }

    return ERR_CARD_NONE;
}



/**
* @brief        向sd卡发送命令
* @details      向sd卡发送命令，并将相应返回
* @param        @arg cmd: 对应命令号
*               @arg arg: 命令对应参数
*               @arg response: 命令对应相应的存放数组，大小为4word
*               @arg mcycle_ms_freq ：mcycle每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CARD_ErrorCodeEnum
* @note
*/
uint32_t hal_sdc_send_cmd(uint32_t cmd, uint32_t arg, uint32_t *response, uint64_t mcycle_ms_freq)
{
    return hal_memory_card_send_cmd(cmd, arg, response, mcycle_ms_freq);
}

/**
* @brief        向sd卡发送停止命令
* @details      向sd卡发送停止命令，并将相应返回
* @param
*               @arg mcycle_ms_freq ：mtime每毫秒的cycle数
* @return       @arg ret: 错误码 @ MEMORY_CARD_ErrorCodeEnum
* @note
*/
uint32_t hal_sdc_send_stop(uint64_t mcycle_ms_freq)
{
    return hal_memory_card_send_stop(mcycle_ms_freq);
}

void hal_dev_sdc_set_bytcnt(uint32_t cnt)
{
    DEV_SDC->BYTCNT = cnt;
}

void hal_dev_sdc_set_blksiz(uint32_t size)
{
    DEV_SDC->BLKSIZ = size;
}

void hal_dev_sdc_set_fifoth(uint32_t fifoth)
{
    DEV_SDC->FIFOTH = fifoth;
}

void hal_dev_sdc_set_dma_enable()
{
    DEV_SDC->CTRL = DEV_SDC_CTRL_DMA_ENABLE;
}

void hal_dev_sdc_set_rintsts(uint32_t val)
{
    DEV_SDC->RINTSTS = val;
}

void hal_dev_sdc_set_intmask(uint32_t val)
{
    DEV_SDC->INTMASK = val;
}

void hal_dev_sdc_set_ctrl_or(uint32_t val)
{
    DEV_SDC->CTRL |= val;
}

void hal_dev_sdc_set_ctrl_and(uint32_t val)
{
    DEV_SDC->CTRL &= val;
}



uint32_t hal_dev_sdc_get_mintsts_state()
{
    return DEV_SDC->MINTSTS;
}

uint32_t hal_dev_sdc_get_rintsts_state()
{
    if ((DEV_SDC->RINTSTS & (DEV_SDC_RINTSTS_DTO | DEV_SDC_RINTSTS_ACD)) != (DEV_SDC_RINTSTS_DTO | DEV_SDC_RINTSTS_ACD))
        return 1;
    else
        return 0;
}

uint32_t hal_dev_sdc_get_state()
{
    if ((DEV_SDC->STATUS & (DEV_SDC_STATUS_DATA_BUSY | DEV_SDC_STATUS_DATA_STATE_MC_BUSY)) != 0)
        return 1;
    else
        return 0;
}

uint32_t hal_dev_sdc_get_ctrl_fifo_reset_state()
{
    if ((DEV_SDC->CTRL & DEV_SDC_CTRL_FIFO_RESET) == DEV_SDC_CTRL_FIFO_RESET)
        return 1;
    else
        return 0;
}

Options_EnableEnum hal_dev_sdc_get_dma_cmd_state(uint32_t channelx)
{
    return DMA_GetCmdStatus(channelx);
}

void hal_dev_sdc_set_sdr_dma_config_init(uint32_t chx, uint32_t sdr, uint32_t bytcnt, uint32_t it_flag, Options_EnableEnum cmd_state)
{
    DMA_SetSourceAddr(chx, sdr);
    DMA_SetByteNum(chx, bytcnt);
//  DMA_ITConfig(chx,it_flag,ENABLE);
    DEV_DMAC->DMA_PD = (DMA_Slot_Transfer_End | DMA_Half_Transfer_End | DMA_Transfer_End) << chx;
    DEV_GLOBAL->DVDD_GLOBAL7 &= ~((DMA_Half_Transfer_End | DMA_Transfer_End) << chx);
    DEV_DMAC->DMA_IE = DEV_GLOBAL->DVDD_GLOBAL7;
    DEV_DMAC->DMA_PD = (DMA_Slot_Transfer_End | DMA_Half_Transfer_End | DMA_Transfer_End) << chx;
    DEV_GLOBAL->DVDD_GLOBAL7 |= (DMA_Transfer_End << chx);
    DEV_GLOBAL->DVDD_GLOBAL7 &= ~(DMA_Half_Transfer_End << chx);
    DEV_DMAC->DMA_IE = DEV_GLOBAL->DVDD_GLOBAL7;
    DMA_Cmd(chx, ENABLE);
}

void hal_dev_sdc_set_dst_dma_config_init(uint32_t chx, uint32_t dst, uint32_t bytcnt, uint32_t it_flag)
{
    DMA_SetDestinationAddr(chx, dst);
    DMA_SetByteNum(chx, bytcnt);
//  DMA_ITConfig(chx,it_flag ,ENABLE);
    DEV_DMAC->DMA_PD = (DMA_Slot_Transfer_End | DMA_Half_Transfer_End | DMA_Transfer_End) << chx;
    DEV_GLOBAL->DVDD_GLOBAL7 &= ~((DMA_Half_Transfer_End | DMA_Transfer_End) << chx);
    DEV_DMAC->DMA_IE = DEV_GLOBAL->DVDD_GLOBAL7;
    DEV_DMAC->DMA_PD = (DMA_Slot_Transfer_End | DMA_Half_Transfer_End | DMA_Transfer_End) << chx;
    DEV_GLOBAL->DVDD_GLOBAL7 |= (DMA_Transfer_End << chx);
    DEV_GLOBAL->DVDD_GLOBAL7 &= ~(DMA_Half_Transfer_End << chx);
    DEV_DMAC->DMA_IE = DEV_GLOBAL->DVDD_GLOBAL7;
    DMA_Cmd(chx, ENABLE);
}

void hal_dev_sdc_set_sdr_dma_config_deinit(uint32_t chx, uint32_t it_flag)
{
//  DMA_ITConfig(chx,DMA_Transfer_End,DISABLE);
    DEV_DMAC->DMA_PD = (DMA_Slot_Transfer_End | DMA_Half_Transfer_End | DMA_Transfer_End) << chx;
    DEV_GLOBAL->DVDD_GLOBAL7 &= ~((DMA_Half_Transfer_End | DMA_Transfer_End) << chx);
    DEV_DMAC->DMA_IE = DEV_GLOBAL->DVDD_GLOBAL7;
    DMA_Cmd(chx, DISABLE);
    DMA_ClearITPendingBit(chx, DMA_Transfer_End);
}


void hal_dev_sdc_set_dst_dma_config_deinit(uint32_t chx, uint32_t it_flag)
{
//  DMA_ITConfig(chx,it_flag,DISABLE);
    DEV_DMAC->DMA_PD = (DMA_Slot_Transfer_End | DMA_Half_Transfer_End | DMA_Transfer_End) << chx;
    DEV_GLOBAL->DVDD_GLOBAL7 &= ~((DMA_Half_Transfer_End | DMA_Transfer_End) << chx);
    DEV_DMAC->DMA_IE = DEV_GLOBAL->DVDD_GLOBAL7;
    DMA_Cmd(chx, DISABLE);
    DMA_ClearITPendingBit(chx, it_flag);
    DEV_SDC->CTRL &= ~(DEV_SDC_CTRL_DMA_ENABLE | DEV_SDC_CTRL_INT_ENABLE);
    DEV_SDC->RINTSTS = DEV_SDC_RINTSTS_INT_STATUS_MASK;
    DEV_SDC->CTRL |= DEV_SDC_CTRL_FIFO_RESET;
}
