424 lines
13 KiB
C
424 lines
13 KiB
C
|
/**
|
||
|
**************************************************************************
|
||
|
* @file at32f435_437_qspi.c
|
||
|
* @version v2.0.2
|
||
|
* @date 2021-11-26
|
||
|
* @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)
|
||
|
{
|
||
|
if(flag == QSPI_CMDSTS_FLAG)
|
||
|
{
|
||
|
qspi_x->cmdsts_bit.cmdsts = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @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;
|
||
|
}
|
||
|
|
||
|
/* 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);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @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
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|