rt-thread-official/bsp/at32/libraries/rt_drivers/drv_sdram.c

257 lines
6.9 KiB
C

/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-05-16 shelton first version
*/
#include "drv_common.h"
#ifdef BSP_USING_SDRAM
#include "drv_sdram.h"
#define DRV_DEBUG
#define LOG_TAG "drv.sdram"
#include <drv_log.h>
#ifdef RT_USING_MEMHEAP_AS_HEAP
static struct rt_memheap system_heap;
#endif
static void sdram_init_sequence(xmc_cmd_bank1_2_type cmd_bank)
{
xmc_sdram_cmd_type sdram_cmd_struct;
uint32_t timeout = 0xffff, delay = 0;
sdram_cmd_struct.cmd = XMC_CMD_CLK;
sdram_cmd_struct.auto_refresh = 1;
sdram_cmd_struct.cmd_banks = cmd_bank;
sdram_cmd_struct.data = 0;
xmc_sdram_cmd(&sdram_cmd_struct);
while((xmc_flag_status_get(XMC_BANK5_6_SDRAM, XMC_BUSY_FLAG) != RESET) && (timeout > 0))
{
timeout --;
}
/* insert 100 ms delay */
for (delay = 0; delay < 0xffff; delay ++)
;
sdram_cmd_struct.cmd = XMC_CMD_PRECHARG_ALL;
sdram_cmd_struct.auto_refresh = 1;
sdram_cmd_struct.cmd_banks = cmd_bank;
sdram_cmd_struct.data = 0;
xmc_sdram_cmd(&sdram_cmd_struct);
timeout = 0xffff;
while((xmc_flag_status_get(XMC_BANK5_6_SDRAM, XMC_BUSY_FLAG) != RESET) && (timeout > 0))
{
timeout --;
}
/* set refresh rate */
xmc_sdram_refresh_counter_set(SDRAM_REFRESH_COUNT);
sdram_cmd_struct.cmd = XMC_CMD_AUTO_REFRESH;
sdram_cmd_struct.auto_refresh = 8;
sdram_cmd_struct.cmd_banks = cmd_bank;
sdram_cmd_struct.data = 0;
xmc_sdram_cmd(&sdram_cmd_struct);
timeout = 0xffff;
while((xmc_flag_status_get(XMC_BANK5_6_SDRAM, XMC_BUSY_FLAG) != RESET) && (timeout > 0))
{
timeout --;
}
sdram_cmd_struct.cmd = XMC_CMD_LOAD_MODE;
sdram_cmd_struct.auto_refresh = 1;
sdram_cmd_struct.cmd_banks = cmd_bank;
#if SDRAM_DATA_WIDTH == 8
sdram_cmd_struct.data = (uint32_t)SDRAM_BURST_LEN_1 |
#elif SDRAM_DATA_WIDTH == 16
sdram_cmd_struct.data = (uint32_t)SDRAM_BURST_LEN_2 |
#endif
SDRAM_BURST_SEQUENTIAL |
#if SDRAM_CAS_LATENCY == 3
SDRAM_CAS_LATENCY_3 |
#else
SDRAM_CAS_LATENCY_2 |
#endif
SDRAM_OPERATING_MODE_STANDARD |
SDRAM_WR_BURST_SINGLE;
xmc_sdram_cmd(&sdram_cmd_struct);
timeout = 0xffff;
while((xmc_flag_status_get(XMC_BANK5_6_SDRAM, XMC_BUSY_FLAG) != RESET) && (timeout > 0))
{
timeout --;
}
}
static int sdram_init(void)
{
int result = RT_EOK;
xmc_cmd_bank1_2_type target_bank = XMC_CMD_BANK1;
xmc_sdram_init_type sdram_init_struct;
xmc_sdram_timing_type sdram_timing_struct;
at32_msp_sdram_init(NULL);
/* xmc configuration */
xmc_sdram_default_para_init(&sdram_init_struct, &sdram_timing_struct);
#if SDRAM_TARGET_BANK == 1
sdram_init_struct.sdram_bank = XMC_SDRAM_BANK1;
#else
sdram_init_struct.sdram_bank = XMC_SDRAM_BANK2;
#endif
#if SDRAM_COLUMN_BITS == 8
sdram_init_struct.column_address = XMC_COLUMN_8;
#elif SDRAM_COLUMN_BITS == 9
sdram_init_struct.column_address = XMC_COLUMN_9;
#elif SDRAM_COLUMN_BITS == 10
sdram_init_struct.column_address = XMC_COLUMN_10;
#else
sdram_init_struct.column_address = XMC_COLUMN_11;
#endif
#if SDRAM_ROW_BITS == 11
sdram_init_struct.row_address = XMC_ROW_11;
#elif SDRAM_ROW_BITS == 12
sdram_init_struct.row_address = XMC_ROW_12;
#else
sdram_init_struct.row_address = XMC_ROW_13;
#endif
#if SDRAM_DATA_WIDTH == 8
sdram_init_struct.width = XMC_MEM_WIDTH_8;
#elif SDRAM_DATA_WIDTH == 16
sdram_init_struct.width = XMC_MEM_WIDTH_16;
#endif
sdram_init_struct.internel_banks = XMC_INBK_4;
#if SDRAM_CAS_LATENCY == 1
sdram_init_struct.cas = XMC_CAS_1;
#elif SDRAM_CAS_LATENCY == 2
sdram_init_struct.cas = XMC_CAS_2;
#else
sdram_init_struct.cas = XMC_CAS_3;
#endif
#if SDRAM_RPIPE_DELAY == 0
sdram_init_struct.read_delay = XMC_READ_DELAY_0;
#elif SDRAM_RPIPE_DELAY == 1
sdram_init_struct.read_delay = XMC_READ_DELAY_1;
#else
sdram_init_struct.read_delay = XMC_READ_DELAY_2;
#endif
#if SDCLOCK_PERIOD == 2
sdram_init_struct.clkdiv = XMC_CLKDIV_2;
#else
sdram_init_struct.clkdiv = XMC_CLKDIV_3;
#endif
sdram_init_struct.write_protection = FALSE;
sdram_init_struct.burst_read = TRUE;
sdram_timing_struct.tmrd = LOADTOACTIVEDELAY;
sdram_timing_struct.txsr = EXITSELFREFRESHDELAY;
sdram_timing_struct.tras = SELFREFRESHTIME;
sdram_timing_struct.trc = ROWCYCLEDELAY;
sdram_timing_struct.twr = WRITERECOVERYTIME;
sdram_timing_struct.trp = RPDELAY;
sdram_timing_struct.trcd = RCDDELAY;
xmc_sdram_init(&sdram_init_struct, &sdram_timing_struct);
#if SDRAM_TARGET_BANK == 1
target_bank = XMC_CMD_BANK1;
#else
target_bank = XMC_CMD_BANK2;
#endif
sdram_init_sequence(target_bank);
#ifdef RT_USING_MEMHEAP_AS_HEAP
/* If RT_USING_MEMHEAP_AS_HEAP is enabled, SDRAM is initialized to the heap */
rt_memheap_init(&system_heap, "sdram", (void *)SDRAM_BANK_ADDR, SDRAM_SIZE);
#endif
return result;
}
INIT_BOARD_EXPORT(sdram_init);
#ifdef DRV_DEBUG
#ifdef FINSH_USING_MSH
int sdram_sample(void)
{
int i = 0;
uint32_t start_time = 0, time_cast = 0;
#if SDRAM_DATA_WIDTH == 8
char data_width = 1;
uint8_t data = 0;
#elif SDRAM_DATA_WIDTH == 16
char data_width = 2;
uint16_t data = 0;
#else
char data_width = 4;
uint32_t data = 0;
#endif
/* write data */
LOG_D("writing the %ld bytes data, waiting....", SDRAM_SIZE);
start_time = rt_tick_get();
for (i = 0; i < SDRAM_SIZE / data_width; i++)
{
#if SDRAM_DATA_WIDTH == 8
*(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint8_t)(i % 100);
#elif SDRAM_DATA_WIDTH == 16
*(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint16_t)(i % 1000);
#endif
}
time_cast = rt_tick_get() - start_time;
LOG_D("write data success, total time: %d.%03dS.", time_cast / RT_TICK_PER_SECOND,
time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
/* read data */
LOG_D("start reading and verifying data, waiting....");
for (i = 0; i < SDRAM_SIZE / data_width; i++)
{
#if SDRAM_DATA_WIDTH == 8
data = *(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width);
if (data != i % 100)
{
LOG_E("sdram test failed!");
break;
}
#elif SDRAM_DATA_WIDTH == 16
data = *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width);
if (data != (uint16_t)(i % 1000))
{
LOG_E("sdram test failed, i = %d!", i);
break;
}
#endif
}
if (i >= SDRAM_SIZE / data_width)
{
LOG_D("sdram test success!");
}
return RT_EOK;
}
MSH_CMD_EXPORT(sdram_sample, sdram sample test)
#endif /* FINSH_USING_MSH */
#endif /* DRV_DEBUG */
#endif /* BSP_USING_SDRAM */