WXK
2025-02-11 e328ebef585cea2351b37117b2d5ac4978ecd3c0
keil/include/drivers/mk_flash.c
@@ -56,23 +56,23 @@
        .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
@@ -82,10 +82,38 @@
        .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
@@ -110,8 +138,9 @@
        {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)
@@ -123,14 +152,14 @@
    }
}
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);
@@ -165,7 +194,7 @@
}
#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);
@@ -192,7 +221,7 @@
}
#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);
@@ -203,7 +232,7 @@
                                  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);
@@ -219,7 +248,7 @@
    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 */
@@ -269,19 +298,19 @@
    // 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);
@@ -505,7 +534,7 @@
#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);
@@ -526,9 +555,9 @@
    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);
@@ -559,6 +588,10 @@
    {
        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);
@@ -596,6 +629,10 @@
        flash_handle[id].state = FLASH_STATE_READY;
    }
#if defined(XIP_EN)
    int_unlock(lock);
#endif
    return DRV_OK;
}
@@ -609,6 +646,10 @@
    {
        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);
@@ -645,6 +686,11 @@
        // update state
        flash_handle[id].state = FLASH_STATE_READY;
    }
#if defined(XIP_EN)
    int_unlock(lock);
#endif
    return DRV_OK;
}
@@ -764,6 +810,10 @@
    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)
@@ -812,51 +862,51 @@
    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;
            }
        }
@@ -866,6 +916,10 @@
        // update state
        flash_handle[id].state = FLASH_STATE_READY;
    }
#if defined(XIP_EN)
    int_unlock(lock);
#endif
    return DRV_OK;
}
@@ -892,6 +946,10 @@
    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);
@@ -946,6 +1004,11 @@
        // update state
        flash_handle[id].state = FLASH_STATE_READY;
    }
#if defined(XIP_EN)
    int_unlock(lock);
#endif
    return DRV_OK;
}
#else
@@ -976,6 +1039,7 @@
        return ret;
    }
#ifndef XIP_EN
    // Reset the flash controller to switch to command mode
    flash_reset_cmd(id);
@@ -1069,7 +1133,11 @@
        // 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;
}
@@ -1099,7 +1167,7 @@
                // 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