739 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			739 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************************
 | 
						|
 | 
						|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
 | 
						|
 | 
						|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
 | 
						|
be copied by any method or incorporated into another program without
 | 
						|
the express written consent of Aerospace C.Power. This Information or any portion
 | 
						|
thereof remains the property of Aerospace C.Power. The Information contained herein
 | 
						|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
 | 
						|
liability for its use in any way and conveys no license or title under
 | 
						|
any patent or copyright and makes no representation or warranty that this
 | 
						|
Information is free from patent or copyright infringement.
 | 
						|
 | 
						|
****************************************************************************/
 | 
						|
#include "hw_reg_api.h"
 | 
						|
#include "chip_reg_base.h"
 | 
						|
#include "apb_cache_reg.h"
 | 
						|
 | 
						|
#include "ahb.h"
 | 
						|
#include "smc.h"
 | 
						|
#include "sram.h"
 | 
						|
#include "sfc.h"
 | 
						|
#include "sfc_rf.h"
 | 
						|
#include "flash.h"
 | 
						|
#include "gp_timer.h"
 | 
						|
#include "uart.h"
 | 
						|
 | 
						|
#include "iot_system.h"
 | 
						|
#include "dbg_io.h"
 | 
						|
#include "iot_clock.h"
 | 
						|
 | 
						|
#include "iot_io_api.h"
 | 
						|
#include "iot_errno_api.h"
 | 
						|
 | 
						|
#include "dtest_printf.h"
 | 
						|
 | 
						|
#define DTEST_CACHE_RAM_CASE_RAM_FULL_RW        (1 << 0)
 | 
						|
#define DTEST_CACHE_RAM_CASE_CACHE_READ_EM      (1 << 1)
 | 
						|
#define DTEST_CACHE_RAM_CASE_CACHE_AS_RAM       (1 << 2)
 | 
						|
#define DTEST_CACHE_RAM_CASE_CACHE_DIRTY_MISS   (1 << 3)
 | 
						|
#define DTEST_CACHE_RAM_CASE_CACHE_LINE         (1 << 4)
 | 
						|
#define DTEST_CACHE_RAM_CASE_CACHE_ADDR_PROTECT (1 << 5)
 | 
						|
#define DTEST_CACHE_RAM_CASE_SFC_SMC_IO_SHARE   (1 << 6)
 | 
						|
#define DTEST_CACHE_RAM_CASE_SFC_SMC_IO_REMAP   (1 << 7)
 | 
						|
 | 
						|
#define DTEST_CACHE_RAM_RAM_SIZE                0x70000    //448kb
 | 
						|
 | 
						|
#define TEST_MEMORY_LENGTH(m)   (m##_ENDADDR - m##_BASEADDR + 1)
 | 
						|
#define ARRAY_SIZE(a)           (sizeof(a) / sizeof(a[0]))
 | 
						|
 | 
						|
typedef struct test_mem_block {
 | 
						|
    uint32_t start;
 | 
						|
    uint32_t length;
 | 
						|
} test_mem_block_t;
 | 
						|
 | 
						|
test_mem_block_t test_mem_table[] = {
 | 
						|
    {ICACHE0_SMC_RAM_BASEADDR, TEST_MEMORY_LENGTH(ICACHE0_SMC_RAM)},
 | 
						|
    {ICACHE1_SMC_RAM_BASEADDR, TEST_MEMORY_LENGTH(ICACHE1_SMC_RAM)},
 | 
						|
    {ICACHE2_SMC_RAM_BASEADDR, TEST_MEMORY_LENGTH(ICACHE2_SMC_RAM)},
 | 
						|
    {DCACHE0_SMC_RAM_BASEADDR, TEST_MEMORY_LENGTH(DCACHE0_SMC_RAM)},
 | 
						|
    {DCACHE1_SMC_RAM_BASEADDR, TEST_MEMORY_LENGTH(DCACHE1_SMC_RAM)},
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief: Test the data bus wiring in a memory region by
 | 
						|
 *         performing a walking 1's test at a fixed address
 | 
						|
 *         within that region.  The address (and hence the
 | 
						|
 *         memory region) is selected by the caller.
 | 
						|
 *
 | 
						|
 * @return: 0 if the test succeeds.
 | 
						|
 *          A non-zero result is the first pattern that failed.
 | 
						|
 */
 | 
						|
static bool_t test_mem_data_bus(uint32_t addr)
 | 
						|
{
 | 
						|
    /* Perform a walking 1's test at the given address */
 | 
						|
    for (uint8_t pattern = 1; pattern != 0; pattern <<= 1) {
 | 
						|
        /*  Write the test pattern */
 | 
						|
        *(volatile uint8_t *)addr = pattern;
 | 
						|
        /* Read it back (immediately is okay for this test) */
 | 
						|
        if (*(volatile uint8_t *)addr != pattern) {
 | 
						|
            dprintf("[MEM_CHECK] data bus check fail, addr:0x%08x\n", addr);
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief: Test the address bus wiring in a memory region by
 | 
						|
 *         performing a walking 1's test on the relevant bits
 | 
						|
 *         of the address and checking for aliasing. This test
 | 
						|
 *         will find single-bit address failures such as stuck
 | 
						|
 *         -high, stuck-low, and shorted pins.  The base address
 | 
						|
 *         and size of the region are selected by the caller.
 | 
						|
 *
 | 
						|
 * Notes:  For best results, the selected base address should
 | 
						|
 *         have enough LSB 0's to guarantee single address bit
 | 
						|
 *         changes.  For example, to test a 64-Kbyte region,
 | 
						|
 *         select a base address on a 64-Kbyte boundary.  Also,
 | 
						|
 *         select the region size as a power-of-two--if at all
 | 
						|
 *         possible.
 | 
						|
 *
 | 
						|
 * Returns: NULL if the test succeeds.
 | 
						|
 *          A non-zero result is the first address at which an
 | 
						|
 *          aliasing problem was uncovered.  By examining the
 | 
						|
 *          contents of memory, it may be possible to gather
 | 
						|
 *          additional information about the problem.
 | 
						|
 */
 | 
						|
static bool_t test_mem_addr_bus(uint32_t addr, uint32_t length)
 | 
						|
{
 | 
						|
    uint32_t addr_mask = (length / sizeof(uint32_t) - 1);
 | 
						|
    uint32_t test_offset;
 | 
						|
    uint32_t pattern = 0xAA;
 | 
						|
    uint32_t antipattern = 0x55;
 | 
						|
 | 
						|
    /*  Write the default pattern at each of the power-of-two offsets */
 | 
						|
    for (uint32_t offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
 | 
						|
        *(volatile uint8_t *)(addr + offset) = pattern;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Check for address bits stuck high. */
 | 
						|
    test_offset = 0;
 | 
						|
    *(volatile uint8_t *)(addr + test_offset) = antipattern;
 | 
						|
    for (uint32_t offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
 | 
						|
        if (*(volatile uint8_t *)(addr + offset) != pattern) {
 | 
						|
            dprintf("[MEM_CHECK] addr bus check fail, addr:0x%08x\n",
 | 
						|
                        addr + offset);
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    *(volatile uint8_t *)(addr + test_offset) = pattern;
 | 
						|
 | 
						|
    /* Check for address bits stuck low or shorted */
 | 
						|
    for (test_offset = 1; (test_offset & addr_mask) != 0; test_offset <<= 1) {
 | 
						|
        *(volatile uint8_t *)(addr + test_offset) = antipattern;
 | 
						|
        if (*(volatile uint8_t *)addr != pattern) {
 | 
						|
            dprintf("[MEM_CHECK] addr bus check fail, addr:0x%08x\n",
 | 
						|
                addr + test_offset);
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        for (uint32_t offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
 | 
						|
            if ((*(volatile uint8_t *)(addr + offset) != pattern)
 | 
						|
                && (offset != test_offset)) {
 | 
						|
                dprintf("[MEM_CHECK] addr bus check fail, addr:0x%08x\n",
 | 
						|
                    addr + test_offset);
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        *(volatile uint8_t *)(addr + test_offset) = pattern;
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief: Test the integrity of a physical memory device by
 | 
						|
 *         performing an increment/decrement test over the
 | 
						|
 *         entire region.  In the process every storage bit
 | 
						|
 *         in the device is tested as a zero and a one.  The
 | 
						|
 *         base address and the size of the region are
 | 
						|
 *         selected by the caller.
 | 
						|
 *
 | 
						|
 * Returns: NULL if the test succeeds.  Also, in that case, the
 | 
						|
 *          entire memory region will be filled with zeros.
 | 
						|
 *
 | 
						|
 *          A non-zero result is the first address at which an
 | 
						|
 *          incorrect value was read back.  By examining the
 | 
						|
 *          contents of memory, it may be possible to gather
 | 
						|
 *          additional information about the problem.
 | 
						|
 */
 | 
						|
static bool_t test_mem_device(uint32_t addr, uint32_t length)
 | 
						|
{
 | 
						|
    uint32_t offset;
 | 
						|
    uint32_t word_len = length / sizeof(uint32_t);
 | 
						|
    uint32_t pattern;
 | 
						|
    uint32_t antipattern;
 | 
						|
    uint32_t *base_addr = (uint32_t *)addr;
 | 
						|
 | 
						|
    /* Fill memory with a known pattern */
 | 
						|
    for (pattern = 1, offset = 0; offset < word_len; pattern++, offset++) {
 | 
						|
        base_addr[offset] = pattern;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Check each location and invert it for the second pass */
 | 
						|
    for (pattern = 1, offset = 0; offset < word_len; pattern++, offset++) {
 | 
						|
        if (base_addr[offset] != pattern) {
 | 
						|
            dprintf("[MEM_CHECK] device write check fail, addr:0x%08x\n",
 | 
						|
                       addr + offset);
 | 
						|
            dprintf("[MEM_CHECK]\t write 0x%08x, read:0x%08x\n", pattern,
 | 
						|
                       base_addr[offset]);
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        antipattern = ~pattern;
 | 
						|
        base_addr[offset] = antipattern;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Check each location for the inverted pattern and zero it. */
 | 
						|
    for (pattern = 1, offset = 0; offset < word_len; pattern++, offset++) {
 | 
						|
        antipattern = ~pattern;
 | 
						|
        if (base_addr[offset] != antipattern) {
 | 
						|
            dprintf("[MEM_CHECK] device invert check fail, addr:0x%08x\n",
 | 
						|
                addr + offset);
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t dtest_cache_ram_cache_line_test()
 | 
						|
{
 | 
						|
    uint32_t i;
 | 
						|
 | 
						|
    dcase_start("cache data bus line and addr bus line\n");
 | 
						|
 | 
						|
    for (i = 0; i < ARRAY_SIZE(test_mem_table); i++) {
 | 
						|
        if (!test_mem_data_bus(test_mem_table[i].start)
 | 
						|
            || !test_mem_addr_bus(test_mem_table[i].start, test_mem_table[i].length)
 | 
						|
            || !test_mem_device(test_mem_table[i].start, test_mem_table[i].length)) {
 | 
						|
            goto fail;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    dcase_success();
 | 
						|
    return ERR_OK;
 | 
						|
fail:
 | 
						|
    dcase_failed();
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
/* there is a space reserved for ROM at the beginning of ram,
 | 
						|
 * and ram is divided into flash, IRAM and DRAM in link script
 | 
						|
 */
 | 
						|
static uint32_t dtest_cache_ram_ram_full_rw_test()
 | 
						|
{
 | 
						|
    uint32_t i, j;
 | 
						|
    uint32_t len[3], addr[3];
 | 
						|
    uint8_t data_test = 0x55, data;
 | 
						|
 | 
						|
    dcase_start("ram full read/write test(space outside code)\n");
 | 
						|
 | 
						|
    addr[0] = AHB_RAM0_BASEADDR;
 | 
						|
    len[0] = (uint32_t)&_start - AHB_RAM0_BASEADDR;
 | 
						|
    addr[1] = (uint32_t)&_flash_end;
 | 
						|
    len[1] = (uint32_t)&_data - (uint32_t)&_flash_end;
 | 
						|
    addr[2] = (uint32_t)&_iram_end;
 | 
						|
    len[2] = DTEST_CACHE_RAM_RAM_SIZE - ((uint32_t)&_iram_end - AHB_RAM0_BASEADDR);
 | 
						|
 | 
						|
    dprintf("read/write space range:\n");
 | 
						|
    for (i = 0; i < 3; i++) {
 | 
						|
        iot_printf("\tindex:%d, addr:0x%08x, len:0x%x\n", i, addr[i], len[i]);
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0; i < 3; i++) {
 | 
						|
        for (j = addr[i]; j < len[i]; j++) {
 | 
						|
            *(uint8_t *)j = data_test;
 | 
						|
        }
 | 
						|
        for (j = addr[i]; j < len[i]; j++) {
 | 
						|
            data = *(uint8_t *)j;
 | 
						|
            if (data != data_test) {
 | 
						|
                dprintf("ram read data error, addr:0x%08x, rdata:0x%x, wdata:0x%x\n",
 | 
						|
                    j, data, data_test);
 | 
						|
                goto fail;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    data_test = 0xaa;
 | 
						|
    for (i = 0; i < 3; i++) {
 | 
						|
        for (j = addr[i]; j < len[i]; j++) {
 | 
						|
            *(uint8_t *)j = data_test;
 | 
						|
        }
 | 
						|
        for (j = addr[i]; j < len[i]; j++) {
 | 
						|
            data = *(uint8_t *)j;
 | 
						|
            if (data != data_test) {
 | 
						|
                dprintf("ram read data error, addr:0x%08x, rdata:0x%x, wdata:0x%x\n",
 | 
						|
                    j, data, data_test);
 | 
						|
                goto fail;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    dcase_success();
 | 
						|
    return ERR_OK;
 | 
						|
fail:
 | 
						|
    dcase_failed();
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t dtest_cache_ram_cache_rw_ext_mem_test()
 | 
						|
{
 | 
						|
    uint8_t i;
 | 
						|
    uint32_t addr_test = 0x00;
 | 
						|
    uint32_t data_test = 0x11223344, data;
 | 
						|
 | 
						|
    dcase_start("cache read/write extern memory(flash/psram) test\n");
 | 
						|
 | 
						|
    dprintf("write extern memory, test addr:0x%08x, test data:0x%08x\n", addr_test, data_test);
 | 
						|
    *(uint32_t *)(ICACHE0_SMC_RAM_BASEADDR + addr_test) = data_test;
 | 
						|
    cache_flush(0, addr_test + ICACHE0_SMC_RAM_BASEADDR, 32);
 | 
						|
    g_sfc_ctrl->erase_sector(addr_test, MOD_SW_MODE_DIS);
 | 
						|
    g_sfc_ctrl->write((uint8_t*)&data_test, addr_test, sizeof(data_test),
 | 
						|
        MOD_SFC_PROG_STAND, MOD_SW_MODE_DIS);
 | 
						|
 | 
						|
    dprintf("read extern memory\n");
 | 
						|
    for (i = AHB_CACHE_I0; i < AHB_CACHE_MAX; i++) {
 | 
						|
//        cache_clear(i);
 | 
						|
        data = *(uint32_t *)(test_mem_table[i].start + addr_test);
 | 
						|
        if (data != data_test) {
 | 
						|
            dprintf("cache read psram error, rdata:0x%08x, wdata:0x%08x\n", data, data_test);
 | 
						|
            goto fail;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = AHB_CACHE_I0; i < AHB_CACHE_MAX; i++) {
 | 
						|
//        cache_clear(i);
 | 
						|
        data = *(uint32_t *)(test_mem_table[i].start + 0x4000000 + addr_test);
 | 
						|
        if (data != data_test) {
 | 
						|
            dprintf("cache read flash error, rdata:0x%08x, wdata:0x%08x\n", data, data_test);
 | 
						|
            goto fail;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    dcase_success();
 | 
						|
    return ERR_OK;
 | 
						|
fail:
 | 
						|
    dcase_failed();
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t dtest_cache_ram_cache_as_ram_test()
 | 
						|
{
 | 
						|
    uint32_t i, err_cnt = 0;
 | 
						|
    uint32_t offset_test = 0x00;
 | 
						|
    uint32_t data_test = 0x11223344, data;
 | 
						|
 | 
						|
    dcase_start("cache is configured for internal ram use\n");
 | 
						|
 | 
						|
    for (i = AHB_CACHE_I0; i < AHB_CACHE_MAX; i++) {
 | 
						|
        cache_disable(i);
 | 
						|
        cache_enable(i);
 | 
						|
        cache_set_buffer_mode(i, AHB_CACHE_MODE_BUFFER);
 | 
						|
        cache_space_dis(i);
 | 
						|
 | 
						|
        iot_delay_us(10);
 | 
						|
        *(uint32_t *)(test_mem_table[i].start + offset_test) = data_test;
 | 
						|
        data = *(uint32_t *)(test_mem_table[i].start + offset_test);
 | 
						|
        if (data != data_test) {
 | 
						|
            dprintf("cache as ram failed, test offset:0x%08x, rdata:0x%08x, wdata:0x%08x\n",
 | 
						|
                offset_test, data, data_test);
 | 
						|
            err_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("restore cache as cache function\n");
 | 
						|
    for (i = AHB_CACHE_I0; i < AHB_CACHE_MAX; i++) {
 | 
						|
        cache_disable(i);
 | 
						|
        cache_enable(i);
 | 
						|
        cache_set_buffer_mode(i, AHB_CACHE_MODE_CACHE);
 | 
						|
        cache_space_ena(i);
 | 
						|
    }
 | 
						|
    iot_delay_us(10);
 | 
						|
    data_test = 0xaabbccdd;
 | 
						|
    offset_test = 0x100000;
 | 
						|
    *(uint32_t *)(ICACHE0_SMC_RAM_BASEADDR + offset_test) = data_test;
 | 
						|
    cache_flush(0, offset_test, 32);
 | 
						|
    cache_clear(0);
 | 
						|
    data = *(uint32_t *)(ICACHE0_SMC_RAM_BASEADDR + offset_test);
 | 
						|
    if (data != data_test) {
 | 
						|
        dprintf("restore cache failed, test offset:0x%08x, rdata:0x%08x, wdata:0x%08x\n",
 | 
						|
            offset_test, data, data_test);
 | 
						|
        err_cnt++;
 | 
						|
    }
 | 
						|
 | 
						|
    if (err_cnt) {
 | 
						|
        dcase_failed();
 | 
						|
        return ERR_FAIL;
 | 
						|
    } else {
 | 
						|
        dcase_success();
 | 
						|
        return ERR_OK;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t dtest_cache_ram_cache_dirty_miss_test()
 | 
						|
{
 | 
						|
    uint32_t addr_test = 0x100000;
 | 
						|
    volatile uint32_t data_test = 0x12345678, data_old1, data_old2, data_new;
 | 
						|
 | 
						|
    dcase_start("cache(sfc) dirty(clear/invalidata) and miss test\n");
 | 
						|
 | 
						|
    dprintf("cache invalidata operation test\n");
 | 
						|
    g_sfc_ctrl->erase_sector(addr_test, MOD_SW_MODE_DIS);
 | 
						|
    cache_clear(0);
 | 
						|
    data_old1 = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
 | 
						|
    g_sfc_ctrl->write((uint8_t*)&data_test, addr_test, sizeof(data_test),
 | 
						|
        MOD_SFC_PROG_STAND, MOD_SW_MODE_DIS);
 | 
						|
    data_old2 = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
    cache_invalidate(0, addr_test + ICACHE0_SFC_RAM_BASEADDR, 32);
 | 
						|
    data_new = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
    dprintf("invalidata test addr:0x%08x, test data:0x%08x, data_old1:0x%08x, "
 | 
						|
        "data_old2:0x%08x, data_new:0x%08x\n", addr_test, data_test, data_old1,
 | 
						|
        data_old2, data_new);
 | 
						|
    if (data_old1 != 0xffffffff) {
 | 
						|
        dprintf("sfc erase error\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
    if (data_old1 != data_old2) {
 | 
						|
        dprintf("cache dirty data error\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
    if (data_new != data_test) {
 | 
						|
        dprintf("cache incalidata operation failed\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("cache clear operation test\n");
 | 
						|
    g_sfc_ctrl->erase_sector(addr_test, MOD_SW_MODE_DIS);
 | 
						|
    cache_clear(0);
 | 
						|
    data_old1 = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
 | 
						|
    g_sfc_ctrl->write((uint8_t*)&data_test, addr_test, sizeof(data_test),
 | 
						|
        MOD_SFC_PROG_STAND, MOD_SW_MODE_DIS);
 | 
						|
    data_old2 = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
    cache_clear(0);
 | 
						|
    data_new = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
    dprintf("clear test addr:0x%08x, test data:0x%08x, data_old1:0x%08x, "
 | 
						|
        "data_old2:0x%08x, data_new:0x%08x\n", addr_test, data_test, data_old1,
 | 
						|
        data_old2, data_new);
 | 
						|
    if (data_old1 != 0xffffffff) {
 | 
						|
        dprintf("sfc erase error\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
    if (data_old1 != data_old2) {
 | 
						|
        dprintf("cache dirty data error\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
    if (data_new != data_test) {
 | 
						|
        dprintf("cache clear operation failed\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("cache miss and auto load test\n");
 | 
						|
    g_sfc_ctrl->erase_sector(addr_test, MOD_SW_MODE_DIS);
 | 
						|
    cache_clear(0);
 | 
						|
    data_old1 = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
 | 
						|
    g_sfc_ctrl->write((uint8_t*)&data_test, addr_test, sizeof(data_test),
 | 
						|
        MOD_SFC_PROG_STAND, MOD_SW_MODE_DIS);
 | 
						|
    /* icache0 has 32KB space, continuous reading of 32KB data will fill the cache */
 | 
						|
    for (uint32_t i = 1; i <= 0x8000; i++) {
 | 
						|
        data_old2 = *(uint8_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test + i);
 | 
						|
    }
 | 
						|
    data_new = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
    dprintf("auto load test addr:0x%08x, test data:0x%08x, data_old1:0x%08x, "
 | 
						|
        "data_old2:0x%08x, data_new:0x%08x\n", addr_test, data_test, data_old1,
 | 
						|
        data_old2, data_new);
 | 
						|
    if (data_old1 != 0xffffffff) {
 | 
						|
        dprintf("sfc erase error\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
    if (data_new != data_test) {
 | 
						|
        dprintf("cache miss and auto load operation failed\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
 | 
						|
    dcase_success();
 | 
						|
    return ERR_OK;
 | 
						|
fail:
 | 
						|
    dcase_failed();
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
//extern void cache_monitor_enable(uint8_t cache_id, uint8_t en);
 | 
						|
//extern void cache_monitor_clear(uint8_t cache_id);
 | 
						|
//extern uint8_t cache_monitor_state(uint8_t cache_id);
 | 
						|
//extern void cache_monitor_set_acc_addr(uint8_t cache_id,
 | 
						|
//    uint32_t addr_s, uint32_t addr_e);
 | 
						|
//extern void cache_monitor_set_mon_addr(uint8_t cache_id,
 | 
						|
//    uint32_t addr_s, uint32_t addr_e);
 | 
						|
 | 
						|
static uint32_t dtest_cache_ram_cache_addr_protect_test()
 | 
						|
{
 | 
						|
#if 0
 | 
						|
    uint8_t i, state;
 | 
						|
    uint32_t addr_acc_s = 0x00000000, addr_acc_e = 0x00008000;
 | 
						|
    uint32_t addr_mon_s = 0x00001000, addr_mon_e = 0x00002000;
 | 
						|
 | 
						|
    dcase_start("cache address protection\n");
 | 
						|
 | 
						|
    dprintf("enable all cache addr monitor function\n");
 | 
						|
    for (i = AHB_CACHE_I0; i < AHB_CACHE_MAX; i++) {
 | 
						|
        cache_monitor_enable(i, 1);
 | 
						|
        cache_monitor_clear(i);
 | 
						|
        cache_monitor_set_acc_addr(i, addr_acc_s, addr_acc_e);
 | 
						|
        cache_monitor_set_mon_addr(i, addr_mon_s, addr_mon_e);
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("using cache to access protected addresses\n");
 | 
						|
    for (i = AHB_CACHE_I0; i < AHB_CACHE_MAX; i++) {
 | 
						|
        *(uint32_t *)(test_mem_table[i].start + addr_mon_s + 32) = 0x11223344;
 | 
						|
        cache_flush(i, addr_mon_s + 32, 32);
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("check cross-border access status\n");
 | 
						|
    for (i = AHB_CACHE_I0; i < AHB_CACHE_MAX; i++) {
 | 
						|
        state = cache_monitor_state(i);
 | 
						|
        if (!state) {
 | 
						|
            dprintf("cache:%d address out of bounds access not detected\n", i);
 | 
						|
            goto fail;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("disable all cache addr monitor function\n");
 | 
						|
    for (i = AHB_CACHE_I0; i < AHB_CACHE_MAX; i++) {
 | 
						|
        cache_monitor_clear(i);
 | 
						|
        cache_monitor_enable(i, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    dcase_success();
 | 
						|
    return ERR_OK;
 | 
						|
fail:
 | 
						|
    dcase_failed();
 | 
						|
    return ERR_FAIL;
 | 
						|
#endif
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t dtest_cache_ram_sfc_smc_io_share_test()
 | 
						|
{
 | 
						|
    uint32_t temp;
 | 
						|
    uint32_t addr_test = 0x100000;
 | 
						|
    uint32_t data, data_flash = 0x11223344, data_psram = 0xaabbccdd;
 | 
						|
 | 
						|
    dcase_start("sfc and smc io share\n");
 | 
						|
 | 
						|
    dprintf("init flash/psram data\n");
 | 
						|
    g_sfc_ctrl->erase_sector(addr_test, MOD_SW_MODE_DIS);
 | 
						|
    g_sfc_ctrl->write((uint8_t*)&data_flash, addr_test, sizeof(data_flash), MOD_SFC_PROG_STAND, MOD_SW_MODE_DIS);
 | 
						|
    cache_clear(0);
 | 
						|
    data = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
    if (data != data_flash) {
 | 
						|
        dprintf("flash write/read failed\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
    *(uint32_t *)(ICACHE0_SMC_RAM_BASEADDR + addr_test) = data_psram;
 | 
						|
    cache_flush(0, addr_test, 32);
 | 
						|
    cache_clear(0);
 | 
						|
    data = *(uint32_t *)(ICACHE0_SMC_RAM_BASEADDR + addr_test);
 | 
						|
    if (data != data_psram) {
 | 
						|
        dprintf("psram write/read failed\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("enable io share, need init flash again\n");
 | 
						|
 | 
						|
    temp = SFC_READ_REG(CFG_SFC_DBG_ADDR);
 | 
						|
    REG_FIELD_SET(SFC_SMC_IO_SHARE, temp, 1);
 | 
						|
    REG_FIELD_SET(SFC_SMC_ARB_SHARE, temp, 1);
 | 
						|
    SFC_WRITE_REG(CFG_SFC_DBG_ADDR, temp);
 | 
						|
    iot_delay_us(1000);
 | 
						|
 | 
						|
    uint8_t id[8] = {0};
 | 
						|
    sfc_qspi_get_id_mult(id, MOD_SFC_SERIAL);
 | 
						|
    dprintf("Manufacturer ID(serial):0x%x, device id:0x%x\n",id[0], id[1]);
 | 
						|
    flash_init(1);
 | 
						|
    sfc_set_endian_mode(1);
 | 
						|
 | 
						|
    dprintf("read flash/psram data again\n");
 | 
						|
    cache_clear(0);
 | 
						|
    data = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
    if (data != data_flash) {
 | 
						|
        dprintf("flash data read failed\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
    cache_clear(0);
 | 
						|
    data = *(uint32_t *)(ICACHE0_SMC_RAM_BASEADDR + addr_test);
 | 
						|
    if (data != data_psram) {
 | 
						|
        dprintf("psram data read failed\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("disable io share\n");
 | 
						|
    temp = SFC_READ_REG(CFG_SFC_DBG_ADDR);
 | 
						|
    REG_FIELD_SET(SFC_SMC_IO_SHARE, temp, 0);
 | 
						|
    REG_FIELD_SET(SFC_SMC_ARB_SHARE, temp, 0);
 | 
						|
    SFC_WRITE_REG(CFG_SFC_DBG_ADDR, temp);
 | 
						|
    iot_delay_us(1000);
 | 
						|
 | 
						|
    dprintf("read flash/psram data again\n");
 | 
						|
    cache_clear(0);
 | 
						|
    data = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
    if (data != data_flash) {
 | 
						|
        dprintf("flash data read failed\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
    cache_clear(0);
 | 
						|
    data = *(uint32_t *)(ICACHE0_SMC_RAM_BASEADDR + addr_test);
 | 
						|
    if (data != data_psram) {
 | 
						|
        dprintf("psram data read failed\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
 | 
						|
    dcase_success();
 | 
						|
    return ERR_OK;
 | 
						|
fail:
 | 
						|
    dcase_failed();
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t dtest_cache_ram_sfc_smc_io_remap_test()
 | 
						|
{
 | 
						|
    volatile uint32_t data;
 | 
						|
    /* QPI mode requires 4 address lines. Staggering 1 helps to observe the timing */
 | 
						|
    uint32_t addr_test = 0x8421;
 | 
						|
    uint32_t cnt = 1000;
 | 
						|
 | 
						|
    (void)data;
 | 
						|
    /* It is necessary to manually change the register
 | 
						|
     * and check whether the timing is correct on the logic analyzer
 | 
						|
     */
 | 
						|
    while (cnt--) {
 | 
						|
        cache_clear(0);
 | 
						|
        data = *(uint32_t *)(ICACHE0_SMC_RAM_BASEADDR + addr_test);
 | 
						|
        dprintf("get psram data:0x%08x\n");
 | 
						|
 | 
						|
        cache_clear(0);
 | 
						|
        data = *(uint32_t *)(ICACHE0_SFC_RAM_BASEADDR + addr_test);
 | 
						|
        dprintf("get flash data:0x%08x\n");
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
static void dtest_cache_ram_main()
 | 
						|
{
 | 
						|
    uint32_t case_group = 0, error_cnt = 0;
 | 
						|
 | 
						|
    dbg_uart_init();
 | 
						|
 | 
						|
    dconfig();
 | 
						|
    dstart();
 | 
						|
    dversion();
 | 
						|
 | 
						|
    if (dtest_get_case_group(&case_group) < 0) {
 | 
						|
        case_group = 0xffffffff;
 | 
						|
    }
 | 
						|
    dprintf("get case group:0x%08X\n", case_group);
 | 
						|
 | 
						|
    dprintf("init gptimer0 for delay\n");
 | 
						|
    gp_timer_init();
 | 
						|
    gp_timer_set(0, 0xffffffff, 0);
 | 
						|
    gp_timer_start(0);
 | 
						|
 | 
						|
    dprintf("reset emc\n");
 | 
						|
    ahb_emc_disable();
 | 
						|
    ahb_emc_enable();
 | 
						|
    ahb_emc_reset();
 | 
						|
 | 
						|
    dprintf("initialize psram\n");
 | 
						|
    sram_qspi_init();
 | 
						|
    sram_qspi_enter();
 | 
						|
    hal_smc_qspi_quad_cfg(0);
 | 
						|
 | 
						|
    dprintf("init sfc and flash\n");
 | 
						|
    flash_init(1);
 | 
						|
    sfc_set_endian_mode(1);
 | 
						|
 | 
						|
    dprintf("initialize all of the cache\n");
 | 
						|
    for (uint8_t i = AHB_CACHE_I0; i < AHB_CACHE_MAX; i++) {
 | 
						|
        cache_disable(i);
 | 
						|
        cache_enable(i);
 | 
						|
        cache_fill_valid_space(i);
 | 
						|
    }
 | 
						|
 | 
						|
    if (case_group & DTEST_CACHE_RAM_CASE_RAM_FULL_RW) {
 | 
						|
        if (dtest_cache_ram_ram_full_rw_test()) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (case_group & DTEST_CACHE_RAM_CASE_CACHE_READ_EM) {
 | 
						|
        if (dtest_cache_ram_cache_rw_ext_mem_test()) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (case_group & DTEST_CACHE_RAM_CASE_CACHE_AS_RAM) {
 | 
						|
        if (dtest_cache_ram_cache_as_ram_test()) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (case_group & DTEST_CACHE_RAM_CASE_CACHE_DIRTY_MISS) {
 | 
						|
        if (dtest_cache_ram_cache_dirty_miss_test()) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (case_group & DTEST_CACHE_RAM_CASE_CACHE_LINE) {
 | 
						|
        if (dtest_cache_ram_cache_line_test()) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* kl3 hardware is not support cache address protect function */
 | 
						|
    if (0) {
 | 
						|
        if (dtest_cache_ram_cache_addr_protect_test()) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* KL3 does not adopt IO share scheme, and image does not support IO share */
 | 
						|
    if (0) {
 | 
						|
        if (dtest_cache_ram_sfc_smc_io_share_test()) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* Manual test */
 | 
						|
    if (0) {
 | 
						|
        if (dtest_cache_ram_sfc_smc_io_remap_test()) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (error_cnt) {
 | 
						|
        dprintf("cache_ram dtest failed\n");
 | 
						|
    } else {
 | 
						|
        dprintf("cache_ram dtest succeed\n");
 | 
						|
    }
 | 
						|
 | 
						|
    dend();
 | 
						|
}
 | 
						|
 | 
						|
int main(void) {
 | 
						|
    dtest_cache_ram_main();
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 |