| | |
| | | .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 */ |
| | |
| | | // 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); |
| | | |
| | |
| | | #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 |