| | |
| | | /* |
| | | * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and |
| | | * Copyright (c) 2019-2025 Beijing Hanwei Innovation Technology Ltd. Co. and |
| | | * its subsidiaries and affiliates (collectly called MKSEMI). |
| | | * |
| | | * All rights reserved. |
| | |
| | | #include "mk_trace.h" |
| | | #include "mk_misc.h" |
| | | |
| | | #define CMP_MASK (1U << 6) |
| | | #define DC_MASK (1U << 4) |
| | | #define QE_MASK (1U << 1) |
| | | #define SRP1_MASK (1U << 0) |
| | | |
| | | #if FLASH_DMA_MODE_EN |
| | | static void flash_dma_callback(void *ch, uint32_t err_code); |
| | | static void flash_dma_write_nbytes_callback(void *ch, uint32_t err_code); |
| | |
| | | .dma_wr_ch = DMA_CH2, |
| | | .dma_rd_ch = DMA_CH3, |
| | | .config = |
| | | { |
| | | .timeout = 0xFFFFU, |
| | | .cs_high_time = 0xFU, |
| | | .dual_mode = false, |
| | | .prefetch_dis = false, |
| | | .cache_prefetch_dis = false, |
| | | .feedback_clk_sel = false, |
| | | .spi_sck_high = false, |
| | | .spi_falling_edge_active = true, |
| | | .dma_en = false, |
| | | .int_en = false, |
| | | .start_addr = FLASH_BASE, |
| | | .total_size = FLASH_SIZE, |
| | | .block_size = FLASH_BLOCK_SIZE, |
| | | .sector_size = FLASH_SECTOR_SIZE, |
| | | .page_size = FLASH_PAGE_SIZE, |
| | | }, |
| | | { |
| | | .timeout = 0xFFFFU, |
| | | .cs_high_time = 0xFU, |
| | | .dual_mode = false, |
| | | .prefetch_dis = false, |
| | | .cache_prefetch_dis = false, |
| | | .feedback_clk_sel = false, |
| | | .spi_sck_high = false, |
| | | .spi_falling_edge_active = true, |
| | | .dma_en = false, |
| | | .int_en = false, |
| | | .start_addr = FLASH_BASE, |
| | | .total_size = FLASH_SIZE, |
| | | .block_size = FLASH_BLOCK_SIZE, |
| | | .sector_size = FLASH_SECTOR_SIZE, |
| | | .page_size = FLASH_PAGE_SIZE, |
| | | }, |
| | | .callback = NULL, |
| | | .flash_type = 0, |
| | | .wrsr_type = 0, // MXIC automotive flash type need set to 1 |
| | |
| | | .is_open = 0, |
| | | #else |
| | | .is_open = 1, // Flash has been opened by default in XIP mode |
| | | .state = FLASH_STATE_READY, |
| | | #endif |
| | | }, |
| | | }; |
| | | |
| | | #if defined(XIP_EN) |
| | | extern struct FLASH_CMD_T flash_cmd[FLASH_MAX_NUM][FLASH_OPCODE_NUM]; |
| | | struct FLASH_CMD_T flash_cmd[FLASH_MAX_NUM][FLASH_OPCODE_NUM] = { |
| | | { |
| | | // QUAD |
| | | //{false, FLASH_DATA_IN, FLASH_CMD_DATA_QUAD_DUAL, FLASH_CMD_OP_ADDR_3B, FLASH_SECTOR_SIZE, 1, 0x6B}, |
| | | {false, FLASH_DATA_IN, FLASH_CMD_OP_SERIAL, FLASH_CMD_OP_ADDR_3B, FLASH_SECTOR_SIZE, 3, 0xEB}, |
| | | {false, FLASH_DATA_OUT, FLASH_CMD_DATA_QUAD_DUAL, FLASH_CMD_OP_ADDR_3B, FLASH_PAGE_SIZE, 0, 0x32}, |
| | | // DUAL |
| | | //{false, FLASH_DATA_IN, FLASH_CMD_DATA_QUAD_DUAL, FLASH_CMD_OP_ADDR_3B, FLASH_SECTOR_SIZE, 1, 0x3B}, |
| | | //{false, FLASH_DATA_IN, FLASH_CMD_OP_SERIAL, FLASH_CMD_OP_ADDR_3B, FLASH_SECTOR_SIZE, 1, 0xBB}, |
| | | //{false, FLASH_DATA_OUT, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ADDR_3B, FLASH_PAGE_SIZE, 0, 0x02}, |
| | | // STD |
| | | //{false, FLASH_DATA_IN, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ADDR_3B, FLASH_SECTOR_SIZE, 0, 0x03}, |
| | | //{false, FLASH_DATA_OUT, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ADDR_3B, FLASH_PAGE_SIZE, 0, 0x02}, |
| | | {false, FLASH_DATA_IN, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ONLY, 1, 0, 0x05}, |
| | | {false, FLASH_DATA_IN, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ONLY, 1, 0, 0x35}, |
| | | {false, FLASH_DATA_OUT, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ADDR_3B, 0, 0, 0x20}, |
| | | {false, FLASH_DATA_OUT, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ADDR_3B, 0, 0, 0xD8}, |
| | | {false, FLASH_DATA_OUT, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ONLY, 0, 0, 0x06}, |
| | | {false, FLASH_DATA_OUT, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ONLY, 2, 0, 0x01}, |
| | | {false, FLASH_DATA_IN, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ONLY, 3, 0, 0x9F}, |
| | | {false, FLASH_DATA_OUT, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ONLY, 0, 0, 0xB9}, // Deep power down |
| | | {false, FLASH_DATA_OUT, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ONLY, 0, 0, 0xAB}, // Release from Deep power down |
| | | }, |
| | | }; |
| | | #else |
| | | static const struct FLASH_CMD_T flash_cmd[FLASH_MAX_NUM][FLASH_OPCODE_NUM] = { |
| | | { |
| | | // QUAD |
| | |
| | | {false, FLASH_DATA_OUT, FLASH_CMD_ALL_SERIAL, FLASH_CMD_OP_ONLY, 0, 0, 0xAB}, // Release from Deep power down |
| | | }, |
| | | }; |
| | | #endif |
| | | |
| | | static void flash_wait_status(enum FLASH_DEV_T id, uint32_t mask, uint32_t status) |
| | | static void RAM_FUNC flash_wait_status(enum FLASH_DEV_T id, uint32_t mask, uint32_t status) |
| | | { |
| | | uint32_t start = sys_timer_get(); |
| | | while ((flash_handle[id].base->STATUS & mask) == status) |
| | |
| | | } |
| | | } |
| | | |
| | | static void flash_reset_cmd(enum FLASH_DEV_T id) |
| | | static void RAM_FUNC flash_reset_cmd(enum FLASH_DEV_T id) |
| | | { |
| | | flash_handle[id].base->STATUS = FLASH_STATUS_RESET_MSK; |
| | | /* Wait for the RESET flag cleared by HW */ |
| | | flash_wait_status(id, FLASH_STATUS_RESET_MSK, FLASH_STATUS_RESET_MSK); |
| | | } |
| | | |
| | | static void flash_write_cmd(enum FLASH_DEV_T id, enum FLASH_OPCODE_T opcode) |
| | | static void RAM_FUNC flash_write_cmd(enum FLASH_DEV_T id, enum FLASH_OPCODE_T opcode) |
| | | { |
| | | /* Wait for the CMD and MCINT flag all be 0 */ |
| | | flash_wait_status(id, FLASH_STATUS_MCINIT_MSK, FLASH_STATUS_MCINIT_MSK); |
| | |
| | | } |
| | | |
| | | #if FLASH_WRITE_EN |
| | | static void flash_write_variable_len_cmd(enum FLASH_DEV_T id, const uint32_t len) |
| | | static void RAM_FUNC flash_write_variable_len_cmd(enum FLASH_DEV_T id, const uint32_t len) |
| | | { |
| | | /* Wait for the CMD and MCINT flag all be 0 */ |
| | | flash_wait_status(id, FLASH_STATUS_MCINIT_MSK, FLASH_STATUS_MCINIT_MSK); |
| | |
| | | } |
| | | #endif |
| | | |
| | | static void flash_write_mem_cmd(enum FLASH_DEV_T id, enum FLASH_OPCODE_T opcode) |
| | | static void RAM_FUNC flash_write_mem_cmd(enum FLASH_DEV_T id, enum FLASH_OPCODE_T opcode) |
| | | { |
| | | /* Wait for the CMD and MCINT flag all be 0 */ |
| | | flash_wait_status(id, FLASH_STATUS_MCINIT_MSK, FLASH_STATUS_MCINIT_MSK); |
| | |
| | | FLASH_MCMD_OPCODE(flash_cmd[id][opcode].opcode); |
| | | } |
| | | |
| | | static uint8_t flash_read_status(enum FLASH_DEV_T id) |
| | | static uint8_t RAM_FUNC flash_read_status(enum FLASH_DEV_T id) |
| | | { |
| | | flash_write_cmd(id, FLASH_OPCODE_GET_STATUS); |
| | | flash_wait_status(id, FLASH_STATUS_INTRQ_MSK, 0U); |
| | |
| | | return (val1); |
| | | } |
| | | |
| | | static void flash_wait_done(enum FLASH_DEV_T id, uint32_t timeout) |
| | | static void RAM_FUNC flash_wait_done(enum FLASH_DEV_T id, uint32_t timeout) |
| | | { |
| | | uint32_t start = sys_timer_get(); |
| | | /* Check WIP bit */ |
| | |
| | | } |
| | | } |
| | | |
| | | static void flash_write_quad_mode(enum FLASH_DEV_T id, uint8_t qe_bit) |
| | | static uint32_t flash_id_read(enum FLASH_DEV_T id) |
| | | { |
| | | uint32_t jedec_id = 0; |
| | | |
| | | flash_write_cmd(id, FLASH_OPCODE_RDID); |
| | | flash_wait_status(id, FLASH_STATUS_INTRQ_MSK, 0U); |
| | | |
| | | jedec_id = flash_handle[id].base->DATA; |
| | | jedec_id = (jedec_id << 8) + flash_handle[id].base->DATA; |
| | | jedec_id = (jedec_id << 8) + flash_handle[id].base->DATA; |
| | | |
| | | // LOG_INFO(TRACE_MODULE_DRIVER, "jedec_id %x\r\n", jedec_id); |
| | | return jedec_id; |
| | | } |
| | | |
| | | static void flash_write_quad_mode(enum FLASH_DEV_T id, uint8_t flash_type) |
| | | { |
| | | uint8_t qe_bit = 0; |
| | | uint8_t s15_s8 = 0; |
| | | |
| | | if (flash_type == 0) |
| | | { |
| | | // Check CMP/DC/QE/SRP1 bits(all non-volatile) |
| | | s15_s8 = flash_read_status1(id); |
| | | qe_bit = (s15_s8 & QE_MASK) ? 1 : 0; |
| | | |
| | | // write quad mode if needed |
| | | if (((flash_handle[id].config.dual_mode == false) && (qe_bit == 0)) || ((flash_handle[id].config.dual_mode == true) && (qe_bit == 1))) |
| | | { |
| | | qe_bit = !qe_bit; |
| | | } |
| | | else if ((s15_s8 & (CMP_MASK | DC_MASK | SRP1_MASK)) != 0) |
| | | { |
| | | } |
| | | else |
| | | { |
| | | return; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // write quad mode anyway |
| | | qe_bit = !flash_handle[id].config.dual_mode; |
| | | } |
| | | |
| | | // Write enable |
| | | flash_write_cmd(id, FLASH_OPCODE_WRITE_ENABLE); |
| | | |
| | |
| | | flash_write_cmd(id, FLASH_OPCODE_WRITE_REGISTER); |
| | | |
| | | // Enable Quad mode |
| | | if (flash_handle[id].flash_type == 1) |
| | | if (flash_type == 1) |
| | | { |
| | | flash_handle[id].base->DATA = qe_bit ? 0x40 : 0x00; |
| | | flash_handle[id].base->DATA = 0x00; |
| | |
| | | // update state |
| | | switch (flash_handle[id].state) |
| | | { |
| | | case FLASH_STATE_READY: |
| | | flash_handle[id].state = new_state; |
| | | break; |
| | | case FLASH_STATE_BUSY_READ: |
| | | case FLASH_STATE_BUSY_ERASE: |
| | | case FLASH_STATE_BUSY_WRITE: |
| | | ret = DRV_BUSY; |
| | | break; |
| | | case FLASH_STATE_RESET: |
| | | case FLASH_STATE_TIMEOUT: |
| | | case FLASH_STATE_ERROR: |
| | | ret = DRV_ERROR; |
| | | break; |
| | | case FLASH_STATE_READY: |
| | | flash_handle[id].state = new_state; |
| | | break; |
| | | case FLASH_STATE_BUSY_READ: |
| | | case FLASH_STATE_BUSY_ERASE: |
| | | case FLASH_STATE_BUSY_WRITE: |
| | | ret = DRV_BUSY; |
| | | break; |
| | | case FLASH_STATE_RESET: |
| | | case FLASH_STATE_TIMEOUT: |
| | | case FLASH_STATE_ERROR: |
| | | ret = DRV_ERROR; |
| | | break; |
| | | } |
| | | int_unlock(lock); |
| | | |
| | |
| | | flash_write_cmd(id, FLASH_OPCODE_RELEASE_POWER_DOWN); |
| | | delay_us(50); |
| | | |
| | | // Read Identification |
| | | uint32_t jedec_id = 0; |
| | | flash_write_cmd(id, FLASH_OPCODE_RDID); |
| | | flash_wait_status(id, FLASH_STATUS_INTRQ_MSK, 0U); |
| | | |
| | | jedec_id = flash_handle[id].base->DATA; |
| | | if (jedec_id == 0xC2) |
| | | // Update flash type |
| | | uint32_t jedec_id = flash_id_read(id); |
| | | if ((jedec_id & 0x00FF0000) == 0x00C20000) |
| | | { |
| | | flash_handle[id].flash_type = 1; |
| | | } |
| | |
| | | { |
| | | flash_handle[id].flash_type = 0; |
| | | } |
| | | jedec_id = (jedec_id << 8) + flash_handle[id].base->DATA; |
| | | jedec_id = (jedec_id << 8) + flash_handle[id].base->DATA; |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "jedec_id %x\r\n", jedec_id); |
| | | |
| | | // Check Quad enable bit, its a non-volatile bit |
| | | uint8_t qe_bit = 0; |
| | | if (flash_handle[id].flash_type == 1) |
| | | { |
| | | // write quad mode anyway |
| | | flash_write_quad_mode(id, !flash_handle[id].config.dual_mode); |
| | | } |
| | | else |
| | | { |
| | | qe_bit = (flash_read_status1(id) >> 1) & 0x1; |
| | | |
| | | // write quad mode if needed |
| | | if (((flash_handle[id].config.dual_mode == false) && (qe_bit == 0)) || ((flash_handle[id].config.dual_mode == true) && (qe_bit == 1))) |
| | | { |
| | | flash_write_quad_mode(id, !qe_bit); |
| | | } |
| | | } |
| | | // Set quad mode based on flash type |
| | | flash_write_quad_mode(id, flash_handle[id].flash_type); |
| | | |
| | | if (flash_handle[id].promote_fclk == 1) |
| | | { |
| | |
| | | FLASH_CMD_FIELDFORM(FLASH_CMD_ALL_SERIAL) | FLASH_CMD_FRAMEFORM(FLASH_CMD_OP_ONLY) | FLASH_CMD_OPCODE(0xAB); |
| | | |
| | | delay_us(30); |
| | | // flash_write_cmd(id, FLASH_OPCODE_RELEASE_POWER_DOWN); |
| | | |
| | | #if BOR_EN |
| | | // enable BOR |
| | | SYSCON->BOD_BOR |= SYSCON_BOR_EN_MSK; |
| | | #endif |
| | | } |
| | | } |
| | | |
| | |
| | | flash_handle[id].base->CMD = FLASH_CMD_DATALEN(0) | FLASH_CMD_POLL(false) | FLASH_CMD_DOUT(FLASH_DATA_OUT) | FLASH_CMD_INTLEN(0) | |
| | | FLASH_CMD_FIELDFORM(FLASH_CMD_ALL_SERIAL) | FLASH_CMD_FRAMEFORM(FLASH_CMD_OP_ONLY) | FLASH_CMD_OPCODE(0xB9); |
| | | |
| | | // flash_write_cmd(id, FLASH_OPCODE_POWER_DOWN); |
| | | delay_us(15); |
| | | |
| | | #if BOR_EN |
| | | // disable BOR |
| | | SYSCON->BOD_BOR &= ~SYSCON_BOR_EN_MSK; |
| | | #endif |
| | | } |
| | | } |
| | | |
| | |
| | | #endif |
| | | |
| | | #if FLASH_WRITE_EN |
| | | static int flash_page_write_nbytes(enum FLASH_DEV_T id, uint32_t addr, const uint8_t *buf, uint32_t len) |
| | | static int RAM_FUNC flash_page_write_nbytes(enum FLASH_DEV_T id, uint32_t addr, const uint8_t *buf, uint32_t len) |
| | | { |
| | | // Write enable |
| | | flash_write_cmd(id, FLASH_OPCODE_WRITE_ENABLE); |
| | |
| | | return DRV_OK; |
| | | } |
| | | |
| | | static int flash_page_write(enum FLASH_DEV_T id, uint32_t page, const uint8_t *buf) |
| | | static int RAM_FUNC flash_page_write(enum FLASH_DEV_T id, uint32_t page, const uint8_t *buf) |
| | | { |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "flash_page_write %d\r\n", page); |
| | | // LOG_INFO(TRACE_MODULE_DRIVER, "flash_page_write %d\r\n", page); |
| | | |
| | | // Write enable |
| | | flash_write_cmd(id, FLASH_OPCODE_WRITE_ENABLE); |
| | |
| | | { |
| | | return ret; |
| | | } |
| | | |
| | | #if defined(XIP_EN) |
| | | uint32_t lock = int_lock(); |
| | | #endif |
| | | |
| | | // Reset the flash controller to switch to command mode |
| | | flash_reset_cmd(id); |
| | |
| | | flash_handle[id].state = FLASH_STATE_READY; |
| | | } |
| | | |
| | | #if defined(XIP_EN) |
| | | int_unlock(lock); |
| | | #endif |
| | | |
| | | return DRV_OK; |
| | | } |
| | | |
| | |
| | | { |
| | | return ret; |
| | | } |
| | | |
| | | #if defined(XIP_EN) |
| | | uint32_t lock = int_lock(); |
| | | #endif |
| | | |
| | | // Reset the flash controller to switch to command mode |
| | | flash_reset_cmd(id); |
| | |
| | | // update state |
| | | flash_handle[id].state = FLASH_STATE_READY; |
| | | } |
| | | |
| | | #if defined(XIP_EN) |
| | | int_unlock(lock); |
| | | #endif |
| | | |
| | | return DRV_OK; |
| | | } |
| | | |
| | |
| | | |
| | | flash_init_write_nbytes_cfg(id, start_addr, buf, len); |
| | | |
| | | #if defined(XIP_EN) |
| | | uint32_t lock = int_lock(); |
| | | #endif |
| | | |
| | | // Reset the flash controller to switch to command mode |
| | | flash_reset_cmd(id); |
| | | if (flash_handle[id].config.dma_en) |
| | |
| | | else |
| | | { |
| | | for (flash_handle[id].wr_nbyte_cfg.write_count = 0x01U; flash_handle[id].wr_nbyte_cfg.write_count <= flash_handle[id].wr_nbyte_cfg.write_num; |
| | | flash_handle[id].wr_nbyte_cfg.write_count++) |
| | | flash_handle[id].wr_nbyte_cfg.write_count++) |
| | | { |
| | | switch (flash_handle[id].wr_nbyte_cfg.page_count) |
| | | { |
| | | case WRITE_ONE_PAGES: |
| | | flash_page_write_nbytes(id, flash_handle[id].wr_nbyte_cfg.dest_tmp_addr, &buf[flash_handle[id].wr_nbyte_cfg.src_buf_pos], |
| | | flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len); |
| | | break; |
| | | |
| | | case WRITE_TWO_PAGES: |
| | | if (0x01U == flash_handle[id].wr_nbyte_cfg.write_count) |
| | | { |
| | | case WRITE_ONE_PAGES: |
| | | flash_page_write_nbytes(id, flash_handle[id].wr_nbyte_cfg.dest_tmp_addr, &buf[flash_handle[id].wr_nbyte_cfg.src_buf_pos], |
| | | flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len); |
| | | flash_handle[id].wr_nbyte_cfg.dest_tmp_addr += flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len; |
| | | flash_handle[id].wr_nbyte_cfg.src_buf_pos += flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len; |
| | | } |
| | | else if (flash_handle[id].wr_nbyte_cfg.write_count == flash_handle[id].wr_nbyte_cfg.write_num) |
| | | { |
| | | flash_page_write_nbytes(id, flash_handle[id].wr_nbyte_cfg.dest_tmp_addr, &buf[flash_handle[id].wr_nbyte_cfg.src_buf_pos], |
| | | flash_handle[id].wr_nbyte_cfg.end_page_inc_data_len); |
| | | } |
| | | break; |
| | | break; |
| | | |
| | | default: |
| | | if (0x01U == flash_handle[id].wr_nbyte_cfg.write_count) |
| | | { |
| | | flash_page_write_nbytes(id, flash_handle[id].wr_nbyte_cfg.dest_tmp_addr, &buf[flash_handle[id].wr_nbyte_cfg.src_buf_pos], |
| | | flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len); |
| | | flash_handle[id].wr_nbyte_cfg.dest_tmp_addr += flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len; |
| | | flash_handle[id].wr_nbyte_cfg.src_buf_pos += flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len; |
| | | } |
| | | else if (flash_handle[id].wr_nbyte_cfg.write_count == flash_handle[id].wr_nbyte_cfg.write_num) |
| | | { |
| | | flash_page_write_nbytes(id, flash_handle[id].wr_nbyte_cfg.dest_tmp_addr, &buf[flash_handle[id].wr_nbyte_cfg.src_buf_pos], |
| | | flash_handle[id].wr_nbyte_cfg.end_page_inc_data_len); |
| | | } |
| | | else |
| | | { |
| | | flash_page_write_nbytes(id, flash_handle[id].wr_nbyte_cfg.dest_tmp_addr, &buf[flash_handle[id].wr_nbyte_cfg.src_buf_pos], |
| | | flash_handle[id].config.page_size); |
| | | flash_handle[id].wr_nbyte_cfg.dest_tmp_addr += flash_handle[id].config.page_size; |
| | | flash_handle[id].wr_nbyte_cfg.src_buf_pos += flash_handle[id].config.page_size; |
| | | } |
| | | break; |
| | | case WRITE_TWO_PAGES: |
| | | if (0x01U == flash_handle[id].wr_nbyte_cfg.write_count) |
| | | { |
| | | flash_page_write_nbytes(id, flash_handle[id].wr_nbyte_cfg.dest_tmp_addr, &buf[flash_handle[id].wr_nbyte_cfg.src_buf_pos], |
| | | flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len); |
| | | flash_handle[id].wr_nbyte_cfg.dest_tmp_addr += flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len; |
| | | flash_handle[id].wr_nbyte_cfg.src_buf_pos += flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len; |
| | | } |
| | | else if (flash_handle[id].wr_nbyte_cfg.write_count == flash_handle[id].wr_nbyte_cfg.write_num) |
| | | { |
| | | flash_page_write_nbytes(id, flash_handle[id].wr_nbyte_cfg.dest_tmp_addr, &buf[flash_handle[id].wr_nbyte_cfg.src_buf_pos], |
| | | flash_handle[id].wr_nbyte_cfg.end_page_inc_data_len); |
| | | } |
| | | break; |
| | | |
| | | default: |
| | | if (0x01U == flash_handle[id].wr_nbyte_cfg.write_count) |
| | | { |
| | | flash_page_write_nbytes(id, flash_handle[id].wr_nbyte_cfg.dest_tmp_addr, &buf[flash_handle[id].wr_nbyte_cfg.src_buf_pos], |
| | | flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len); |
| | | flash_handle[id].wr_nbyte_cfg.dest_tmp_addr += flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len; |
| | | flash_handle[id].wr_nbyte_cfg.src_buf_pos += flash_handle[id].wr_nbyte_cfg.start_page_inc_data_len; |
| | | } |
| | | else if (flash_handle[id].wr_nbyte_cfg.write_count == flash_handle[id].wr_nbyte_cfg.write_num) |
| | | { |
| | | flash_page_write_nbytes(id, flash_handle[id].wr_nbyte_cfg.dest_tmp_addr, &buf[flash_handle[id].wr_nbyte_cfg.src_buf_pos], |
| | | flash_handle[id].wr_nbyte_cfg.end_page_inc_data_len); |
| | | } |
| | | else |
| | | { |
| | | flash_page_write_nbytes(id, flash_handle[id].wr_nbyte_cfg.dest_tmp_addr, &buf[flash_handle[id].wr_nbyte_cfg.src_buf_pos], |
| | | flash_handle[id].config.page_size); |
| | | flash_handle[id].wr_nbyte_cfg.dest_tmp_addr += flash_handle[id].config.page_size; |
| | | flash_handle[id].wr_nbyte_cfg.src_buf_pos += flash_handle[id].config.page_size; |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | |
| | |
| | | // update state |
| | | flash_handle[id].state = FLASH_STATE_READY; |
| | | } |
| | | |
| | | #if defined(XIP_EN) |
| | | int_unlock(lock); |
| | | #endif |
| | | |
| | | return DRV_OK; |
| | | } |
| | |
| | | uint32_t offset_addr = start_addr - flash_handle[id].config.start_addr; |
| | | uint32_t page_start = offset_addr / flash_handle[id].config.page_size; |
| | | uint32_t page_end = (offset_addr + len) / flash_handle[id].config.page_size; |
| | | |
| | | #if defined(XIP_EN) |
| | | uint32_t lock = int_lock(); |
| | | #endif |
| | | |
| | | // Reset the flash controller to switch to command mode |
| | | flash_reset_cmd(id); |
| | |
| | | // update state |
| | | flash_handle[id].state = FLASH_STATE_READY; |
| | | } |
| | | |
| | | #if defined(XIP_EN) |
| | | int_unlock(lock); |
| | | #endif |
| | | |
| | | return DRV_OK; |
| | | } |
| | | #else |
| | |
| | | return ret; |
| | | } |
| | | |
| | | #ifndef XIP_EN |
| | | // Reset the flash controller to switch to command mode |
| | | flash_reset_cmd(id); |
| | | |
| | |
| | | // update state |
| | | flash_handle[id].state = FLASH_STATE_READY; |
| | | } |
| | | |
| | | #else |
| | | memcpy(buf, (uint8_t *)(start_addr), len); |
| | | // update state |
| | | flash_handle[id].state = FLASH_STATE_READY; |
| | | #endif |
| | | return DRV_OK; |
| | | } |
| | | |
| | |
| | | // wait until the flash writing operation is complete |
| | | delay_us(350); |
| | | if ((flash_handle[id].wr_nbyte_cfg.write_count == flash_handle[id].wr_nbyte_cfg.write_num) && |
| | | (flash_handle[id].wr_nbyte_cfg.write_count > 0x01U)) |
| | | (flash_handle[id].wr_nbyte_cfg.write_count > 0x01U)) |
| | | { |
| | | flash_handle[id].wr_nbyte_cfg.src_buf_pos += flash_handle[id].config.page_size; |
| | | // Write enable |