AT32F435_437_Firmware_Library/libraries/drivers/src/at32f435_437_qspi.c

430 lines
14 KiB
C

/**
**************************************************************************
* @file at32f435_437_qspi.c
* @version v2.0.9
* @date 2022-06-28
* @brief contain all the functions for qspi 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 QSPI
* @brief QSPI driver modules
* @{
*/
#ifdef QSPI_MODULE_ENABLED
/** @defgroup QSPI_private_functions
* @{
*/
/**
* @brief enable/disable encryption for qspi.
* @note the function must be configured only when qspi in command-port mode!!!
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param new_state (TRUE or FALSE)
* @retval none
*/
void qspi_encryption_enable(qspi_type* qspi_x, confirm_state new_state)
{
qspi_x->ctrl_bit.keyen = new_state;
}
/**
* @brief set qspi sck mode.
* @note the function must be configured only when qspi in command-port mode!!!
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param new_mode: new state to be set
* this parameter can be one of the following values:
* - QSPI_SCK_MODE_0
* - QSPI_SCK_MODE_3
* @retval none
*/
void qspi_sck_mode_set(qspi_type* qspi_x, qspi_clk_mode_type new_mode)
{
qspi_x->ctrl_bit.sckmode = new_mode;
}
/**
* @brief set qspi clock division
* @note the function must be configured only when qspi in command-port mode!!!
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param new_clkdiv: new division value
* this parameter can be one of the following values:
* - QSPI_CLK_DIV_2
* - QSPI_CLK_DIV_4
* - QSPI_CLK_DIV_6
* - QSPI_CLK_DIV_8
* - QSPI_CLK_DIV_3
* - QSPI_CLK_DIV_5
* - QSPI_CLK_DIV_10
* - QSPI_CLK_DIV_12
* @retval none
*/
void qspi_clk_division_set(qspi_type* qspi_x, qspi_clk_div_type new_clkdiv)
{
qspi_x->ctrl_bit.clkdiv = new_clkdiv;
}
/**
* @brief enable/disable cache in xip mode
* @note the function must be configured only when qspi in command-port mode!!!
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param new_state (TRUE or FALSE)
* @retval none
*/
void qspi_xip_cache_bypass_set(qspi_type* qspi_x, confirm_state new_state)
{
qspi_x->xip_cmd_w3_bit.bypassc = new_state;
}
/**
* @brief enable/disable interrupt when command is completed
* @note the function must be configured only when qspi in command-port mode!!!
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param new_state (TRUE or FALSE)
* @retval none
*/
void qspi_interrupt_enable(qspi_type* qspi_x, confirm_state new_state)
{
qspi_x->ctrl2_bit.cmdie = new_state;
}
/**
* @brief get status flags.
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param flag: specifies the flag to check.
* this parameter can be one of the following values:
* - QSPI_RXFIFORDY_FLAG
* - QSPI_TXFIFORDY_FLAG
* - QSPI_CMDSTS_FLAG
* @retval the new state of usart_flag (SET or RESET).
*/
flag_status qspi_flag_get(qspi_type* qspi_x, uint32_t flag)
{
flag_status bit_status = RESET;
switch(flag)
{
case QSPI_RXFIFORDY_FLAG:
bit_status = (flag_status)qspi_x->fifosts_bit.rxfifordy;
break;
case QSPI_TXFIFORDY_FLAG:
bit_status = (flag_status)qspi_x->fifosts_bit.txfifordy;
break;
case QSPI_CMDSTS_FLAG:
bit_status = (flag_status)qspi_x->cmdsts_bit.cmdsts;
break;
default:
break;
}
return bit_status;
}
/**
* @brief clear flags
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param flag: flags to be clear
* this parameter can be one of the following values:
* - QSPI_CMDSTS_FLAG
* @retval none
*/
void qspi_flag_clear(qspi_type* qspi_x, uint32_t flag)
{
qspi_x->cmdsts = QSPI_CMDSTS_FLAG;
}
/**
* @brief set dma threshold for dma rx
* @note the function must be configured only when qspi in command-port mode!!!
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param new_threshold: value to set
* this parameter can be one of the following values:
* - QSPI_DMA_FIFO_THOD_WORD08
* - QSPI_DMA_FIFO_THOD_WORD16
* - QSPI_DMA_FIFO_THOD_WORD32
* @retval none
*/
void qspi_dma_rx_threshold_set(qspi_type* qspi_x, qspi_dma_fifo_thod_type new_threshold)
{
qspi_x->ctrl2_bit.rxfifo_thod = new_threshold;
}
/**
* @brief set dma threshold for dma tx
* @note the function must be configured only when qspi in command-port mode!!!
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param new_threshold: value to set
* this parameter can be one of the following values:
* - QSPI_DMA_FIFO_THOD_WORD08
* - QSPI_DMA_FIFO_THOD_WORD16
* - QSPI_DMA_FIFO_THOD_WORD32
* @retval none
*/
void qspi_dma_tx_threshold_set(qspi_type* qspi_x, qspi_dma_fifo_thod_type new_threshold)
{
qspi_x->ctrl2_bit.txfifo_thod = new_threshold;
}
/**
* @brief enable/disable dma transfer
* @note the function must be configured only when qspi in command-port mode!!!
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param new_state (TRUE or FALSE)
* @retval none
*/
void qspi_dma_enable(qspi_type* qspi_x, confirm_state new_state)
{
qspi_x->ctrl2_bit.dmaen = new_state;
}
/**
* @brief set wip position in status register of flash
* @note the function must be configured only when qspi in command-port mode!!!
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param busy_pos: value to set
* this parameter can be one of the following values:
* - QSPI_BUSY_OFFSET_0
* - QSPI_BUSY_OFFSET_1
* - QSPI_BUSY_OFFSET_2
* - QSPI_BUSY_OFFSET_3
* - QSPI_BUSY_OFFSET_4
* - QSPI_BUSY_OFFSET_5
* - QSPI_BUSY_OFFSET_6
* - QSPI_BUSY_OFFSET_7
* @retval none
*/
void qspi_busy_config(qspi_type* qspi_x, qspi_busy_pos_type busy_pos)
{
qspi_x->ctrl_bit.busy = busy_pos;
}
/**
* @brief enable xip mode or command-port mode.
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param new_state (TRUE or FALSE)
* @retval none
*/
void qspi_xip_enable(qspi_type* qspi_x, confirm_state new_state)
{
/* skip if state is no change */
if(new_state == (confirm_state)(qspi_x->ctrl_bit.xipsel))
{
return;
}
/* wait until tx fifo emoty*/
while(qspi_x->fifosts_bit.txfifordy == 0);
/* flush and reset qspi state */
qspi_x->ctrl_bit.xiprcmdf = 1;
/* wait until action is finished */
while(qspi_x->ctrl_bit.abort);
/* set xip mode to new state */
qspi_x->ctrl_bit.xipsel = new_state;
/* wait until abort is not set */
while(qspi_x->ctrl_bit.abort);
/* wait until cache status valid*/
if(new_state == TRUE)
{
while( qspi_x->xip_cmd_w3_bit.csts );
}
}
/**
* @brief set command-port and qspi_x will start to work
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param qspi_cmd_struct: pointer to qspi cmd structure
* @retval none
*/
void qspi_cmd_operation_kick(qspi_type* qspi_x, qspi_cmd_type* qspi_cmd_struct)
{
uint32_t w1_val = 0, w3_val = 0;
/* config analyse cmd_w0 register */
qspi_x->cmd_w0 = (uint32_t)qspi_cmd_struct->address_code;
/* config analyse cmd_w1 register */
w1_val = (uint32_t)qspi_cmd_struct->address_length;
w1_val |= (uint32_t)(qspi_cmd_struct->second_dummy_cycle_num << 16);
w1_val |= (uint32_t)(qspi_cmd_struct->instruction_length << 24);
w1_val |= (uint32_t)(qspi_cmd_struct->pe_mode_enable << 28);
qspi_x->cmd_w1 = w1_val;
/* config analyse cmd_w2 register */
qspi_x->cmd_w2 = (uint32_t)qspi_cmd_struct->data_counter;
/* config analyse cmd_w3 register */
w3_val = (uint32_t)(qspi_cmd_struct->write_data_enable << 1);
w3_val |= (uint32_t)(qspi_cmd_struct->read_status_enable << 2);
w3_val |= (uint32_t)(qspi_cmd_struct->read_status_config << 3);
w3_val |= (uint32_t)(qspi_cmd_struct->operation_mode << 5);
w3_val |= (uint32_t)(qspi_cmd_struct->pe_mode_operate_code << 16);
w3_val |= (uint32_t)(qspi_cmd_struct->instruction_code << 24);
qspi_x->cmd_w3 = w3_val;
}
/**
* @brief initial xip mode for qspi_x
* @param qspi_x: select the qspi peripheral.
* this parameter can be one of the following values:
* QSPI1,QSPI2.
* @param xip_init_struct: pointer to xip init structure.
* @retval none.
*/
void qspi_xip_init(qspi_type* qspi_x, qspi_xip_type* xip_init_struct)
{
uint32_t xc0_val = 0, xc1_val = 0, xc2_val = 0;
/* config analyse xip_cmd_w0 register */
xc0_val = (uint32_t)xip_init_struct->read_second_dummy_cycle_num;
xc0_val |= (uint32_t)(xip_init_struct->read_operation_mode << 8);
xc0_val |= (uint32_t)(xip_init_struct->read_address_length << 11);
xc0_val |= (uint32_t)(xip_init_struct->read_instruction_code << 12);
qspi_x->xip_cmd_w0 = xc0_val;
/* config analyse xip_cmd_w1 register */
xc1_val = (uint32_t)xip_init_struct->write_second_dummy_cycle_num;
xc1_val |= (uint32_t)(xip_init_struct->write_operation_mode << 8);
xc1_val |= (uint32_t)(xip_init_struct->write_address_length << 11);
xc1_val |= (uint32_t)(xip_init_struct->write_instruction_code << 12);
qspi_x->xip_cmd_w1 = xc1_val;
/* config analyse xip_cmd_w2 register */
xc2_val = (uint32_t)xip_init_struct->read_data_counter;
xc2_val |= (uint32_t)(xip_init_struct->read_time_counter << 8);
xc2_val |= (uint32_t)(xip_init_struct->read_select_mode << 15);
xc2_val |= (uint32_t)(xip_init_struct->write_data_counter << 16);
xc2_val |= (uint32_t)(xip_init_struct->write_time_counter << 24);
xc2_val |= (uint32_t)(xip_init_struct->write_select_mode << 31);
qspi_x->xip_cmd_w2 = xc2_val;
}
/**
* @brief read one byte from qspi device in command mode
* @param qspi_x: select the qspi peripheral.
* @retval 8-bit data.
*/
uint8_t qspi_byte_read(qspi_type* qspi_x)
{
return qspi_x->dt_u8;
}
/**
* @brief read one half-word from qspi device in command mode
* @param qspi_x: select the qspi peripheral.
* @retval 16-bit data.
*/
uint16_t qspi_half_word_read(qspi_type* qspi_x)
{
return qspi_x->dt_u16;
}
/**
* @brief read one word from qspi device in command mode
* @param qspi_x: select the qspi peripheral.
* @retval 32-bit data.
*/
uint32_t qspi_word_read(qspi_type* qspi_x)
{
return qspi_x->dt;
}
/**
* @brief write one byte to qspi device in command mode
* @param qspi_x: select the qspi peripheral.
* @param value: 8-bit data.
* @retval none.
*/
void qspi_byte_write(qspi_type* qspi_x, uint8_t value)
{
qspi_x->dt_u8 = value;
}
/**
* @brief write one half-word to qspi device in command mode
* @param qspi_x: select the qspi peripheral.
* @param value: 16-bit data.
* @retval none.
*/
void qspi_half_word_write(qspi_type* qspi_x, uint16_t value)
{
qspi_x->dt_u16 = value;
}
/**
* @brief write one word to qspi device in command mode
* @param qspi_x: select the qspi peripheral.
* @param value: 32-bit data.
* @retval none.
*/
void qspi_word_write(qspi_type* qspi_x, uint32_t value)
{
qspi_x->dt = value;
}
/**
* @}
*/
#endif
/**
* @}
*/
/**
* @}
*/