nu_qspi.c 29.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
/**************************************************************************//**
 * @file     qspi.c
 * @version  V3.00
 * @brief    M480 series QSPI driver source file
 *
 * SPDX-License-Identifier: Apache-2.0
 * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "NuMicro.h"

/** @addtogroup Standard_Driver Standard Driver
  @{
*/

/** @addtogroup QSPI_Driver QSPI Driver
  @{
*/


/** @addtogroup QSPI_EXPORTED_FUNCTIONS QSPI Exported Functions
  @{
*/

/**
  * @brief  This function make QSPI module be ready to transfer.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @param[in]  u32MasterSlave Decides the QSPI module is operating in master mode or in slave mode. (QSPI_SLAVE, QSPI_MASTER)
  * @param[in]  u32QSPIMode Decides the transfer timing. (QSPI_MODE_0, QSPI_MODE_1, QSPI_MODE_2, QSPI_MODE_3)
  * @param[in]  u32DataWidth Decides the data width of a QSPI transaction.
  * @param[in]  u32BusClock The expected frequency of QSPI bus clock in Hz.
  * @return Actual frequency of QSPI peripheral clock.
  * @details By default, the QSPI transfer sequence is MSB first, the slave selection signal is active low and the automatic
  *          slave selection function is disabled.
  *          In Slave mode, the u32BusClock shall be NULL and the QSPI clock divider setting will be 0.
  *          The actual clock rate may be different from the target QSPI clock rate.
  *          For example, if the QSPI source clock rate is 12 MHz and the target QSPI bus clock rate is 7 MHz, the
  *          actual QSPI clock rate will be 6MHz.
  * @note   If u32BusClock = 0, DIVIDER setting will be set to the maximum value.
  * @note   If u32BusClock >= system clock frequency, QSPI peripheral clock source will be set to APB clock and DIVIDER will be set to 0.
  * @note   If u32BusClock >= QSPI peripheral clock source, DIVIDER will be set to 0.
  * @note   In slave mode, the QSPI peripheral clock rate will be equal to APB clock rate.
  */
uint32_t QSPI_Open(QSPI_T *qspi,
                   uint32_t u32MasterSlave,
                   uint32_t u32QSPIMode,
                   uint32_t u32DataWidth,
                   uint32_t u32BusClock)
{
W
Wayne Lin 已提交
49
    uint32_t u32ClkSrc = 0U, u32Div, u32HCLKFreq, u32RetValue = 0U;
50

W
Wayne Lin 已提交
51
    if (u32DataWidth == 32U)
52 53 54 55 56 57 58
    {
        u32DataWidth = 0U;
    }

    /* Get system clock frequency */
    u32HCLKFreq = CLK_GetHCLKFreq();

W
Wayne Lin 已提交
59
    if (u32MasterSlave == QSPI_MASTER)
60 61 62 63 64 65 66
    {
        /* Default setting: slave selection signal is active low; disable automatic slave selection function. */
        qspi->SSCTL = QSPI_SS_ACTIVE_LOW;

        /* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */
        qspi->CTL = u32MasterSlave | (u32DataWidth << QSPI_CTL_DWIDTH_Pos) | (u32QSPIMode) | QSPI_CTL_QSPIEN_Msk;

W
Wayne Lin 已提交
67
        if (u32BusClock >= u32HCLKFreq)
68 69 70 71 72 73 74 75 76 77 78
        {
            /* Select PCLK as the clock source of QSPI */
            if (qspi == QSPI0)
                CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_QSPI0SEL_Msk)) | CLK_CLKSEL2_QSPI0SEL_PCLK0;
            else if (qspi == QSPI1)
                CLK->CLKSEL3 = (CLK->CLKSEL3 & (~CLK_CLKSEL3_QSPI1SEL_Msk)) | CLK_CLKSEL3_QSPI1SEL_PCLK1;
        }

        /* Check clock source of QSPI */
        if (qspi == QSPI0)
        {
W
Wayne Lin 已提交
79
            if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT)
80 81 82
            {
                u32ClkSrc = __HXT; /* Clock source is HXT */
            }
W
Wayne Lin 已提交
83
            else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL)
84 85 86
            {
                u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
            }
W
Wayne Lin 已提交
87
            else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0)
88 89 90 91 92 93 94 95 96 97 98
            {
                /* Clock source is PCLK0 */
                u32ClkSrc = CLK_GetPCLK0Freq();
            }
            else
            {
                u32ClkSrc = __HIRC; /* Clock source is HIRC */
            }
        }
        else if (qspi == QSPI1)
        {
W
Wayne Lin 已提交
99
            if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_HXT)
100 101 102
            {
                u32ClkSrc = __HXT; /* Clock source is HXT */
            }
W
Wayne Lin 已提交
103
            else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PLL)
104 105 106
            {
                u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
            }
W
Wayne Lin 已提交
107
            else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PCLK1)
108 109 110 111 112 113 114 115 116 117
            {
                /* Clock source is PCLK1 */
                u32ClkSrc = CLK_GetPCLK1Freq();
            }
            else
            {
                u32ClkSrc = __HIRC; /* Clock source is HIRC */
            }
        }

W
Wayne Lin 已提交
118
        if (u32BusClock >= u32HCLKFreq)
119 120 121 122 123 124
        {
            /* Set DIVIDER = 0 */
            qspi->CLKDIV = 0U;
            /* Return master peripheral clock rate */
            u32RetValue = u32ClkSrc;
        }
W
Wayne Lin 已提交
125
        else if (u32BusClock >= u32ClkSrc)
126 127 128 129 130 131
        {
            /* Set DIVIDER = 0 */
            qspi->CLKDIV = 0U;
            /* Return master peripheral clock rate */
            u32RetValue = u32ClkSrc;
        }
W
Wayne Lin 已提交
132
        else if (u32BusClock == 0U)
133 134 135 136 137 138 139 140 141
        {
            /* Set DIVIDER to the maximum value 0xFF. f_qspi = f_qspi_clk_src / (DIVIDER + 1) */
            qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk;
            /* Return master peripheral clock rate */
            u32RetValue = (u32ClkSrc / (0xFFU + 1U));
        }
        else
        {
            u32Div = (((u32ClkSrc * 10U) / u32BusClock + 5U) / 10U) - 1U; /* Round to the nearest integer */
W
Wayne Lin 已提交
142
            if (u32Div > 0xFFU)
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
            {
                u32Div = 0xFFU;
                qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk;
                /* Return master peripheral clock rate */
                u32RetValue = (u32ClkSrc / (0xFFU + 1U));
            }
            else
            {
                qspi->CLKDIV = (qspi->CLKDIV & (~QSPI_CLKDIV_DIVIDER_Msk)) | (u32Div << QSPI_CLKDIV_DIVIDER_Pos);
                /* Return master peripheral clock rate */
                u32RetValue = (u32ClkSrc / (u32Div + 1U));
            }
        }
    }
    else     /* For slave mode, force the QSPI peripheral clock rate to equal APB clock rate. */
    {
        /* Default setting: slave selection signal is low level active. */
        qspi->SSCTL = QSPI_SS_ACTIVE_LOW;

        /* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */
        qspi->CTL = u32MasterSlave | (u32DataWidth << QSPI_CTL_DWIDTH_Pos) | (u32QSPIMode) | QSPI_CTL_QSPIEN_Msk;

        /* Set DIVIDER = 0 */
        qspi->CLKDIV = 0U;

        /* Select PCLK as the clock source of QSPI */
        if (qspi == QSPI0)
        {
            CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_QSPI0SEL_Msk)) | CLK_CLKSEL2_QSPI0SEL_PCLK0;
            /* Return slave peripheral clock rate */
            u32RetValue = CLK_GetPCLK0Freq();
        }
        else if (qspi == QSPI1)
        {
            CLK->CLKSEL3 = (CLK->CLKSEL3 & (~CLK_CLKSEL3_QSPI1SEL_Msk)) | CLK_CLKSEL3_QSPI1SEL_PCLK1;
            /* Return slave peripheral clock rate */
            u32RetValue = CLK_GetPCLK1Freq();
        }
    }

    return u32RetValue;
}

/**
  * @brief  Disable QSPI controller.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @return None
  * @details This function will reset QSPI controller.
  */
void QSPI_Close(QSPI_T *qspi)
{
    /* Reset QSPI */
    if (qspi == QSPI0)
    {
        SYS->IPRST1 |= SYS_IPRST1_QSPI0RST_Msk;
        SYS->IPRST1 &= ~SYS_IPRST1_QSPI0RST_Msk;
    }
    else if (qspi == QSPI1)
    {
        SYS->IPRST2 |= SYS_IPRST2_QSPI1RST_Msk;
        SYS->IPRST2 &= ~SYS_IPRST2_QSPI1RST_Msk;
    }
}

/**
  * @brief  Clear RX FIFO buffer.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @return None
  * @details This function will clear QSPI RX FIFO buffer. The RXEMPTY (QSPI_STATUS[8]) will be set to 1.
  */
void QSPI_ClearRxFIFO(QSPI_T *qspi)
{
    qspi->FIFOCTL |= QSPI_FIFOCTL_RXFBCLR_Msk;
}

/**
  * @brief  Clear TX FIFO buffer.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @return None
  * @details This function will clear QSPI TX FIFO buffer. The TXEMPTY (QSPI_STATUS[16]) will be set to 1.
  * @note The TX shift register will not be cleared.
  */
void QSPI_ClearTxFIFO(QSPI_T *qspi)
{
    qspi->FIFOCTL |= QSPI_FIFOCTL_TXFBCLR_Msk;
}

/**
  * @brief  Disable the automatic slave selection function.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @return None
  * @details This function will disable the automatic slave selection function and set slave selection signal to inactive state.
  */
void QSPI_DisableAutoSS(QSPI_T *qspi)
{
    qspi->SSCTL &= ~(QSPI_SSCTL_AUTOSS_Msk | QSPI_SSCTL_SS_Msk);
}

/**
  * @brief  Enable the automatic slave selection function.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @param[in]  u32SSPinMask Specifies slave selection pins. (QSPI_SS)
  * @param[in]  u32ActiveLevel Specifies the active level of slave selection signal. (QSPI_SS_ACTIVE_HIGH, QSPI_SS_ACTIVE_LOW)
  * @return None
  * @details This function will enable the automatic slave selection function. Only available in Master mode.
  *          The slave selection pin and the active level will be set in this function.
  */
void QSPI_EnableAutoSS(QSPI_T *qspi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel)
{
    qspi->SSCTL = (qspi->SSCTL & (~(QSPI_SSCTL_AUTOSS_Msk | QSPI_SSCTL_SSACTPOL_Msk | QSPI_SSCTL_SS_Msk))) | (u32SSPinMask | u32ActiveLevel | QSPI_SSCTL_AUTOSS_Msk);
}

/**
  * @brief  Set the QSPI bus clock.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @param[in]  u32BusClock The expected frequency of QSPI bus clock in Hz.
  * @return Actual frequency of QSPI bus clock.
  * @details This function is only available in Master mode. The actual clock rate may be different from the target QSPI bus clock rate.
  *          For example, if the QSPI source clock rate is 12 MHz and the target QSPI bus clock rate is 7 MHz, the actual QSPI bus clock
  *          rate will be 6 MHz.
  * @note   If u32BusClock = 0, DIVIDER setting will be set to the maximum value.
  * @note   If u32BusClock >= system clock frequency, QSPI peripheral clock source will be set to APB clock and DIVIDER will be set to 0.
  * @note   If u32BusClock >= QSPI peripheral clock source, DIVIDER will be set to 0.
  */
uint32_t QSPI_SetBusClock(QSPI_T *qspi, uint32_t u32BusClock)
{
    uint32_t u32ClkSrc, u32HCLKFreq;
    uint32_t u32Div, u32RetValue;

    /* Get system clock frequency */
    u32HCLKFreq = CLK_GetHCLKFreq();

W
Wayne Lin 已提交
275
    if (u32BusClock >= u32HCLKFreq)
276 277 278 279 280 281 282 283 284 285 286
    {
        /* Select PCLK as the clock source of QSPI */
        if (qspi == QSPI0)
            CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_QSPI0SEL_Msk)) | CLK_CLKSEL2_QSPI0SEL_PCLK0;
        else if (qspi == QSPI1)
            CLK->CLKSEL3 = (CLK->CLKSEL3 & (~CLK_CLKSEL3_QSPI1SEL_Msk)) | CLK_CLKSEL3_QSPI1SEL_PCLK1;
    }

    /* Check clock source of QSPI */
    if (qspi == QSPI0)
    {
W
Wayne Lin 已提交
287
        if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT)
288 289 290
        {
            u32ClkSrc = __HXT; /* Clock source is HXT */
        }
W
Wayne Lin 已提交
291
        else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL)
292 293 294
        {
            u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
        }
W
Wayne Lin 已提交
295
        else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0)
296 297 298 299 300 301 302 303 304 305 306
        {
            /* Clock source is PCLK0 */
            u32ClkSrc = CLK_GetPCLK0Freq();
        }
        else
        {
            u32ClkSrc = __HIRC; /* Clock source is HIRC */
        }
    }
    else if (qspi == QSPI1)
    {
W
Wayne Lin 已提交
307
        if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_HXT)
308 309 310
        {
            u32ClkSrc = __HXT; /* Clock source is HXT */
        }
W
Wayne Lin 已提交
311
        else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PLL)
312 313 314
        {
            u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
        }
W
Wayne Lin 已提交
315
        else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PCLK1)
316 317 318 319 320 321 322 323 324 325
        {
            /* Clock source is PCLK1 */
            u32ClkSrc = CLK_GetPCLK1Freq();
        }
        else
        {
            u32ClkSrc = __HIRC; /* Clock source is HIRC */
        }
    }

W
Wayne Lin 已提交
326
    if (u32BusClock >= u32HCLKFreq)
327 328 329 330 331 332
    {
        /* Set DIVIDER = 0 */
        qspi->CLKDIV = 0U;
        /* Return master peripheral clock rate */
        u32RetValue = u32ClkSrc;
    }
W
Wayne Lin 已提交
333
    else if (u32BusClock >= u32ClkSrc)
334 335 336 337 338 339
    {
        /* Set DIVIDER = 0 */
        qspi->CLKDIV = 0U;
        /* Return master peripheral clock rate */
        u32RetValue = u32ClkSrc;
    }
W
Wayne Lin 已提交
340
    else if (u32BusClock == 0U)
341 342 343 344 345 346 347 348 349
    {
        /* Set DIVIDER to the maximum value 0xFF. f_qspi = f_qspi_clk_src / (DIVIDER + 1) */
        qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk;
        /* Return master peripheral clock rate */
        u32RetValue = (u32ClkSrc / (0xFFU + 1U));
    }
    else
    {
        u32Div = (((u32ClkSrc * 10U) / u32BusClock + 5U) / 10U) - 1U; /* Round to the nearest integer */
W
Wayne Lin 已提交
350
        if (u32Div > 0x1FFU)
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
        {
            u32Div = 0x1FFU;
            qspi->CLKDIV |= QSPI_CLKDIV_DIVIDER_Msk;
            /* Return master peripheral clock rate */
            u32RetValue = (u32ClkSrc / (0xFFU + 1U));
        }
        else
        {
            qspi->CLKDIV = (qspi->CLKDIV & (~QSPI_CLKDIV_DIVIDER_Msk)) | (u32Div << QSPI_CLKDIV_DIVIDER_Pos);
            /* Return master peripheral clock rate */
            u32RetValue = (u32ClkSrc / (u32Div + 1U));
        }
    }

    return u32RetValue;
}

/**
  * @brief  Configure FIFO threshold setting.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @param[in]  u32TxThreshold Decides the TX FIFO threshold. It could be 0 ~ 7.
  * @param[in]  u32RxThreshold Decides the RX FIFO threshold. It could be 0 ~ 7.
  * @return None
  * @details Set TX FIFO threshold and RX FIFO threshold configurations.
  */
void QSPI_SetFIFO(QSPI_T *qspi, uint32_t u32TxThreshold, uint32_t u32RxThreshold)
{
    qspi->FIFOCTL = (qspi->FIFOCTL & ~(QSPI_FIFOCTL_TXTH_Msk | QSPI_FIFOCTL_RXTH_Msk)) |
                    (u32TxThreshold << QSPI_FIFOCTL_TXTH_Pos) |
                    (u32RxThreshold << QSPI_FIFOCTL_RXTH_Pos);
}

/**
  * @brief  Get the actual frequency of QSPI bus clock. Only available in Master mode.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @return Actual QSPI bus clock frequency in Hz.
  * @details This function will calculate the actual QSPI bus clock rate according to the QSPInSEL and DIVIDER settings. Only available in Master mode.
  */
uint32_t QSPI_GetBusClock(QSPI_T *qspi)
{
    uint32_t u32Div;
W
Wayne Lin 已提交
392
    uint32_t u32ClkSrc = 0;
393 394 395 396 397 398 399

    /* Get DIVIDER setting */
    u32Div = (qspi->CLKDIV & QSPI_CLKDIV_DIVIDER_Msk) >> QSPI_CLKDIV_DIVIDER_Pos;

    /* Check clock source of QSPI */
    if (qspi == QSPI0)
    {
W
Wayne Lin 已提交
400
        if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_HXT)
401 402 403
        {
            u32ClkSrc = __HXT; /* Clock source is HXT */
        }
W
Wayne Lin 已提交
404
        else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PLL)
405 406 407
        {
            u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
        }
W
Wayne Lin 已提交
408
        else if ((CLK->CLKSEL2 & CLK_CLKSEL2_QSPI0SEL_Msk) == CLK_CLKSEL2_QSPI0SEL_PCLK0)
409 410 411 412 413 414 415 416 417 418 419
        {
            /* Clock source is PCLK0 */
            u32ClkSrc = CLK_GetPCLK0Freq();
        }
        else
        {
            u32ClkSrc = __HIRC; /* Clock source is HIRC */
        }
    }
    else if (qspi == QSPI1)
    {
W
Wayne Lin 已提交
420
        if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_HXT)
421 422 423
        {
            u32ClkSrc = __HXT; /* Clock source is HXT */
        }
W
Wayne Lin 已提交
424
        else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PLL)
425 426 427
        {
            u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
        }
W
Wayne Lin 已提交
428
        else if ((CLK->CLKSEL3 & CLK_CLKSEL3_QSPI1SEL_Msk) == CLK_CLKSEL3_QSPI1SEL_PCLK1)
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
        {
            /* Clock source is PCLK1 */
            u32ClkSrc = CLK_GetPCLK1Freq();
        }
        else
        {
            u32ClkSrc = __HIRC; /* Clock source is HIRC */
        }
    }

    /* Return QSPI bus clock rate */
    return (u32ClkSrc / (u32Div + 1U));
}

/**
  * @brief  Enable interrupt function.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @param[in]  u32Mask The combination of all related interrupt enable bits.
  *                     Each bit corresponds to a interrupt enable bit.
  *                     This parameter decides which interrupts will be enabled. It is combination of:
  *                       - \ref QSPI_UNIT_INT_MASK
  *                       - \ref QSPI_SSACT_INT_MASK
  *                       - \ref QSPI_SSINACT_INT_MASK
  *                       - \ref QSPI_SLVUR_INT_MASK
  *                       - \ref QSPI_SLVBE_INT_MASK
  *                       - \ref QSPI_TXUF_INT_MASK
  *                       - \ref QSPI_FIFO_TXTH_INT_MASK
  *                       - \ref QSPI_FIFO_RXTH_INT_MASK
  *                       - \ref QSPI_FIFO_RXOV_INT_MASK
  *                       - \ref QSPI_FIFO_RXTO_INT_MASK
  *
  * @return None
  * @details Enable QSPI related interrupts specified by u32Mask parameter.
  */
void QSPI_EnableInt(QSPI_T *qspi, uint32_t u32Mask)
{
    /* Enable unit transfer interrupt flag */
W
Wayne Lin 已提交
466
    if ((u32Mask & QSPI_UNIT_INT_MASK) == QSPI_UNIT_INT_MASK)
467 468 469 470 471
    {
        qspi->CTL |= QSPI_CTL_UNITIEN_Msk;
    }

    /* Enable slave selection signal active interrupt flag */
W
Wayne Lin 已提交
472
    if ((u32Mask & QSPI_SSACT_INT_MASK) == QSPI_SSACT_INT_MASK)
473 474 475 476 477
    {
        qspi->SSCTL |= QSPI_SSCTL_SSACTIEN_Msk;
    }

    /* Enable slave selection signal inactive interrupt flag */
W
Wayne Lin 已提交
478
    if ((u32Mask & QSPI_SSINACT_INT_MASK) == QSPI_SSINACT_INT_MASK)
479 480 481 482 483
    {
        qspi->SSCTL |= QSPI_SSCTL_SSINAIEN_Msk;
    }

    /* Enable slave TX under run interrupt flag */
W
Wayne Lin 已提交
484
    if ((u32Mask & QSPI_SLVUR_INT_MASK) == QSPI_SLVUR_INT_MASK)
485 486 487 488 489
    {
        qspi->SSCTL |= QSPI_SSCTL_SLVURIEN_Msk;
    }

    /* Enable slave bit count error interrupt flag */
W
Wayne Lin 已提交
490
    if ((u32Mask & QSPI_SLVBE_INT_MASK) == QSPI_SLVBE_INT_MASK)
491 492 493 494 495
    {
        qspi->SSCTL |= QSPI_SSCTL_SLVBEIEN_Msk;
    }

    /* Enable slave TX underflow interrupt flag */
W
Wayne Lin 已提交
496
    if ((u32Mask & QSPI_TXUF_INT_MASK) == QSPI_TXUF_INT_MASK)
497 498 499 500 501
    {
        qspi->FIFOCTL |= QSPI_FIFOCTL_TXUFIEN_Msk;
    }

    /* Enable TX threshold interrupt flag */
W
Wayne Lin 已提交
502
    if ((u32Mask & QSPI_FIFO_TXTH_INT_MASK) == QSPI_FIFO_TXTH_INT_MASK)
503 504 505 506 507
    {
        qspi->FIFOCTL |= QSPI_FIFOCTL_TXTHIEN_Msk;
    }

    /* Enable RX threshold interrupt flag */
W
Wayne Lin 已提交
508
    if ((u32Mask & QSPI_FIFO_RXTH_INT_MASK) == QSPI_FIFO_RXTH_INT_MASK)
509 510 511 512 513
    {
        qspi->FIFOCTL |= QSPI_FIFOCTL_RXTHIEN_Msk;
    }

    /* Enable RX overrun interrupt flag */
W
Wayne Lin 已提交
514
    if ((u32Mask & QSPI_FIFO_RXOV_INT_MASK) == QSPI_FIFO_RXOV_INT_MASK)
515 516 517 518 519
    {
        qspi->FIFOCTL |= QSPI_FIFOCTL_RXOVIEN_Msk;
    }

    /* Enable RX time-out interrupt flag */
W
Wayne Lin 已提交
520
    if ((u32Mask & QSPI_FIFO_RXTO_INT_MASK) == QSPI_FIFO_RXTO_INT_MASK)
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
    {
        qspi->FIFOCTL |= QSPI_FIFOCTL_RXTOIEN_Msk;
    }
}

/**
  * @brief  Disable interrupt function.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @param[in]  u32Mask The combination of all related interrupt enable bits.
  *                     Each bit corresponds to a interrupt bit.
  *                     This parameter decides which interrupts will be disabled. It is combination of:
  *                       - \ref QSPI_UNIT_INT_MASK
  *                       - \ref QSPI_SSACT_INT_MASK
  *                       - \ref QSPI_SSINACT_INT_MASK
  *                       - \ref QSPI_SLVUR_INT_MASK
  *                       - \ref QSPI_SLVBE_INT_MASK
  *                       - \ref QSPI_TXUF_INT_MASK
  *                       - \ref QSPI_FIFO_TXTH_INT_MASK
  *                       - \ref QSPI_FIFO_RXTH_INT_MASK
  *                       - \ref QSPI_FIFO_RXOV_INT_MASK
  *                       - \ref QSPI_FIFO_RXTO_INT_MASK
  *
  * @return None
  * @details Disable QSPI related interrupts specified by u32Mask parameter.
  */
void QSPI_DisableInt(QSPI_T *qspi, uint32_t u32Mask)
{
    /* Disable unit transfer interrupt flag */
W
Wayne Lin 已提交
549
    if ((u32Mask & QSPI_UNIT_INT_MASK) == QSPI_UNIT_INT_MASK)
550 551 552 553 554
    {
        qspi->CTL &= ~QSPI_CTL_UNITIEN_Msk;
    }

    /* Disable slave selection signal active interrupt flag */
W
Wayne Lin 已提交
555
    if ((u32Mask & QSPI_SSACT_INT_MASK) == QSPI_SSACT_INT_MASK)
556 557 558 559 560
    {
        qspi->SSCTL &= ~QSPI_SSCTL_SSACTIEN_Msk;
    }

    /* Disable slave selection signal inactive interrupt flag */
W
Wayne Lin 已提交
561
    if ((u32Mask & QSPI_SSINACT_INT_MASK) == QSPI_SSINACT_INT_MASK)
562 563 564 565 566
    {
        qspi->SSCTL &= ~QSPI_SSCTL_SSINAIEN_Msk;
    }

    /* Disable slave TX under run interrupt flag */
W
Wayne Lin 已提交
567
    if ((u32Mask & QSPI_SLVUR_INT_MASK) == QSPI_SLVUR_INT_MASK)
568 569 570 571 572
    {
        qspi->SSCTL &= ~QSPI_SSCTL_SLVURIEN_Msk;
    }

    /* Disable slave bit count error interrupt flag */
W
Wayne Lin 已提交
573
    if ((u32Mask & QSPI_SLVBE_INT_MASK) == QSPI_SLVBE_INT_MASK)
574 575 576 577 578
    {
        qspi->SSCTL &= ~QSPI_SSCTL_SLVBEIEN_Msk;
    }

    /* Disable slave TX underflow interrupt flag */
W
Wayne Lin 已提交
579
    if ((u32Mask & QSPI_TXUF_INT_MASK) == QSPI_TXUF_INT_MASK)
580 581 582 583 584
    {
        qspi->FIFOCTL &= ~QSPI_FIFOCTL_TXUFIEN_Msk;
    }

    /* Disable TX threshold interrupt flag */
W
Wayne Lin 已提交
585
    if ((u32Mask & QSPI_FIFO_TXTH_INT_MASK) == QSPI_FIFO_TXTH_INT_MASK)
586 587 588 589 590
    {
        qspi->FIFOCTL &= ~QSPI_FIFOCTL_TXTHIEN_Msk;
    }

    /* Disable RX threshold interrupt flag */
W
Wayne Lin 已提交
591
    if ((u32Mask & QSPI_FIFO_RXTH_INT_MASK) == QSPI_FIFO_RXTH_INT_MASK)
592 593 594 595 596
    {
        qspi->FIFOCTL &= ~QSPI_FIFOCTL_RXTHIEN_Msk;
    }

    /* Disable RX overrun interrupt flag */
W
Wayne Lin 已提交
597
    if ((u32Mask & QSPI_FIFO_RXOV_INT_MASK) == QSPI_FIFO_RXOV_INT_MASK)
598 599 600 601 602
    {
        qspi->FIFOCTL &= ~QSPI_FIFOCTL_RXOVIEN_Msk;
    }

    /* Disable RX time-out interrupt flag */
W
Wayne Lin 已提交
603
    if ((u32Mask & QSPI_FIFO_RXTO_INT_MASK) == QSPI_FIFO_RXTO_INT_MASK)
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
    {
        qspi->FIFOCTL &= ~QSPI_FIFOCTL_RXTOIEN_Msk;
    }
}

/**
  * @brief  Get interrupt flag.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @param[in]  u32Mask The combination of all related interrupt sources.
  *                     Each bit corresponds to a interrupt source.
  *                     This parameter decides which interrupt flags will be read. It is combination of:
  *                       - \ref QSPI_UNIT_INT_MASK
  *                       - \ref QSPI_SSACT_INT_MASK
  *                       - \ref QSPI_SSINACT_INT_MASK
  *                       - \ref QSPI_SLVUR_INT_MASK
  *                       - \ref QSPI_SLVBE_INT_MASK
  *                       - \ref QSPI_TXUF_INT_MASK
  *                       - \ref QSPI_FIFO_TXTH_INT_MASK
  *                       - \ref QSPI_FIFO_RXTH_INT_MASK
  *                       - \ref QSPI_FIFO_RXOV_INT_MASK
  *                       - \ref QSPI_FIFO_RXTO_INT_MASK
  *
  * @return Interrupt flags of selected sources.
  * @details Get QSPI related interrupt flags specified by u32Mask parameter.
  */
uint32_t QSPI_GetIntFlag(QSPI_T *qspi, uint32_t u32Mask)
{
    uint32_t u32IntFlag = 0U, u32TmpVal;

    u32TmpVal = qspi->STATUS & QSPI_STATUS_UNITIF_Msk;
    /* Check unit transfer interrupt flag */
W
Wayne Lin 已提交
635
    if ((u32Mask & QSPI_UNIT_INT_MASK) && (u32TmpVal))
636 637 638 639 640 641
    {
        u32IntFlag |= QSPI_UNIT_INT_MASK;
    }

    u32TmpVal = qspi->STATUS & QSPI_STATUS_SSACTIF_Msk;
    /* Check slave selection signal active interrupt flag */
W
Wayne Lin 已提交
642
    if ((u32Mask & QSPI_SSACT_INT_MASK) && (u32TmpVal))
643 644 645 646 647 648
    {
        u32IntFlag |= QSPI_SSACT_INT_MASK;
    }

    u32TmpVal = qspi->STATUS & QSPI_STATUS_SSINAIF_Msk;
    /* Check slave selection signal inactive interrupt flag */
W
Wayne Lin 已提交
649
    if ((u32Mask & QSPI_SSINACT_INT_MASK) && (u32TmpVal))
650 651 652 653 654 655
    {
        u32IntFlag |= QSPI_SSINACT_INT_MASK;
    }

    u32TmpVal = qspi->STATUS & QSPI_STATUS_SLVURIF_Msk;
    /* Check slave TX under run interrupt flag */
W
Wayne Lin 已提交
656
    if ((u32Mask & QSPI_SLVUR_INT_MASK) && (u32TmpVal))
657 658 659 660 661 662
    {
        u32IntFlag |= QSPI_SLVUR_INT_MASK;
    }

    u32TmpVal = qspi->STATUS & QSPI_STATUS_SLVBEIF_Msk;
    /* Check slave bit count error interrupt flag */
W
Wayne Lin 已提交
663
    if ((u32Mask & QSPI_SLVBE_INT_MASK) && (u32TmpVal))
664 665 666 667 668 669
    {
        u32IntFlag |= QSPI_SLVBE_INT_MASK;
    }

    u32TmpVal = qspi->STATUS & QSPI_STATUS_TXUFIF_Msk;
    /* Check slave TX underflow interrupt flag */
W
Wayne Lin 已提交
670
    if ((u32Mask & QSPI_TXUF_INT_MASK) && (u32TmpVal))
671 672 673 674 675 676
    {
        u32IntFlag |= QSPI_TXUF_INT_MASK;
    }

    u32TmpVal = qspi->STATUS & QSPI_STATUS_TXTHIF_Msk;
    /* Check TX threshold interrupt flag */
W
Wayne Lin 已提交
677
    if ((u32Mask & QSPI_FIFO_TXTH_INT_MASK) && (u32TmpVal))
678 679 680 681 682 683
    {
        u32IntFlag |= QSPI_FIFO_TXTH_INT_MASK;
    }

    u32TmpVal = qspi->STATUS & QSPI_STATUS_RXTHIF_Msk;
    /* Check RX threshold interrupt flag */
W
Wayne Lin 已提交
684
    if ((u32Mask & QSPI_FIFO_RXTH_INT_MASK) && (u32TmpVal))
685 686 687 688 689 690
    {
        u32IntFlag |= QSPI_FIFO_RXTH_INT_MASK;
    }

    u32TmpVal = qspi->STATUS & QSPI_STATUS_RXOVIF_Msk;
    /* Check RX overrun interrupt flag */
W
Wayne Lin 已提交
691
    if ((u32Mask & QSPI_FIFO_RXOV_INT_MASK) && (u32TmpVal))
692 693 694 695 696 697
    {
        u32IntFlag |= QSPI_FIFO_RXOV_INT_MASK;
    }

    u32TmpVal = qspi->STATUS & QSPI_STATUS_RXTOIF_Msk;
    /* Check RX time-out interrupt flag */
W
Wayne Lin 已提交
698
    if ((u32Mask & QSPI_FIFO_RXTO_INT_MASK) && (u32TmpVal))
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
    {
        u32IntFlag |= QSPI_FIFO_RXTO_INT_MASK;
    }

    return u32IntFlag;
}

/**
  * @brief  Clear interrupt flag.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @param[in]  u32Mask The combination of all related interrupt sources.
  *                     Each bit corresponds to a interrupt source.
  *                     This parameter decides which interrupt flags will be cleared. It could be the combination of:
  *                       - \ref QSPI_UNIT_INT_MASK
  *                       - \ref QSPI_SSACT_INT_MASK
  *                       - \ref QSPI_SSINACT_INT_MASK
  *                       - \ref QSPI_SLVUR_INT_MASK
  *                       - \ref QSPI_SLVBE_INT_MASK
  *                       - \ref QSPI_TXUF_INT_MASK
  *                       - \ref QSPI_FIFO_RXOV_INT_MASK
  *                       - \ref QSPI_FIFO_RXTO_INT_MASK
  *
  * @return None
  * @details Clear QSPI related interrupt flags specified by u32Mask parameter.
  */
void QSPI_ClearIntFlag(QSPI_T *qspi, uint32_t u32Mask)
{
W
Wayne Lin 已提交
726
    if (u32Mask & QSPI_UNIT_INT_MASK)
727 728 729 730
    {
        qspi->STATUS = QSPI_STATUS_UNITIF_Msk; /* Clear unit transfer interrupt flag */
    }

W
Wayne Lin 已提交
731
    if (u32Mask & QSPI_SSACT_INT_MASK)
732 733 734 735
    {
        qspi->STATUS = QSPI_STATUS_SSACTIF_Msk; /* Clear slave selection signal active interrupt flag */
    }

W
Wayne Lin 已提交
736
    if (u32Mask & QSPI_SSINACT_INT_MASK)
737 738 739 740
    {
        qspi->STATUS = QSPI_STATUS_SSINAIF_Msk; /* Clear slave selection signal inactive interrupt flag */
    }

W
Wayne Lin 已提交
741
    if (u32Mask & QSPI_SLVUR_INT_MASK)
742 743 744 745
    {
        qspi->STATUS = QSPI_STATUS_SLVURIF_Msk; /* Clear slave TX under run interrupt flag */
    }

W
Wayne Lin 已提交
746
    if (u32Mask & QSPI_SLVBE_INT_MASK)
747 748 749 750
    {
        qspi->STATUS = QSPI_STATUS_SLVBEIF_Msk; /* Clear slave bit count error interrupt flag */
    }

W
Wayne Lin 已提交
751
    if (u32Mask & QSPI_TXUF_INT_MASK)
752 753 754 755
    {
        qspi->STATUS = QSPI_STATUS_TXUFIF_Msk; /* Clear slave TX underflow interrupt flag */
    }

W
Wayne Lin 已提交
756
    if (u32Mask & QSPI_FIFO_RXOV_INT_MASK)
757 758 759 760
    {
        qspi->STATUS = QSPI_STATUS_RXOVIF_Msk; /* Clear RX overrun interrupt flag */
    }

W
Wayne Lin 已提交
761
    if (u32Mask & QSPI_FIFO_RXTO_INT_MASK)
762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
    {
        qspi->STATUS = QSPI_STATUS_RXTOIF_Msk; /* Clear RX time-out interrupt flag */
    }
}

/**
  * @brief  Get QSPI status.
  * @param[in]  qspi The pointer of the specified QSPI module.
  * @param[in]  u32Mask The combination of all related sources.
  *                     Each bit corresponds to a source.
  *                     This parameter decides which flags will be read. It is combination of:
  *                       - \ref QSPI_BUSY_MASK
  *                       - \ref QSPI_RX_EMPTY_MASK
  *                       - \ref QSPI_RX_FULL_MASK
  *                       - \ref QSPI_TX_EMPTY_MASK
  *                       - \ref QSPI_TX_FULL_MASK
  *                       - \ref QSPI_TXRX_RESET_MASK
  *                       - \ref QSPI_QSPIEN_STS_MASK
  *                       - \ref QSPI_SSLINE_STS_MASK
  *
  * @return Flags of selected sources.
  * @details Get QSPI related status specified by u32Mask parameter.
  */
uint32_t QSPI_GetStatus(QSPI_T *qspi, uint32_t u32Mask)
{
    uint32_t u32Flag = 0U, u32TmpValue;

    u32TmpValue = qspi->STATUS & QSPI_STATUS_BUSY_Msk;
    /* Check busy status */
W
Wayne Lin 已提交
791
    if ((u32Mask & QSPI_BUSY_MASK) && (u32TmpValue))
792 793 794 795 796 797
    {
        u32Flag |= QSPI_BUSY_MASK;
    }

    u32TmpValue = qspi->STATUS & QSPI_STATUS_RXEMPTY_Msk;
    /* Check RX empty flag */
W
Wayne Lin 已提交
798
    if ((u32Mask & QSPI_RX_EMPTY_MASK) && (u32TmpValue))
799 800 801 802 803 804
    {
        u32Flag |= QSPI_RX_EMPTY_MASK;
    }

    u32TmpValue = qspi->STATUS & QSPI_STATUS_RXFULL_Msk;
    /* Check RX full flag */
W
Wayne Lin 已提交
805
    if ((u32Mask & QSPI_RX_FULL_MASK) && (u32TmpValue))
806 807 808 809 810 811
    {
        u32Flag |= QSPI_RX_FULL_MASK;
    }

    u32TmpValue = qspi->STATUS & QSPI_STATUS_TXEMPTY_Msk;
    /* Check TX empty flag */
W
Wayne Lin 已提交
812
    if ((u32Mask & QSPI_TX_EMPTY_MASK) && (u32TmpValue))
813 814 815 816 817 818
    {
        u32Flag |= QSPI_TX_EMPTY_MASK;
    }

    u32TmpValue = qspi->STATUS & QSPI_STATUS_TXFULL_Msk;
    /* Check TX full flag */
W
Wayne Lin 已提交
819
    if ((u32Mask & QSPI_TX_FULL_MASK) && (u32TmpValue))
820 821 822 823 824 825
    {
        u32Flag |= QSPI_TX_FULL_MASK;
    }

    u32TmpValue = qspi->STATUS & QSPI_STATUS_TXRXRST_Msk;
    /* Check TX/RX reset flag */
W
Wayne Lin 已提交
826
    if ((u32Mask & QSPI_TXRX_RESET_MASK) && (u32TmpValue))
827 828 829 830 831 832
    {
        u32Flag |= QSPI_TXRX_RESET_MASK;
    }

    u32TmpValue = qspi->STATUS & QSPI_STATUS_QSPIENSTS_Msk;
    /* Check QSPIEN flag */
W
Wayne Lin 已提交
833
    if ((u32Mask & QSPI_QSPIEN_STS_MASK) && (u32TmpValue))
834 835 836 837 838 839
    {
        u32Flag |= QSPI_QSPIEN_STS_MASK;
    }

    u32TmpValue = qspi->STATUS & QSPI_STATUS_SSLINE_Msk;
    /* Check QSPIx_SS line status */
W
Wayne Lin 已提交
840
    if ((u32Mask & QSPI_SSLINE_STS_MASK) && (u32TmpValue))
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856
    {
        u32Flag |= QSPI_SSLINE_STS_MASK;
    }

    return u32Flag;
}



/*@}*/ /* end of group QSPI_EXPORTED_FUNCTIONS */

/*@}*/ /* end of group QSPI_Driver */

/*@}*/ /* end of group Standard_Driver */

/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/