From d1e67153c5a12a3c1853e9b029d13dd2353b0138 Mon Sep 17 00:00:00 2001 From: danielzhang Date: Fri, 12 Jan 2024 14:57:01 +0800 Subject: [PATCH] add mx25r module pack --- ra/fsp/inc/api/r_mx25r_extend_api.h | 132 +++++++++++ ra/fsp/inc/instances/r_mx25r_extend.h | 40 ++++ ra/fsp/src/r_mx25r/r_mx25r_extend.c | 302 ++++++++++++++++++++++++++ 3 files changed, 474 insertions(+) create mode 100644 ra/fsp/inc/api/r_mx25r_extend_api.h create mode 100644 ra/fsp/inc/instances/r_mx25r_extend.h create mode 100644 ra/fsp/src/r_mx25r/r_mx25r_extend.c diff --git a/ra/fsp/inc/api/r_mx25r_extend_api.h b/ra/fsp/inc/api/r_mx25r_extend_api.h new file mode 100644 index 000000000..6e3987b2d --- /dev/null +++ b/ra/fsp/inc/api/r_mx25r_extend_api.h @@ -0,0 +1,132 @@ +#ifndef FSP_INC_API_R_MX25R_EXTEND_API_H_ +#define FSP_INC_API_R_MX25R_EXTEND_API_H_ + +/* Register definitions, common services and error codes. */ +#include "bsp_api.h" + +/** Available commands for the Macronix MX25xxx series Serial NOR Flash device */ +typedef enum e_qspi_command +{ + /** Reset Operations */ + QSPI_COMMAND_RESET_ENABLE = 0x66, ///< Enable reset + QSPI_COMMAND_RESET_MEMORY = 0x99, ///< Reset memory + + QSPI_COMMAND_DEEP_POWER_DOWN = 0xb9, ///< Enter deep power down mode + QSPI_COMMAND_RELEASE_DEEP_POWER_DOWN = 0xab, ///< Release from deep power down mode + + /** Write Operations */ + QSPI_COMMAND_WRITE_ENABLE = 0x06, ///< Write Enable + QSPI_COMMAND_WRITE_DISABLE = 0x04, ///< Write Disable + + /** Register Operations */ + QSPI_COMMAND_READ_STATUS_REGISTER = 0x05, ///< Read Status register + QSPI_COMMAND_WRITE_STATUS_REGISTER = 0x01, ///< Write Status register + QSPI_COMMAND_READ_CONFIG_REGISTER = 0x15, ///< Read Configuration register + QSPI_COMMAND_READ_ID = 0x9F, ///< Read the chip ID + QSPI_COMMAND_READ_SECURITY_REGISTER = 0x2B, ///< Read Security register + QSPI_COMMAND_WRITE_SECURITY_REGISTER = 0x2F, ///< Write Security register + +} qspi_command; + +typedef struct st_mx25r_status_register +{ + union + { + uint8_t status; + struct + { + uint8_t wip : 1; ///< Erase/Write in progress (busy = 1) + uint8_t wel : 1; ///< Write Latch Enable (Set to 1 after write enable, 0 write disable) + uint8_t bp : 4; ///< Block Protection bits (1=protected, 0= unprotected) + uint8_t qe : 1; ///< Quad Enable (1= Quad enabled) + uint8_t srwd : 1; ///< Status Register Write Disable Bit + }status_b; + }; +} mx25r_status_reg; + +typedef struct st_mx25R_security_register +{ + union + { + uint8_t security; + struct + { + uint8_t secured_OTP : 1; ///< Secured OTP indicator bit + uint8_t ldso : 1; ///< Lock-down OTP (0=not lock-down, 1=lock-down) + uint8_t psb : 1; ///< Program Suspend bit (0=not suspend, 1=suspend) + uint8_t esb : 1; ///< Erase Suspend bit (0=not suspend, 1=suspend) + uint8_t : 1; ///< Reverse + uint8_t p_fial : 1; ///< (0=normal program succeed, 1=program failed) + uint8_t e_fial : 1; ///< (0=normal erase succeed, 1=erase failed) + uint8_t wpsel : 1; ///< Only for MX25Lxxx,OTP (0=BP mode, 1=advance mode) + }security_b; + }; +} mx25R_security_reg; + +typedef struct st_mx25r_configuration_register +{ + union + { + uint8_t configuration1; + struct + { + uint8_t : 3; ///< reserved + uint8_t tb : 1; ///< top/bottom selected (OTP bit) + uint8_t : 2; ///< reserved + uint8_t dc : 1; ///< dummy cycle for 2read and 4read + uint8_t : 1; ///< reserved + }configuration1_b; + }; + union + { + uint8_t configuration2; + struct + { + uint8_t : 1; ///< reserved + uint8_t lhs : 1; ///< ultra low power mode and high performance mode switch + uint8_t : 6; ///< reserved + }configuration2_b; + }; + +} mx25r_cfg_reg; + + +typedef struct st_mx25r_ID +{ + uint8_t manufacturer_id; ///< Manufacturer ID + uint8_t memory_type; ///< Memory type + uint8_t memory_capacity; ///< Memory capacity +} mx25r_ID; + + +/** QSPI functions implemented at the HAL layer follow this API. */ +typedef struct st_mx25r_extend_api +{ + void (* mx25r_lowpowermode)(void); + void (* mx25r_highperformancemode)(void); + void (* mx25r_enter_deeppower)(void); + void (* mx25r_exit_deeppower)(void); + void (* mx25r_device_reset)(void); + void (* rdid)(mx25r_ID* ID); + void (* rdsr)(mx25r_status_reg* status); + void (* rdscur)(mx25R_security_reg* security); + void (* rdcr)(mx25r_cfg_reg* configuration); + +} mx25r_extend_api_t; + +typedef void mx25r_extend_ctrl_t; + +typedef struct mx25r_extend_cfg +{ + void const * p_extend; ///< Pointer to hardware dependent configuration +} mx25r_extend_cfg_t; + +typedef struct st_mx25r_extend_instance +{ + mx25r_extend_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance + mx25r_extend_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance + mx25r_extend_api_t const * p_api; ///< Pointer to the API structure for this instance + +} mx25r_extend_instance_t; + +#endif /* FSP_INC_API_R_MX25R_EXTEND_API_H_ */ diff --git a/ra/fsp/inc/instances/r_mx25r_extend.h b/ra/fsp/inc/instances/r_mx25r_extend.h new file mode 100644 index 000000000..486410307 --- /dev/null +++ b/ra/fsp/inc/instances/r_mx25r_extend.h @@ -0,0 +1,40 @@ +#ifndef FSP_INC_INSTANCES_R_MX25R_EXTEND_H_ +#define FSP_INC_INSTANCES_R_MX25R_EXTEND_H_ + +#include +#include + +/** User configuration structure, used in open function */ +typedef struct st_mx25r_extend_flash_cfg +{ + spi_flash_instance_t const * p_flash; ///< Pointer to a QSPI flash instance +} mx25r_extend_flash_cfg_t; + +/** Instance control block. This is private to the FSP and should not be used or modified by the application. */ +typedef struct st_mx25r_extend_instance_ctrl +{ + mx25r_extend_cfg_t const * p_cfg; +} mx25r_extend_instance_ctrl_t; + +extern const mx25r_extend_api_t g_mx25r_extend_on_QSPI; + +extern bool deepdown; + +void MX25R_LowPowerMode(void); +void MX25R_HighPerformanceMode(void); +void MX25R_Enter_DeepPower(void); +void MX25R_Exit_DeepPower(void); +void MX25R_Device_Reset(void); +void RDID(mx25r_ID* ID); +void RDSR(mx25r_status_reg* status); +void RDSCUR(mx25R_security_reg* security); +void RDCR(mx25r_cfg_reg* configuration); + +fsp_err_t setNormalMode(); +fsp_err_t setHighPerformanceMode(); +fsp_err_t setLowPowerMode(); +fsp_err_t setSuperLowPowerMode(); +fsp_err_t setDeepPowerDownMode(); +fsp_err_t power_init(); + +#endif /* FSP_INC_INSTANCES_R_MX25R_EXTEND_H_ */ diff --git a/ra/fsp/src/r_mx25r/r_mx25r_extend.c b/ra/fsp/src/r_mx25r/r_mx25r_extend.c new file mode 100644 index 000000000..c21c7009a --- /dev/null +++ b/ra/fsp/src/r_mx25r/r_mx25r_extend.c @@ -0,0 +1,302 @@ +#include +#include "bsp_api.h" + +const mx25r_extend_api_t g_mx25r_extend_on_QSPI = +{ + .mx25r_device_reset = MX25R_Device_Reset, + .mx25r_enter_deeppower = MX25R_Enter_DeepPower, + .mx25r_exit_deeppower = MX25R_Exit_DeepPower, + .mx25r_highperformancemode = MX25R_HighPerformanceMode, + .mx25r_lowpowermode = MX25R_LowPowerMode, + .rdid = RDID, + .rdcr = RDCR, + .rdsr = RDSR, + .rdscur = RDSCUR, +}; + +bool deepdown; + +void RDID(mx25r_ID* ID) +{ + /* Check there is no serial transfer in progress */ + while (1U == R_QSPI->SFMCST_b.COMBSY) + { + } + + /* Enter direct communication mode */ + R_QSPI->SFMCMD = 1U; + + /* Read ID. */ + R_QSPI->SFMCOM = QSPI_COMMAND_READ_ID; /* Write the command */ + ID->manufacturer_id = R_QSPI->SFMCOM_b.SFMD; /* Read manufacturer_id*/ + ID->memory_capacity = R_QSPI->SFMCOM_b.SFMD; /* Read memory_capacity*/ + ID->memory_type = R_QSPI->SFMCOM_b.SFMD; /* Read memory_type*/ + R_QSPI->SFMCMD = 1U; + + /* Return to ROM access mode */ + R_QSPI->SFMCMD = 0U; +} + +void RDSR(mx25r_status_reg* status) +{ + /* Check there is no serial transfer in progress */ + while (1U == R_QSPI->SFMCST_b.COMBSY) + { + } + + /* Enter direct communication mode */ + R_QSPI->SFMCMD = 1U; + + /* Read status register. */ + R_QSPI->SFMCOM = QSPI_COMMAND_READ_STATUS_REGISTER; /* Write the command */ + status->status = R_QSPI->SFMCOM_b.SFMD; /* Read Read status register*/ + R_QSPI->SFMCMD = 1U; + + /* Return to ROM access mode */ + R_QSPI->SFMCMD = 0U; +} + +void RDSCUR(mx25R_security_reg* security) +{ + /* Check there is no serial transfer in progress */ + while (1U == R_QSPI->SFMCST_b.COMBSY) + { + } + + /* Enter direct communication mode */ + R_QSPI->SFMCMD = 1U; + + /* Read security register. */ + R_QSPI->SFMCOM = QSPI_COMMAND_READ_SECURITY_REGISTER; /* Write the command */ + security->security = R_QSPI->SFMCOM_b.SFMD; /* Read Read security register*/ + R_QSPI->SFMCMD = 1U; + + /* Return to ROM access mode */ + R_QSPI->SFMCMD = 0U; +} + +void RDCR(mx25r_cfg_reg* configuration) +{ + /* Check there is no serial transfer in progress */ + while (1U == R_QSPI->SFMCST_b.COMBSY) + { + } + + /* Enter direct communication mode */ + R_QSPI->SFMCMD = 1U; + + /* Read configuration register-1 and configuration register-2. */ + R_QSPI->SFMCOM = QSPI_COMMAND_READ_CONFIG_REGISTER; /* Write the command */ + configuration->configuration1 = R_QSPI->SFMCOM_b.SFMD; /* Read Read security register*/ + configuration->configuration2 = R_QSPI->SFMCOM_b.SFMD; /* Read Read security register*/ + R_QSPI->SFMCMD = 1U; + + /* Return to ROM access mode */ + R_QSPI->SFMCMD = 0U; +} + +void MX25R_LowPowerMode (void) +{ + mx25r_status_reg status_reg; + mx25r_cfg_reg cfg_reg; + + /* Check there is no serial transfer in progress */ + while (1U == R_QSPI->SFMCST_b.COMBSY) + { + } + + /* Enter direct communication mode */ + R_QSPI->SFMCMD = 1U; + + /* Read status register */ + R_QSPI->SFMCOM = QSPI_COMMAND_READ_STATUS_REGISTER; /* Write the command */ + status_reg.status = R_QSPI->SFMCOM_b.SFMD; /* Read status register */ + R_QSPI->SFMCMD = 1U; /* Close the SPI bus cycle */ + + /* Read configuration register-1 and configuration register-2. */ + R_QSPI->SFMCOM = QSPI_COMMAND_READ_CONFIG_REGISTER; /* Write the command */ + cfg_reg.configuration1 = R_QSPI->SFMCOM_b.SFMD; /* Read configuration register 1*/ + cfg_reg.configuration2 = R_QSPI->SFMCOM_b.SFMD; /* Read configuration register 2*/ + R_QSPI->SFMCMD = 1U; /* Close the SPI bus cycle */ + + /* set configuration register-2 lhs bit to 0 to goto ultra lower power mode*/ + cfg_reg.configuration2_b.lhs = 0U; + + R_QSPI->SFMCOM = QSPI_COMMAND_WRITE_ENABLE; /* Write the command */ + R_QSPI->SFMCMD_b.DCOM = 1U; /* Close the SPI bus cycle */ + + /* Write Status Register, configuration register-1 and configuration register-2 */ + R_QSPI->SFMCOM = QSPI_COMMAND_WRITE_STATUS_REGISTER; /* Write the command */ + R_QSPI->SFMCOM = status_reg.status; /* Write the Status Register */ + R_QSPI->SFMCOM = cfg_reg.configuration1; /* Write the configuration register-1 */ + R_QSPI->SFMCOM = cfg_reg.configuration2; /* Write the configuration register-2 */ + R_QSPI->SFMCMD_b.DCOM = 1U; /* Close the SPI bus cycle */ + + /* Write Status Register takes 40ms */ + R_BSP_SoftwareDelay(40U, BSP_DELAY_UNITS_MILLISECONDS); + + /* Return to ROM access mode */ + R_QSPI->SFMCMD = 0U; +} + +void MX25R_HighPerformanceMode (void) +{ + mx25r_status_reg status_reg; + mx25r_cfg_reg cfg_reg; + + /* Check there is no serial transfer in progress */ + while (1U == R_QSPI->SFMCST_b.COMBSY) + { + } + + /* Enter direct communication mode */ + R_QSPI->SFMCMD = 1U; + + /* Read status register */ + R_QSPI->SFMCOM = QSPI_COMMAND_READ_STATUS_REGISTER; /* Write the command */ + status_reg.status = R_QSPI->SFMCOM_b.SFMD; /* Read status register */ + R_QSPI->SFMCMD = 1U; /* Close the SPI bus cycle */ + + /* Read configuration register-1 and configuration register-2. */ + R_QSPI->SFMCOM = QSPI_COMMAND_READ_CONFIG_REGISTER; /* Write the command */ + cfg_reg.configuration1 = R_QSPI->SFMCOM_b.SFMD; /* Read configuration register 1*/ + cfg_reg.configuration2 = R_QSPI->SFMCOM_b.SFMD; /* Read configuration register 2*/ + R_QSPI->SFMCMD = 1U; /* Close the SPI bus cycle */ + + /* set configuration register-2 lhs bit to 1 to goto high performance mode*/ + cfg_reg.configuration2_b.lhs = 1U; + + R_QSPI->SFMCOM = QSPI_COMMAND_WRITE_ENABLE; /* Write the command */ + R_QSPI->SFMCMD = 1U; /* Close the SPI bus cycle */ + + /* Write Status Register, configuration register-1 and configuration register-2 */ + R_QSPI->SFMCOM = QSPI_COMMAND_WRITE_STATUS_REGISTER; /* Write the command */ + R_QSPI->SFMCOM = status_reg.status; /* Write the Status Register */ + R_QSPI->SFMCOM = cfg_reg.configuration1; /* Write the configuration register-1 */ + R_QSPI->SFMCOM = cfg_reg.configuration2; /* Write the configuration register-2 */ + R_QSPI->SFMCMD = 1U; /* Close the SPI bus cycle */ + + /* Write Status Register takes 40ms */ + R_BSP_SoftwareDelay(40U, BSP_DELAY_UNITS_MILLISECONDS); + + /* Return to ROM access mode */ + R_QSPI->SFMCMD = 0U; +} + +void MX25R_Enter_DeepPower (void) +{ + /* Check there is no serial transfer in progress */ + while (1U == R_QSPI->SFMCST_b.COMBSY){} + + /* enter direct communication mode */ + R_QSPI->SFMCMD = 1U; + + R_QSPI->SFMCOM = QSPI_COMMAND_DEEP_POWER_DOWN; /* Write the command */ + R_QSPI->SFMCMD = 1U; /* Close the SPI bus cycle */ + + /* As soon as CS# goes high, a maximum delay of 10us is required before entering the Deep Power-down mode*/ + R_BSP_SoftwareDelay(10U, BSP_DELAY_UNITS_MICROSECONDS); + + /* Return to ROM access mode */ + R_QSPI->SFMCMD = 0U; +} + +void MX25R_Exit_DeepPower (void) +{ + /* Check there is no serial transfer in progress */ + while (1U == R_QSPI->SFMCST_b.COMBSY) + { + } + + /* enter direct communication mode */ + R_QSPI->SFMCMD = 1U; + + /** For MX25Rxx: flash chip doesn't have RDP command, so using using CS# go low and then go high method + * to release from deep power down mode */ + /* 1) CS# keeps high for minimum 30us */ + R_BSP_SoftwareDelay(30U, BSP_DELAY_UNITS_MICROSECONDS); + + /* 2) CS# keeps low for minimum 20ns, MCU highest frequency is 240MhZ, 20ns at least need 4 instructions */ + R_QSPI->SFMCOM = 0x00U; /* used to keep CS# low */ + R_QSPI->SFMCOM = 0x00U; /* used to keep CS# low */ + R_QSPI->SFMCOM = 0x00U; /* used to keep CS# low */ + R_QSPI->SFMCOM = 0x00U; /* used to keep CS# low */ + R_QSPI->SFMCMD = 1U; /* Close the SPI bus cycle */ + + /* 3) As soon as CS# goes high, a maximum delay of 35us is required before releasing from Deep Power-down mode */ + R_BSP_SoftwareDelay(35U, BSP_DELAY_UNITS_MICROSECONDS); + + /* Return to ROM access mode */ + R_QSPI->SFMCMD = 0U; + +} + +void MX25R_Device_Reset (void) +{ + /* 1) Check there is no serial transfer in progress */ + while (1U == R_QSPI->SFMCST_b.COMBSY) + { + } + + /* enter direct communication mode */ + R_QSPI->SFMCMD = 1U; + + /* 2) Reset the flash device. */ + R_QSPI->SFMCOM = QSPI_COMMAND_RESET_ENABLE; /* Write the command */ + R_QSPI->SFMCMD = 1U; /* Close the SPI bus cycle */ + R_QSPI->SFMCOM = QSPI_COMMAND_RESET_MEMORY; /* Write the command */ + R_QSPI->SFMCMD = 1U; /* Close the SPI bus cycle */ + + /* 3) Reset takes maximum 80us */ + R_BSP_SoftwareDelay(80U, BSP_DELAY_UNITS_MICROSECONDS); + + R_QSPI->SFMCMD = 1U; /* enter direct communication mode */ + + R_QSPI->SFMCMD = 0U; /* Return to ROM access mode */ + +} + +fsp_err_t setNormalMode() +{ + return FSP_ERR_UNSUPPORTED; +} + +fsp_err_t setHighPerformanceMode() +{ + if(deepdown){ + MX25R_Exit_DeepPower(); + } + + MX25R_HighPerformanceMode(); + return FSP_SUCCESS; +} + +fsp_err_t setLowPowerMode() +{ + if(deepdown){ + MX25R_Exit_DeepPower(); + } + + MX25R_LowPowerMode(); + return FSP_SUCCESS; +} + +fsp_err_t setSuperLowPowerMode() +{ + return FSP_ERR_UNSUPPORTED; +} + +fsp_err_t setDeepPowerDownMode() +{ + MX25R_Enter_DeepPower(); + deepdown = true; + return FSP_SUCCESS; +} + +fsp_err_t power_init() +{ + deepdown = false; + return FSP_SUCCESS; +} + +