/** ************************************************************************** * @file at32f435_437_sdio.c * @version v2.0.9 * @date 2022-06-28 * @brief contains all the functions for the sdio firmware library ************************************************************************** * Copyright notice & Disclaimer * * The software Board Support Package (BSP) that is made available to * download from Artery official website is the copyrighted work of Artery. * Artery authorizes customers to use, copy, and distribute the BSP * software and its related documentation for the purpose of design and * development in conjunction with Artery microcontrollers. Use of the * software is governed by this copyright notice and the following disclaimer. * * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. * ************************************************************************** */ #include "at32f435_437_conf.h" /** @addtogroup AT32F435_437_periph_driver * @{ */ /** @defgroup SDIO * @brief SDIO driver modules * @{ */ #ifdef SDIO_MODULE_ENABLED /** @defgroup SDIO_private_functions * @{ */ /** * @brief reset the sdio register * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @retval none */ void sdio_reset(sdio_type *sdio_x) { sdio_x->pwrctrl = 0x0; sdio_x->clkctrl = 0x0; sdio_x->argu = 0x0; sdio_x->cmdctrl = 0x0; sdio_x->dttmr = 0x0; sdio_x->dtlen = 0x0; sdio_x->dtctrl = 0x0; sdio_x->inten = 0x0; sdio_x->intclr = 0x004007FF; } /** * @brief set the power status of the controller * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param power_state * this parameter can be one of the following values: * - SDIO_POWER_OFF * - SDIO_POWER_ON * @retval none */ void sdio_power_set(sdio_type *sdio_x, sdio_power_state_type power_state) { sdio_x->pwrctrl_bit.ps = power_state; } /** * @brief get power status. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @retval sdio_power_state_type (SDIO_POWER_ON or SDIO_POWER_OFF) */ sdio_power_state_type sdio_power_status_get(sdio_type *sdio_x) { return (sdio_power_state_type)(sdio_x->pwrctrl_bit.ps); } /** * @brief config sdio clock * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param clk_div: sdio clock divide factor(frequency = sdio_clk / [clk_psc + 2]). * @param clk_edg * this parameter can be one of the following values: * - SDIO_CLOCK_EDGE_RISING * - SDIO_CLOCK_EDGE_FALLING * @retval none */ void sdio_clock_config(sdio_type *sdio_x, uint16_t clk_div, sdio_edge_phase_type clk_edg) { /* config clock edge */ sdio_x->clkctrl_bit.clkegs = clk_edg; /* config clock divide [7:0] */ sdio_x->clkctrl_bit.clkdiv_l = (clk_div & 0xFF); /* config clock divide [9:8] */ sdio_x->clkctrl_bit.clkdiv_h = ((clk_div & 0x300) >> 8); } /** * @brief config sdio bus width * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param width * this parameter can be one of the following values: * - SDIO_BUS_WIDTH_D1 * - SDIO_BUS_WIDTH_D4 * - SDIO_BUS_WIDTH_D8 * @retval none */ void sdio_bus_width_config(sdio_type *sdio_x, sdio_bus_width_type width) { sdio_x->clkctrl_bit.busws = width; } /** * @brief enable or disable clock divider bypss * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval none */ void sdio_clock_bypass(sdio_type *sdio_x, confirm_state new_state) { sdio_x->clkctrl_bit.bypsen = new_state; } /** * @brief enable or disable power saving mode, config sdio_ck clock output * when the bus is idle. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval none */ void sdio_power_saving_mode_enable(sdio_type *sdio_x, confirm_state new_state) { sdio_x->clkctrl_bit.pwrsven = new_state; } /** * @brief enable or disable hardware flow control. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval none */ void sdio_flow_control_enable(sdio_type *sdio_x, confirm_state new_state) { sdio_x->clkctrl_bit.hfcen = new_state; } /** * @brief enable or disable sdio_ck output. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval none */ void sdio_clock_enable(sdio_type *sdio_x, confirm_state new_state) { sdio_x->clkctrl_bit.clkoen = new_state; } /** * @brief enable or disable dma. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval none */ void sdio_dma_enable(sdio_type *sdio_x, confirm_state new_state) { sdio_x->dtctrl_bit.dmaen = new_state; } /** * @brief config corresponding interrupt. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param int_opt * this parameter can be one of the following values: * - SDIO_CMDFAIL_INT * - SDIO_DTFAIL_INT * - SDIO_CMDTIMEOUT_INT * - SDIO_DTTIMEOUT_INT * - SDIO_TXERRU_INT * - SDIO_RXERRO_INT * - SDIO_CMDRSPCMPL_INT * - SDIO_CMDCMPL_INT * - SDIO_DTCMP_INT * - SDIO_SBITERR_INT * - SDIO_DTBLKCMPL_INT * - SDIO_DOCMD_INT * - SDIO_DOTX_INT * - SDIO_DORX_INT * - SDIO_TXBUFH_INT * - SDIO_RXBUFH_INT * - SDIO_TXBUFF_INT * - SDIO_RXBUFF_INT * - SDIO_TXBUFE_INT * - SDIO_RXBUFE_INT * - SDIO_TXBUF_INT * - SDIO_RXBUF_INT * - SDIO_SDIOIF_INT * @param new_state (TRUE or FALSE) * @retval none */ void sdio_interrupt_enable(sdio_type *sdio_x, uint32_t int_opt, confirm_state new_state) { /* enable interrupt */ if(TRUE == new_state) { sdio_x->inten |= int_opt; } /* disable interrupt */ else { sdio_x->inten &= ~(int_opt); } } /** * @brief get sdio flag. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param flag * this parameter can be one of the following values: * - SDIO_CMDFAIL_FLAG * - SDIO_DTFAIL_FLAG * - SDIO_CMDTIMEOUT_FLAG * - SDIO_DTTIMEOUT_FLAG * - SDIO_TXERRU_FLAG * - SDIO_RXERRO_FLAG * - SDIO_CMDRSPCMPL_FLAG * - SDIO_CMDCMPL_FLAG * - SDIO_DTCMPL_FLAG * - SDIO_SBITERR_FLAG * - SDIO_DTBLKCMPL_FLAG * - SDIO_DOCMD_FLAG * - SDIO_DOTX_FLAG * - SDIO_DORX_FLAG * - SDIO_TXBUFH_FLAG * - SDIO_RXBUFH_FLAG * - SDIO_TXBUFF_FLAG * - SDIO_RXBUFF_FLAG * - SDIO_TXBUFE_FLAG * - SDIO_RXBUFE_FLAG * - SDIO_TXBUF_FLAG * - SDIO_RXBUF_FLAG * - SDIO_SDIOIF_FLAG * @retval flag_status (SET or RESET) */ flag_status sdio_flag_get(sdio_type *sdio_x, uint32_t flag) { flag_status status = RESET; if((sdio_x->sts & flag) == flag) { status = SET; } else { status = RESET; } return status; } /** * @brief clear sdio flag. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param int_opt * this parameter can be any combination of the following values: * - SDIO_CMDFAIL_FLAG * - SDIO_DTFAIL_FLAG * - SDIO_CMDTIMEOUT_FLAG * - SDIO_DTTIMEOUT_FLAG * - SDIO_TXERRU_FLAG * - SDIO_RXERRO_FLAG * - SDIO_CMDRSPCMPL_FLAG * - SDIO_CMDCMPL_FLAG * - SDIO_DTCMPL_FLAG * - SDIO_SBITERR_FLAG * - SDIO_DTBLKCMPL_FLAG * - SDIO_SDIOIF_FLAG * @retval none */ void sdio_flag_clear(sdio_type *sdio_x, uint32_t flag) { sdio_x->intclr = flag; } /** * @brief config sdio command. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param command_struct : pointer to a sdio_command_struct_type structure * that contains the configuration information for the sdio command. * @retval none */ void sdio_command_config(sdio_type *sdio_x, sdio_command_struct_type *command_struct) { /* disable command path state machine */ sdio_x->cmdctrl_bit.ccsmen = FALSE; /* config command argument */ sdio_x->argu = command_struct->argument; /* config command register */ sdio_x->cmdctrl_bit.cmdidx = command_struct->cmd_index; sdio_x->cmdctrl_bit.rspwt = command_struct->rsp_type; sdio_x->cmdctrl_bit.intwt = (command_struct->wait_type & 0x1); /* [1:0] -> [0] */ sdio_x->cmdctrl_bit.pndwt = (command_struct->wait_type & 0x2)>>1; /* [1:0] -> [1] */ } /** * @brief enable or disable command path state machine(CPSM). * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval none */ void sdio_command_state_machine_enable(sdio_type *sdio_x, confirm_state new_state) { sdio_x->cmdctrl_bit.ccsmen = new_state; } /** * @brief get command index of last command for which response received. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval uint8_t: command index */ uint8_t sdio_command_response_get(sdio_type *sdio_x) { return sdio_x->rspcmd_bit.rspcmd; } /** * @brief get response received from the card for the last command. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param reg_index * this parameter can be one of the following values: * - SDIO_RSP1_INDEX * - SDIO_RSP2_INDEX * - SDIO_RSP3_INDEX * - SDIO_RSP4_INDEX * @retval uint32_t: response register value */ uint32_t sdio_response_get(sdio_type *sdio_x, sdio_rsp_index_type reg_index) { uint32_t response_value = 0; switch(reg_index) { case SDIO_RSP1_INDEX: response_value = sdio_x->rsp1; break; case SDIO_RSP2_INDEX: response_value = sdio_x->rsp2; break; case SDIO_RSP3_INDEX: response_value = sdio_x->rsp3; break; case SDIO_RSP4_INDEX: response_value = sdio_x->rsp4; break; default: break; } return response_value; } /** * @brief config sdio data. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param data_struct : pointer to a sdio_data_struct_type structure * that contains the configuration information for the sdio data. * @retval none */ void sdio_data_config(sdio_type *sdio_x, sdio_data_struct_type *data_struct) { /* disable data path state machine */ sdio_x->dtctrl_bit.tfren = FALSE; /* config data block, transfer mode and transfer direction */ sdio_x->dtctrl_bit.blksize = data_struct->block_size; sdio_x->dtctrl_bit.tfrdir = data_struct->transfer_direction; sdio_x->dtctrl_bit.tfrmode = data_struct->transfer_mode; /* config data length */ sdio_x->dtlen_bit.dtlen = data_struct->data_length; /* config data transfer timeout */ sdio_x->dttmr_bit.timeout = data_struct->timeout; } /** * @brief enable or disable data path state machine(DPSM). * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval none */ void sdio_data_state_machine_enable(sdio_type *sdio_x, confirm_state new_state) { sdio_x->dtctrl_bit.tfren = new_state; } /** * @brief get the number of remaining data bytes to be transferred. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @retval uint32_t: number of bytes */ uint32_t sdio_data_counter_get(sdio_type *sdio_x) { return sdio_x->dtcnt; } /** * @brief read a word data from sdio fifo. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @retval uint32_t: data received */ uint32_t sdio_data_read(sdio_type *sdio_x) { return sdio_x->buf; } /** * @brief get the number of words left to be written to or read from fifo.. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @retval uint32_t: number of words */ uint32_t sdio_buffer_counter_get(sdio_type *sdio_x) { return sdio_x->bufcnt; } /** * @brief write one word data to fifo. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param data: data to be transferred. * @retval none */ void sdio_data_write(sdio_type *sdio_x, uint32_t data) { sdio_x->buf = data; } /** * @brief set the read wait mode. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param mode * this parameter can be one of the following values: * - SDIO_READ_WAIT_CONTROLLED_BY_D2 * - SDIO_READ_WAIT_CONTROLLED_BY_CK * @retval none */ void sdio_read_wait_mode_set(sdio_type *sdio_x, sdio_read_wait_mode_type mode) { sdio_x->dtctrl_bit.rdwtmode = mode; } /** * @brief enable or disable to start sd i/o read wait operation. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval none */ void sdio_read_wait_start(sdio_type *sdio_x, confirm_state new_state) { sdio_x->dtctrl_bit.rdwtstart = new_state; } /** * @brief enable or disable to stop sd i/o read wait operation. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval none */ void sdio_read_wait_stop(sdio_type *sdio_x, confirm_state new_state) { sdio_x->dtctrl_bit.rdwtstop = new_state; } /** * @brief enable or disable the sd i/o function. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval none */ void sdio_io_function_enable(sdio_type *sdio_x, confirm_state new_state) { sdio_x->dtctrl_bit.ioen = new_state; } /** * @brief enable or disable sd i/o suspend command sending. * @param sdio_x: to select the sdio peripheral. * this parameter can be one of the following values: * SDIO1, SDIO2. * @param new_state (TRUE or FALSE) * @retval none */ void sdio_io_suspend_command_set(sdio_type *sdio_x, confirm_state new_state) { sdio_x->cmdctrl_bit.iosusp = new_state; } /** * @} */ #endif /** * @} */ /** * @} */