MindSDK_MM32F5270/device/drivers/hal_qspi.c
Yilin Sun 3977144e90
Initial MM32F527x commit.
Signed-off-by: Yilin Sun <imi415@imi.moe>
2023-03-27 21:54:40 +08:00

203 lines
6.7 KiB
C

/*
* Copyright 2022 MindMotion Microelectronics Co., Ltd.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "hal_qspi.h"
void QSPI_Init(QSPI_Type * QSPIx, QSPI_Init_Type * init)
{
if (NULL == init /* if the init pointer is null, quit init. */
|| init->SckDiv < 2u || init->SckDiv > 9u || init->SckDiv % 2u != 0u /* The available value must be even & the range would be 2 ~ 128. */
|| init->CsHighLevelCycles < 2u || init->CsHighLevelCycles > 9u /* available range would be 2 ~ 9. */
|| init->RxSampleDelay > 3u)
{
return;
}
QSPIx->CR = (QSPIx->CR & ~(QSPI_CR_SCKDIV_MASK | QSPI_CR_CSRHT_MASK | QSPI_CR_SCKMODE_MASK | QSPI_CR_OPMODE_MASK) )
| QSPI_CR_SCKDIV(init->SckDiv / 2u - 1u) /* set the baudrate. */
| QSPI_CR_CSRHT(init->CsHighLevelCycles - 2u) /* set the CS high level cycle. */
| QSPI_CR_SCKMODE(init->SpiMode) /* set the SPI mode. */
| QSPI_CR_OPMODE(QSPI_OpMode_Idle); /* set the operation mode, idle by default. */
QSPIx->DMCR = (QSPIx->DMCR & ~QSPI_DMCR_RXDLY_MASK) | QSPI_DMCR_RXDLY(init->RxSampleDelay);
QSPIx->IMCR = (QSPIx->IMCR & ~QSPI_IMCR_RXDLY_MASK) | QSPI_IMCR_RXDLY(init->RxSampleDelay);
}
void QSPI_EnableDirectRead(QSPI_Type * QSPIx, QSPI_DirectXferConf_Type * conf)
{
if (NULL == conf) /* disabled. */
{
QSPIx->CR = (QSPIx->CR & ~QSPI_CR_OPMODE_MASK) | QSPI_CR_OPMODE(QSPI_OpMode_Idle);
return;
}
QSPIx->DMCR = (QSPIx->DMCR & ~(QSPI_DMCR_NUMDC_MASK | QSPI_DMCR_DMODE_MASK
| QSPI_DMCR_ABMODE_MASK | QSPI_DMCR_ABSIZE_MASK | QSPI_DMCR_ADSIZE_MASK
| QSPI_DMCR_ADMODE_MASK | QSPI_DMCR_IMODE_MASK | QSPI_DMCR_INST_MASK) )
| QSPI_DMCR_NUMDC(conf->DummyCycles)
| QSPI_DMCR_DMODE(conf->DataBusWidth)
| QSPI_DMCR_ABSIZE(conf->AltWordWidth)
| QSPI_DMCR_ABMODE(conf->AltBusWidth)
| QSPI_DMCR_ADSIZE(conf->AddrWordWidth)
| QSPI_DMCR_ADMODE(conf->AddrBusWidth)
| QSPI_DMCR_IMODE(conf->CmdBusWidth)
| QSPI_DMCR_INST(conf->CmdValue);
QSPIx->DABR = QSPI_DABR_DALT(conf->AltValue);
QSPIx->CR = ( QSPIx->CR & ~( QSPI_CR_OPMODE_MASK) ) | QSPI_CR_OPMODE(QSPI_OpMode_Direct);
}
uint8_t QSPI_GetDirectData8b(QSPI_Type * QSPIx, uint32_t offset)
{
(void)QSPIx;
return (*( (uint8_t *)(QSPI_M_BASE + offset) ) );
}
uint16_t QSPI_GetDirectData16b(QSPI_Type * QSPIx, uint32_t offset)
{
(void)QSPIx;
return (*( (uint16_t *)(QSPI_M_BASE + offset) ) );
}
uint32_t QSPI_GetDirectData32b(QSPI_Type * QSPIx, uint32_t offset)
{
(void)QSPIx;
return (*( (uint32_t *)(QSPI_M_BASE + offset) ) );
}
void QSPI_SetIndirectReadConf(QSPI_Type * QSPIx, QSPI_IndirectXferConf_Type * conf)
{
if(NULL == conf)
{
return;
}
QSPIx->IMCR = ( QSPIx->IMCR & ~(QSPI_IMCR_IDMODE_MASK | QSPI_IMCR_NUMDC_MASK | QSPI_IMCR_DSIZE_MASK
| QSPI_IMCR_DMODE_MASK | QSPI_IMCR_ABSIZE_MASK | QSPI_IMCR_ABMODE_MASK
| QSPI_IMCR_ADSIZE_MASK | QSPI_IMCR_ADMODE_MASK | QSPI_IMCR_IMODE_MASK
| QSPI_IMCR_INST_MASK) )
| QSPI_IMCR_IDMODE(0u) /* read. */
| QSPI_IMCR_NUMDC(conf->DummyCycles)
| QSPI_IMCR_DSIZE(conf->DataWordWidth)
| QSPI_IMCR_DMODE(conf->DataBusWidth)
| QSPI_IMCR_ABSIZE(conf->AltWordWidth)
| QSPI_IMCR_ABMODE(conf->AltBusWidth)
| QSPI_IMCR_ADSIZE(conf->AddrWordWidth)
| QSPI_IMCR_ADMODE(conf->AddrBusWidth)
| QSPI_IMCR_IMODE(conf->CmdBusWidth)
| QSPI_IMCR_INST(conf->CmdValue);
QSPIx->IABR = QSPI_IABR_IALT(conf->AltValue);
QSPIx->IADR = QSPI_IADR_IADDR(conf->AddrValue);
QSPIx->IWCR = QSPI_IWCR_IWCNT(0u); /* wait 7 AHB_CLK to quit inrect mode. */
QSPIx->IDLR = QSPI_IDLR_IDLEN(conf->DataLen - 1u);
QSPIx->CR = (QSPIx->CR & ~QSPI_CR_OPMODE_MASK) | QSPI_CR_OPMODE(QSPI_OpMode_Indirect);
}
uint32_t QSPI_GetIndirectData(QSPI_Type * QSPIx)
{
return QSPIx->IDFR;
}
void QSPI_SetIndirectWriteConf(QSPI_Type * QSPIx, QSPI_IndirectXferConf_Type * conf)
{
if(NULL == conf)
{
return;
}
QSPIx->IMCR = ( QSPIx->IMCR & ~(QSPI_IMCR_IDMODE_MASK | QSPI_IMCR_NUMDC_MASK | QSPI_IMCR_DSIZE_MASK
| QSPI_IMCR_DMODE_MASK | QSPI_IMCR_ABSIZE_MASK | QSPI_IMCR_ABMODE_MASK
| QSPI_IMCR_ADSIZE_MASK | QSPI_IMCR_ADMODE_MASK | QSPI_IMCR_IMODE_MASK
| QSPI_IMCR_INST_MASK) )
| QSPI_IMCR_IDMODE(1u) /* write. */
| QSPI_IMCR_NUMDC(conf->DummyCycles)
| QSPI_IMCR_DSIZE(conf->DataWordWidth)
| QSPI_IMCR_DMODE(conf->DataBusWidth)
| QSPI_IMCR_ABSIZE(conf->AltWordWidth)
| QSPI_IMCR_ABMODE(conf->AltBusWidth)
| QSPI_IMCR_ADSIZE(conf->AddrWordWidth)
| QSPI_IMCR_ADMODE(conf->AddrBusWidth)
| QSPI_IMCR_IMODE(conf->CmdBusWidth)
| QSPI_IMCR_INST(conf->CmdValue);
QSPIx->IABR = QSPI_IABR_IALT(conf->AltValue);
QSPIx->IADR = QSPI_IADR_IADDR(conf->AddrValue);
QSPIx->IWCR = QSPI_IWCR_IWCNT(0u); /* wait 7 AHB_CLK to quit inrect mode. */
QSPIx->IDLR = QSPI_IDLR_IDLEN(conf->DataLen - 1u);
QSPIx->CR = (QSPIx->CR & ~QSPI_CR_OPMODE_MASK) | QSPI_CR_OPMODE(QSPI_OpMode_Indirect);
}
void QSPI_PutIndirectData(QSPI_Type * QSPIx, uint32_t value)
{
QSPIx->IDFR = value;
}
void QSPI_EnableXIP(QSPI_Type * QSPIx, bool enable)
{
if (true == enable)
{
QSPIx->CR = QSPIx->CR | QSPI_CR_XIPMODE_MASK;
}
else
{
QSPIx->CR = QSPIx->CR & ~QSPI_CR_XIPMODE_MASK;
}
}
void QSPI_SetIndirectAutoXIP(QSPI_Type * QSPIx, bool enable)
{
if (true == enable)
{
QSPIx->IMCR |= QSPI_IMCR_XIPIM_MASK;
}
else
{
QSPIx->IMCR &= ~QSPI_IMCR_XIPIM_MASK;
}
}
uint32_t QSPI_GetStatus(QSPI_Type * QSPIx)
{
return QSPIx->SR;
}
void QSPI_ClearStatus(QSPI_Type * QSPIx, uint32_t status)
{
QSPIx->SR &= status; /* write 1 to clear status. */
}
uint32_t QSPI_GetOpMode(QSPI_Type * QSPIx)
{
return (QSPIx->SR & QSPI_SR_OPCRCF_MASK) >> QSPI_SR_OPCRCF_SHIFT;
}
void QSPI_EnableInterrupts(QSPI_Type * QSPIx, uint32_t interrupts, bool enable)
{
if(true == enable)
{
QSPIx->IDER |= interrupts;
}
else
{
QSPIx->IDER &= ~interrupts;
}
}
void QSPI_EnableDMARequest(QSPI_Type * QSPIx, uint32_t request, bool enable)
{
if(true == enable)
{
QSPIx->IDER |= request;
}
else
{
QSPIx->IDER &= ~request;
}
}
/* EOF. */