123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- /**
- *******************************************************************************
- * @file w25qxx.c
- * @brief This midware file provides firmware functions to W25QXX group spi flash.
- @verbatim
- Change Logs:
- Date Author Notes
- 2022-03-31 CDT First version
- @endverbatim
- *******************************************************************************
- * Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
- *
- * This software component is licensed by XHSC under BSD 3-Clause license
- * (the "License"); You may not use this file except in compliance with the
- * License. You may obtain a copy of the License at:
- * opensource.org/licenses/BSD-3-Clause
- *
- *******************************************************************************
- */
- /*******************************************************************************
- * Include files
- ******************************************************************************/
- #include "hal_w25qxx.h"
- /**
- * @addtogroup BSP
- * @{
- */
- /**
- * @addtogroup Components
- * @{
- */
- /**
- * @defgroup W25QXX Flash Driver for W25QXX
- * @{
- */
- /*******************************************************************************
- * Local type definitions ('typedef')
- ******************************************************************************/
- /*******************************************************************************
- * Local pre-processor symbols/macros ('#define')
- ******************************************************************************/
- /**
- * @defgroup W25QXX_Local_Macros W25QXX Local Macros
- * @{
- */
- #define W25QXX_FLAG_BUSY (1UL << 0U)
- #define W25QXX_FLAG_WEL (1UL << 1U) /*!< Write Enable Latch */
- #define W25QXX_FLAG_SUSPEND (1UL << 15U) /*!< Write Enable Latch */
- #define LOAD_CMD(a, cmd, addr) do { \
- (a)[0U] = (cmd); \
- (a)[1U] = (uint8_t)((addr) >> 16U); \
- (a)[2U] = (uint8_t)((addr) >> 8U); \
- (a)[3U] = (uint8_t)(addr); \
- } while (0U)
- /**
- * @}
- */
- /*******************************************************************************
- * Global variable definitions (declared in header file with 'extern')
- ******************************************************************************/
- /*******************************************************************************
- * Local function prototypes ('static')
- ******************************************************************************/
- /*******************************************************************************
- * Local variable definitions ('static')
- ******************************************************************************/
- /*******************************************************************************
- * Function implementation - global ('extern') and local ('static')
- ******************************************************************************/
- /**
- * @addtogroup W25QXX_Local_Functions W25QXX Local Functions
- * @{
- */
- /**
- * @brief W25QXX write command.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @param [in] u8Cmd Command of W25QXX.
- * @param [in] pu8CmdData Pointer to a buffer that contains the data following the command.
- * @param [in] u32CmdDataLen The length of the command data in bytes.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- static int32_t W25QXX_WriteCmd(const stc_w25qxx_ll_t *pstcW25qxxLL, \
- uint8_t u8Cmd, const uint8_t *pu8CmdData, uint32_t u32CmdDataLen)
- {
- int32_t i32Ret;
- pstcW25qxxLL->Active();
- i32Ret = pstcW25qxxLL->Trans(&u8Cmd, 1U);
- if ((i32Ret == LL_OK) && (pu8CmdData != NULL) && (u32CmdDataLen > 0UL)) {
- i32Ret = pstcW25qxxLL->Trans(pu8CmdData, u32CmdDataLen);
- }
- pstcW25qxxLL->Inactive();
- return i32Ret;
- }
- /**
- * @brief W25QXX read command.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @param [in] u8Cmd Command of W25QXX.
- * @param [in] pu8CmdData Pointer to a buffer that contains the data following the command.
- * @param [in] u32CmdDataLen The length of the command data in bytes.
- * @param [in] pu8Info The information of the command.
- * @param [in] u8InfoLen The length of the information.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- static int32_t W25QXX_ReadCmd(const stc_w25qxx_ll_t *pstcW25qxxLL, \
- uint8_t u8Cmd, uint8_t *pu8CmdData, uint32_t u32CmdDataLen,
- uint8_t *pu8Info, uint8_t u8InfoLen)
- {
- int32_t i32Ret;
- pstcW25qxxLL->Active();
- i32Ret = pstcW25qxxLL->Trans(&u8Cmd, 1U);
- if ((i32Ret == LL_OK) && (pu8CmdData != NULL) && (u32CmdDataLen > 0UL)) {
- i32Ret = pstcW25qxxLL->Trans(pu8CmdData, u32CmdDataLen);
- }
- if ((i32Ret == LL_OK) && (pu8Info != NULL) && (u8InfoLen > 0UL)) {
- i32Ret = pstcW25qxxLL->Receive(pu8Info, (uint32_t)u8InfoLen);
- }
- pstcW25qxxLL->Inactive();
- return i32Ret;
- }
- /**
- * @brief W25QXX write data.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @param [in] u8Cmd Command of W25QXX.
- * @param [in] u32Addr The start address of the data to be written.
- * @param [in] pu8Data The data to be written.
- * @param [in] u32DataLen The length of the data in bytes.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- static int32_t W25QXX_Wt(const stc_w25qxx_ll_t *pstcW25qxxLL, \
- uint8_t u8Cmd, uint32_t u32Addr, \
- const uint8_t *pu8Data, uint32_t u32DataLen)
- {
- uint8_t au8Cmd[4U];
- int32_t i32Ret;
- LOAD_CMD(au8Cmd, u8Cmd, u32Addr);
- pstcW25qxxLL->Active();
- i32Ret = pstcW25qxxLL->Trans(au8Cmd, 4U);
- if ((i32Ret == LL_OK) && (pu8Data != NULL) && (u32DataLen > 0UL)) {
- i32Ret = pstcW25qxxLL->Trans(pu8Data, u32DataLen);
- }
- pstcW25qxxLL->Inactive();
- return i32Ret;
- }
- /**
- * @brief W25QXX read data.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @param [in] u8Cmd Command of W25QXX.
- * @param [in] u32Addr The start address of the data to be written.
- * @param [in] pu8Data The data to be stored.
- * @param [in] u32DataLen The length of the data in bytes.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- static int32_t W25QXX_Rd(const stc_w25qxx_ll_t *pstcW25qxxLL, \
- uint8_t u8Cmd, uint32_t u32Addr, \
- uint8_t *pu8Data, uint32_t u32DataLen)
- {
- uint8_t au8Cmd[4U];
- int32_t i32Ret;
- LOAD_CMD(au8Cmd, u8Cmd, u32Addr);
- pstcW25qxxLL->Active();
- i32Ret = pstcW25qxxLL->Trans(au8Cmd, 4U);
- if (i32Ret == LL_OK) {
- i32Ret = pstcW25qxxLL->Receive(pu8Data, u32DataLen);
- }
- pstcW25qxxLL->Inactive();
- return i32Ret;
- }
- /**
- * @brief W25QXX Write enable.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- static int32_t W25QXX_WriteEnable(const stc_w25qxx_ll_t *pstcW25qxxLL)
- {
- return W25QXX_WriteCmd(pstcW25qxxLL, W25QXX_WRITE_ENABLE, NULL, 0U);
- }
- /**
- * @brief W25QXX Write disable.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- static int32_t W25QXX_WriteDisable(const stc_w25qxx_ll_t *pstcW25qxxLL)
- {
- return W25QXX_WriteCmd(pstcW25qxxLL, W25QXX_WRITE_DISABLE, NULL, 0U);
- }
- /**
- * @brief Wait for processing done.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_TIMEOUT: SPI timeout or W25QXX timeout.
- */
- static int32_t W25QXX_WaitProcessDone(const stc_w25qxx_ll_t *pstcW25qxxLL)
- {
- uint8_t u8Status;
- int32_t i32Ret = LL_ERR_TIMEOUT;
- volatile uint32_t u32Timecount = W25QXX_TIMEOUT;
- while (u32Timecount-- != 0UL) {
- i32Ret = W25QXX_ReadStatus(pstcW25qxxLL, W25QXX_READ_STATUS_REGISTER_1, &u8Status);
- if ((i32Ret == LL_OK) && ((u8Status & W25QXX_FLAG_BUSY) == 0U)) {
- break;
- }
- }
- return i32Ret;
- }
- /**
- * @}
- */
- /**
- * @defgroup W25QXX_Global_Functions W25QXX Global Functions
- * @{
- */
- /**
- * @brief Initializes W25QXX.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter
- */
- int32_t W25QXX_Init(const stc_w25qxx_ll_t *pstcW25qxxLL)
- {
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if (pstcW25qxxLL != NULL) {
- pstcW25qxxLL->Init();
- i32Ret = LL_OK;
- }
- return i32Ret;
- }
- /**
- * @brief De-Initialize W25QXX.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter
- */
- int32_t W25QXX_DeInit(const stc_w25qxx_ll_t *pstcW25qxxLL)
- {
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if (pstcW25qxxLL != NULL) {
- pstcW25qxxLL->DeInit();
- i32Ret = LL_OK;
- }
- return i32Ret;
- }
- /**
- * @brief Read manufacturer device ID.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @param [out] pu16ID Pointer to an address to store the device ID.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- int32_t W25QXX_GetManDeviceId(const stc_w25qxx_ll_t *pstcW25qxxLL, uint16_t *pu16ID)
- {
- uint8_t au8TempId[2U];
- uint8_t au8Dummy[3U] = {0U};
- uint16_t u16ManID;
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if ((pstcW25qxxLL != NULL) && (pu16ID != NULL)) {
- i32Ret = W25QXX_ReadCmd(pstcW25qxxLL, W25QXX_MANUFACTURER_DEVICE_ID, au8Dummy, 3U, au8TempId, 2U);
- if (i32Ret == LL_OK) {
- u16ManID = (uint16_t)au8TempId[0U] << 8U;
- u16ManID |= au8TempId[1U];
- *pu16ID = u16ManID;
- }
- }
- return i32Ret;
- }
- /**
- * @brief Read unique ID.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @param [out] pu8UniqueId Pointer to a buffer the 64 bit unique ID to be stored.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- int32_t W25QXX_GetUniqueId(const stc_w25qxx_ll_t *pstcW25qxxLL, uint8_t *pu8UniqueId)
- {
- uint8_t au8Dummy[4U] = {0U};
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if ((pstcW25qxxLL != NULL) && (pu8UniqueId != NULL)) {
- i32Ret = W25QXX_ReadCmd(pstcW25qxxLL, W25QXX_READ_UNIQUE_ID, au8Dummy, 4U, pu8UniqueId, 8U);
- }
- return i32Ret;
- }
- /**
- * @brief Read status register.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @param [in] u8SrRdCmd Command of reading status register.
- * @arg W25QXX_READ_STATUS_REGISTER_1: Read status register 1.
- * @arg W25QXX_READ_STATUS_REGISTER_2: Read status register 2.
- * @arg W25QXX_READ_STATUS_REGISTER_3: Read status register 3.
- * @param [out] pu8Status Pointer to an address the status value to be stored.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- int32_t W25QXX_ReadStatus(const stc_w25qxx_ll_t *pstcW25qxxLL, uint8_t u8SrRdCmd, uint8_t *pu8Status)
- {
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if ((pstcW25qxxLL != NULL) && (pu8Status != NULL)) {
- i32Ret = W25QXX_ReadCmd(pstcW25qxxLL, u8SrRdCmd, NULL, 0U, pu8Status, 1U);
- }
- return i32Ret;
- }
- /**
- * @brief Write status register.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @param [in] u8SrWtCmd Command of writting status register.
- * @arg W25QXX_WRITE_STATUS_REGISTER_1: Write status register 1.
- * @arg W25QXX_WRITE_STATUS_REGISTER_2: Write status register 2.
- * @arg W25QXX_WRITE_STATUS_REGISTER_3: Write status register 3.
- * @param [in] u8Value 8bit value of the specified status register.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- int32_t W25QXX_WriteStatus(const stc_w25qxx_ll_t *pstcW25qxxLL, uint8_t u8SrWtCmd, uint8_t u8Value)
- {
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if (pstcW25qxxLL != NULL) {
- i32Ret = W25QXX_WriteCmd(pstcW25qxxLL, u8SrWtCmd, &u8Value, 1U);
- }
- return i32Ret;
- }
- /**
- * @brief Power down.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- int32_t W25QXX_PowerDown(const stc_w25qxx_ll_t *pstcW25qxxLL)
- {
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if (pstcW25qxxLL != NULL) {
- i32Ret = W25QXX_WriteCmd(pstcW25qxxLL, W25QXX_POWER_DOWN, NULL, 0U);
- if (i32Ret == LL_OK) {
- pstcW25qxxLL->Delay(1U);
- }
- }
- return i32Ret;
- }
- /**
- * @brief Release power down.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- int32_t W25QXX_ReleasePowerDown(const stc_w25qxx_ll_t *pstcW25qxxLL)
- {
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if (pstcW25qxxLL != NULL) {
- i32Ret = W25QXX_WriteCmd(pstcW25qxxLL, W25QXX_RELEASE_POWER_DOWN_ID, NULL, 0U);
- if (i32Ret == LL_OK) {
- pstcW25qxxLL->Delay(1U);
- }
- }
- return i32Ret;
- }
- /**
- * @brief Ease chip.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter.
- * - LL_ERR_TIMEOUT: SPI timeout or W25QXX timeout.
- */
- int32_t W25QXX_EraseChip(const stc_w25qxx_ll_t *pstcW25qxxLL)
- {
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if (pstcW25qxxLL != NULL) {
- i32Ret = W25QXX_WriteEnable(pstcW25qxxLL);
- if (i32Ret == LL_OK) {
- i32Ret = W25QXX_WaitProcessDone(pstcW25qxxLL);
- }
- if (i32Ret == LL_OK) {
- i32Ret = W25QXX_WriteCmd(pstcW25qxxLL, W25QXX_CHIP_ERASE, NULL, 0U);
- }
- if (i32Ret == LL_OK) {
- i32Ret = W25QXX_WaitProcessDone(pstcW25qxxLL);
- }
- }
- return i32Ret;
- }
- /**
- * @brief Ease sector.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @param [in] u32Addr Any address of the specified sector.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter.
- * - LL_ERR_TIMEOUT: SPI timeout or W25QXX timeout.
- */
- int32_t W25QXX_EraseSector(const stc_w25qxx_ll_t *pstcW25qxxLL, uint32_t u32Addr)
- {
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if (pstcW25qxxLL != NULL) {
- i32Ret = W25QXX_WriteEnable(pstcW25qxxLL);
- if (i32Ret == LL_OK) {
- i32Ret = W25QXX_WaitProcessDone(pstcW25qxxLL);
- }
- if (i32Ret == LL_OK) {
- i32Ret = W25QXX_Wt(pstcW25qxxLL, W25QXX_SECTOR_ERASE, u32Addr, NULL, 0U);
- }
- if (i32Ret == LL_OK) {
- i32Ret = W25QXX_WaitProcessDone(pstcW25qxxLL);
- }
- if (i32Ret == LL_OK) {
- i32Ret = W25QXX_WriteDisable(pstcW25qxxLL);
- }
- }
- return i32Ret;
- }
- /**
- * @brief W25QXX read data.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @param [in] u32Addr The start address of the data to be read.
- * @param [in] pu8ReadBuf The pointer to the buffer contains the data to be stored.
- * @param [in] u32NumByteToRead Buffer size in bytes.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter.
- * - LL_ERR_TIMEOUT: SPI timeout.
- */
- int32_t W25QXX_ReadData(const stc_w25qxx_ll_t *pstcW25qxxLL, uint32_t u32Addr, \
- uint8_t *pu8ReadBuf, uint32_t u32NumByteToRead)
- {
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if ((pstcW25qxxLL != NULL) && (pu8ReadBuf != NULL) && (u32NumByteToRead != 0UL)) {
- i32Ret = W25QXX_Rd(pstcW25qxxLL, W25QXX_READ_DATA, u32Addr, pu8ReadBuf, u32NumByteToRead);
- }
- return i32Ret;
- }
- /**
- * @brief W25QXX page program.
- * @param [in] pstcW25qxxLL Pointer to a @ref stc_w25qxx_ll_t structure.
- * @param [in] u32Addr Start address of the page.
- * @param [in] pu8Data Pointer to a buffer that contains the data to be written.
- * @param [in] u32NumByteToProgram Size of the buffer.
- * @retval int32_t:
- * - LL_OK: No error occurred.
- * - LL_ERR_INVD_PARAM: Invalid parameter.
- * - LL_ERR_TIMEOUT: SPI timeout or W25QXX timeout.
- */
- int32_t W25QXX_PageProgram(const stc_w25qxx_ll_t *pstcW25qxxLL, uint32_t u32Addr, \
- const uint8_t *pu8Data, uint32_t u32NumByteToProgram)
- {
- int32_t i32Ret = LL_ERR_INVD_PARAM;
- if ((pstcW25qxxLL != NULL) && (pu8Data != NULL) && (u32NumByteToProgram != 0UL)) {
- i32Ret = W25QXX_WriteEnable(pstcW25qxxLL);
- if (i32Ret == LL_OK) {
- i32Ret = W25QXX_Wt(pstcW25qxxLL, W25QXX_PAGE_PROGRAM, u32Addr, pu8Data, u32NumByteToProgram);
- }
- if (i32Ret == LL_OK) {
- i32Ret = W25QXX_WaitProcessDone(pstcW25qxxLL);
- }
- }
- return i32Ret;
- }
- /**
- * @}
- */
- /**
- * @}
- */
- /**
- * @}
- */
- /**
- * @}
- */
- /*******************************************************************************
- * EOF (not truncated)
- ******************************************************************************/
|