379 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			379 lines
		
	
	
		
			11 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 "sram.h"
 | 
						|
#include "smc.h"
 | 
						|
#include "ahb.h"
 | 
						|
#include "gp_timer.h"
 | 
						|
 | 
						|
#include "uart.h"
 | 
						|
#include "dbg_io.h"
 | 
						|
 | 
						|
#include "iot_io_api.h"
 | 
						|
#include "os_mem_api.h"
 | 
						|
#include "iot_errno_api.h"
 | 
						|
 | 
						|
#include "dtest_printf.h"
 | 
						|
 | 
						|
#define DTEST_SMC_CASE_GET_SIZE     (1 << 0)
 | 
						|
#define DTEST_SMC_CASE_API_RW       (1 << 1)
 | 
						|
#define DTEST_SMC_CASE_CACHE_RW     (1 << 2)
 | 
						|
#define DTEST_SMC_CASE_FULL_RW      (1 << 3)
 | 
						|
 | 
						|
/* test PSRAM size using write loopback mechanism */
 | 
						|
uint32_t dtest_smc_get_psram_size_test(uint8_t *size)
 | 
						|
{
 | 
						|
    uint8_t i;
 | 
						|
    uint32_t addr_test, data_test, data;
 | 
						|
 | 
						|
    dcase_start("get psram size test\n");
 | 
						|
 | 
						|
//    cache_invalidate(0, ICACHE0_SMC_RAM_BASEADDR, 32);
 | 
						|
    cache_clear(0);
 | 
						|
    *(volatile uint32_t *)(ICACHE0_SMC_RAM_BASEADDR) = 0x0;
 | 
						|
    cache_flush(0, 0x00, 32);
 | 
						|
 | 
						|
    for (i = 0; i < 32; i++) {
 | 
						|
        addr_test = 0x100000 * i;
 | 
						|
        uint8_t temp = i ^ 0x55;
 | 
						|
        data_test = (temp << 24) | (temp << 16) | (temp << 8) | temp;
 | 
						|
        dprintf("test addr:0x%08x, data:0x%08x\n", addr_test, data_test);
 | 
						|
        *(volatile uint32_t *)(ICACHE0_SMC_RAM_BASEADDR + addr_test) = data_test;
 | 
						|
        cache_flush(0, addr_test, 32);
 | 
						|
 | 
						|
//        cache_invalidate(0, ICACHE0_SMC_RAM_BASEADDR, 32);
 | 
						|
        cache_clear(0);
 | 
						|
        data = *(volatile uint32_t *)(ICACHE0_SMC_RAM_BASEADDR);
 | 
						|
        if (addr_test == 0x00) {
 | 
						|
            if (data != data_test) {
 | 
						|
                dprintf("addr(0x00) write and read error, psram not working\n");
 | 
						|
                *size = 0;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            if (data == data_test) {
 | 
						|
                dprintf("write data loopback\n");
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (i == 32) {
 | 
						|
        dprintf("no matching psram size found\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("get psram size:%d\n", i);
 | 
						|
    dcase_success();
 | 
						|
    return ERR_OK;
 | 
						|
fail:
 | 
						|
    dcase_failed();
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t dtest_smc_api_test()
 | 
						|
{
 | 
						|
    int i = 0;
 | 
						|
    uint8_t rdata[0x40] = {0};
 | 
						|
    uint8_t wdata[0x40] = {0};
 | 
						|
    uint8_t data_test = 0x55;
 | 
						|
    uint32_t addr_test = 0x10000;
 | 
						|
 | 
						|
    dcase_start("smc api read/write test\n");
 | 
						|
 | 
						|
    dprintf("init test data with 0x%x\n", data_test);
 | 
						|
    os_mem_set(wdata, data_test, sizeof(wdata));
 | 
						|
 | 
						|
    while(sram_qspi_is_busy() != HAL_SRAM_OK) {
 | 
						|
        dprintf("FLASH IS Busy Now!\n");
 | 
						|
    }
 | 
						|
 | 
						|
    /* spi mode */
 | 
						|
    dprintf("use spi mode to read/write psram\n");
 | 
						|
 | 
						|
    sram_qspi_exit();
 | 
						|
    while (sram_qspi_is_busy() != HAL_SRAM_OK);
 | 
						|
    dprintf("qpi exit succeed\n");
 | 
						|
 | 
						|
    dprintf("spi write data\n");
 | 
						|
    sram_qspi_write(wdata, addr_test, sizeof(wdata));
 | 
						|
    while(sram_qspi_is_busy() != HAL_SRAM_OK);
 | 
						|
 | 
						|
    dprintf("spi read data\n");
 | 
						|
    sram_qspi_read(rdata, addr_test, sizeof(rdata));
 | 
						|
    while(sram_qspi_is_busy() != HAL_SRAM_OK);
 | 
						|
    for (i = 0; i < sizeof(wdata); i++) {
 | 
						|
        if (wdata[i] != rdata[i]) {
 | 
						|
            dprintf("spi mode read data err, index:%d, wdata:%x, rdata:%x\n", i, wdata[i], rdata[i]);
 | 
						|
            goto fail;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* qpi mode */
 | 
						|
    data_test = 0xaa;
 | 
						|
    dprintf("use qpi mode to read/write psram, init test data with 0x%x\n", data_test);
 | 
						|
    os_mem_set(wdata, data_test, sizeof(wdata));
 | 
						|
 | 
						|
    sram_qspi_enter();
 | 
						|
    while(sram_qspi_is_busy() != HAL_SRAM_OK);
 | 
						|
    dprintf("qspi enter succeed\n");
 | 
						|
 | 
						|
    dprintf("qpi write data\n");
 | 
						|
    sram_qspi_quad_write(wdata, addr_test, sizeof(wdata));
 | 
						|
    while(sram_qspi_is_busy());
 | 
						|
 | 
						|
    dprintf("qpi read data\n");
 | 
						|
    os_mem_set(rdata, 0x00, sizeof(rdata));
 | 
						|
 | 
						|
    sram_qspi_quad_read(rdata, addr_test, sizeof(rdata));
 | 
						|
    while(sram_qspi_is_busy() != HAL_SRAM_OK);
 | 
						|
    for (i = 0; i < sizeof(wdata); i++) {
 | 
						|
        if (wdata[i] != rdata[i]) {
 | 
						|
            dprintf("qpi mode read data err, index:%d, wdata:%x, rdata:%x\n", i, wdata[i], rdata[i]);
 | 
						|
            goto fail;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    dcase_success();
 | 
						|
    return ERR_OK;
 | 
						|
fail:
 | 
						|
    dcase_failed();
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t dtest_smc_cache_rw_test()
 | 
						|
{
 | 
						|
    uint32_t i = 0, data = 0, error = 0, test_len = 0x1000, addr_test = 0x000000;
 | 
						|
 | 
						|
    dcase_start("smc cache read/write test\n");
 | 
						|
 | 
						|
    for (i = 0; i < test_len; i++) {
 | 
						|
        *((volatile uint8_t*)(DCACHE0_SMC_RAM_BASEADDR + addr_test + i)) = i % 0xff;
 | 
						|
    }
 | 
						|
    cache_flush(AHB_CACHE_D0, addr_test, test_len);
 | 
						|
 | 
						|
    dprintf("write/read sram by icache0\n");
 | 
						|
    cache_invalidate(AHB_CACHE_I0, addr_test, test_len);
 | 
						|
    for (i = 0; i < test_len; i++) {
 | 
						|
        data = *(volatile uint8_t *)(ICACHE0_SMC_RAM_BASEADDR + addr_test + i);
 | 
						|
        if (data != (i % 0xff)) {
 | 
						|
            dprintf("ERROR icache0 sram read: i:%d, data:%02x\n", i, data);
 | 
						|
            error++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("write/read sram by icache1\n");
 | 
						|
    cache_invalidate(AHB_CACHE_I1, addr_test, test_len);
 | 
						|
    for (i = 0; i < test_len; i++) {
 | 
						|
        data = *(volatile uint8_t *)(ICACHE1_SMC_RAM_BASEADDR + addr_test + i);
 | 
						|
        if (data != (i % 0xff)) {
 | 
						|
            dprintf("ERROR icache1 sram read: i:%d, data:%02x\n", i, data);
 | 
						|
            error++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("write/read sram by icache2\n");
 | 
						|
    cache_invalidate(AHB_CACHE_I2, addr_test, test_len);
 | 
						|
    for (i = 0; i < test_len; i++) {
 | 
						|
        data = *(volatile uint8_t *)(ICACHE2_SMC_RAM_BASEADDR + addr_test + i);
 | 
						|
        if (data != (i % 0xff)) {
 | 
						|
            dprintf("ERROR icache2 sram read: i:%d, data:%02x\n", i, data);
 | 
						|
            error++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("write/read sram by dcache0\n");
 | 
						|
    cache_invalidate(AHB_CACHE_D0, addr_test, test_len);
 | 
						|
    for (i = 0; i < test_len; i++) {
 | 
						|
        data = *(volatile uint8_t *)(DCACHE0_SMC_RAM_BASEADDR + addr_test + i);
 | 
						|
        if (data != (i % 0xff)) {
 | 
						|
            dprintf("ERROR dcache0 sram read: i:%d, data:%02x\n", i, data);
 | 
						|
            error++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("write/read sram by dcache1\n");
 | 
						|
    cache_invalidate(AHB_CACHE_D1, addr_test, test_len);
 | 
						|
    for (i = 0; i < test_len; i++) {
 | 
						|
        data = *(volatile uint8_t *)(DCACHE1_SMC_RAM_BASEADDR + addr_test + i);
 | 
						|
        if (data != (i % 0xff)) {
 | 
						|
            dprintf("ERROR dcache1 sram read: i:%d, data:%02x\n", i, data);
 | 
						|
            error++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (0 == error) {
 | 
						|
        dcase_success();
 | 
						|
        return ERR_OK;
 | 
						|
    }else {
 | 
						|
        dcase_failed();
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
uint32_t dtest_smc_psram_full_rw_test(uint8_t psram_size)
 | 
						|
{
 | 
						|
    uint32_t i = 0, error = 0, temp;
 | 
						|
    uint8_t data_test = 0x55, data;
 | 
						|
    uint32_t len_test = psram_size * 0x100000;
 | 
						|
    uint32_t time_old = 0, time_new = 0, time_use;
 | 
						|
 | 
						|
    dcase_start("psram full read/write test\n");
 | 
						|
 | 
						|
    /* icache_wr_auto_load = 0, it can significantly speed up the reading and
 | 
						|
     * writing of large amounts of data.
 | 
						|
     * In this test, the cache has no other work, and almost no miss will
 | 
						|
     * be generated, so no significant reduction in time is observed(4m - 14678us).
 | 
						|
     */
 | 
						|
    temp = CACHE0_READ_REG(CFG_CACHE_CTR0_ADDR);
 | 
						|
    REG_FIELD_SET(ICACHE_WR_AUTO_LOAD, temp, 0);
 | 
						|
    CACHE0_WRITE_REG(CFG_CACHE_CTR0_ADDR, temp);
 | 
						|
 | 
						|
    time_old = gp_timer_get_current_val(0);
 | 
						|
 | 
						|
    dprintf("write psram, data:0x%x, len:0x%x\n", data_test, len_test);
 | 
						|
    cache_clear(AHB_CACHE_I0);
 | 
						|
    for (i = 0; i < len_test; i++) {
 | 
						|
        *((volatile uint8_t*)(ICACHE0_SMC_RAM_BASEADDR + i)) = i % 0xff;
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("read psram\n");
 | 
						|
    cache_invalidate(AHB_CACHE_I0, 0x00, 0x8000);
 | 
						|
    for (i = 0; i < len_test; i++) {
 | 
						|
        data = *(volatile uint8_t *)(ICACHE0_SMC_RAM_BASEADDR + i);
 | 
						|
        if (data != data_test) {
 | 
						|
            dprintf("ERROR icache0 sram read: i:%d, data:%02x\n", i, data);
 | 
						|
            error++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    data_test = 0xaa;
 | 
						|
    dprintf("write psram, data:0x%x, len:0x%x\n", data_test, len_test);
 | 
						|
    cache_clear(AHB_CACHE_I0);
 | 
						|
    for (i = 0; i < len_test; i++) {
 | 
						|
        *((volatile uint8_t*)(ICACHE0_SMC_RAM_BASEADDR + i)) = i % 0xff;
 | 
						|
    }
 | 
						|
 | 
						|
    dprintf("read psram\n");
 | 
						|
    cache_invalidate(AHB_CACHE_I0, 0x00, 0x8000);
 | 
						|
    for (i = 0; i < len_test; i++) {
 | 
						|
        data = *(volatile uint8_t *)(ICACHE0_SMC_RAM_BASEADDR + i);
 | 
						|
        if (data != data_test) {
 | 
						|
            dprintf("ERROR icache0 sram read: i:%d, data:%02x\n", i, data);
 | 
						|
            error++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    time_new = gp_timer_get_current_val(0);
 | 
						|
    time_use = (time_old < time_new) ? (time_new - time_old) :
 | 
						|
        (0xffffffff - time_old + time_new);
 | 
						|
    dprintf("full read/write complete, it takes %d us\n", time_use);
 | 
						|
 | 
						|
    temp = CACHE0_READ_REG(CFG_CACHE_CTR0_ADDR);
 | 
						|
    REG_FIELD_SET(ICACHE_WR_AUTO_LOAD, temp, 1);
 | 
						|
    CACHE0_WRITE_REG(CFG_CACHE_CTR0_ADDR, temp);
 | 
						|
 | 
						|
    if (0 == error) {
 | 
						|
        dcase_success();
 | 
						|
        return ERR_OK;
 | 
						|
    }else {
 | 
						|
        dcase_failed();
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void dtest_smc_main()
 | 
						|
{
 | 
						|
    uint32_t case_group = 0, error_cnt = 0;
 | 
						|
    uint8_t psram_size = 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);
 | 
						|
 | 
						|
    gp_timer_init();
 | 
						|
    gp_timer_set(0, 0xffffffff, 0);
 | 
						|
    gp_timer_start(0);
 | 
						|
 | 
						|
    /* reset emc */
 | 
						|
    dprintf("reset emc\n");
 | 
						|
    ahb_emc_disable();
 | 
						|
    ahb_emc_enable();
 | 
						|
    ahb_emc_reset();
 | 
						|
 | 
						|
    /* init psram */
 | 
						|
    dprintf("initialize psram\n");
 | 
						|
    sram_qspi_init();
 | 
						|
    sram_qspi_enter();
 | 
						|
    hal_smc_qspi_quad_cfg(0);
 | 
						|
 | 
						|
    /* init cache */
 | 
						|
    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_SMC_CASE_GET_SIZE) {
 | 
						|
        if (dtest_smc_get_psram_size_test(&psram_size)) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* only buffer mode, register mode will be failed */
 | 
						|
    if (case_group & DTEST_SMC_CASE_API_RW) {
 | 
						|
        if (dtest_smc_api_test()) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (case_group & DTEST_SMC_CASE_CACHE_RW) {
 | 
						|
        if (dtest_smc_cache_rw_test()) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (case_group & DTEST_SMC_CASE_FULL_RW) {
 | 
						|
        if (dtest_smc_psram_full_rw_test(psram_size)) {
 | 
						|
            error_cnt++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (error_cnt) {
 | 
						|
        dprintf("smc dtest failed\n");
 | 
						|
    } else {
 | 
						|
        dprintf("smc dtest succeed\n");
 | 
						|
    }
 | 
						|
 | 
						|
    dend();
 | 
						|
}
 | 
						|
 | 
						|
int main(void) {
 | 
						|
    dtest_smc_main();
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 |