| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- /*
- * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2023-02-24 CDT first version
- * 2024-02-20 CDT modify exclk clock max frequency to 40MHz for HC32F4A0
- * add t_rcd_p/t_rfc_p/t_rp_p configuration
- * 2024-12-24 CDT modify sample clock to EXMC_DMC_SAMPLE_CLK_EXTCLK for HC32F4A0
- */
- /*******************************************************************************
- * Include files
- ******************************************************************************/
- #include <rtthread.h>
- #if defined(BSP_USING_EXMC)
- #if defined(BSP_USING_SDRAM)
- #include "drv_sdram.h"
- #include "board_config.h"
- #include "sdram_port.h"
- /*******************************************************************************
- * Local type definitions ('typedef')
- ******************************************************************************/
- /*******************************************************************************
- * Local pre-processor symbols/macros ('#define')
- ******************************************************************************/
- //#define DRV_DEBUG
- #define LOG_TAG "drv.sdram"
- #include <drv_log.h>
- /*******************************************************************************
- * Global variable definitions (declared in header file with 'extern')
- ******************************************************************************/
- #if defined (BSP_USING_SDRAM)
- rt_err_t rt_hw_board_sdram_init(void);
- #endif
- /*******************************************************************************
- * Local function prototypes ('static')
- ******************************************************************************/
- /*******************************************************************************
- * Local variable definitions ('static')
- ******************************************************************************/
- #ifdef RT_USING_MEMHEAP_AS_HEAP
- static struct rt_memheap _system_heap;
- #endif
- /*******************************************************************************
- * Function implementation - global ('extern') and local ('static')
- ******************************************************************************/
- /**
- * @brief SDRAM initialization sequence.
- * @param [in] chip The command chip number.
- * @param [in] md_reg_value The SDRAM mode register value
- * @retval None
- */
- static void _sdram_initialization_sequence(rt_uint32_t chip, rt_uint32_t md_reg_value)
- {
- /* SDRAM initialization sequence:
- CMD NOP->PrechargeAll->AutoRefresh->AutoRefresh->MdRegConfig->NOP */
- (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_NOP, 0UL);
- (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_PRECHARGE_ALL, 0UL);
- (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_AUTO_REFRESH, 0UL);
- (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_AUTO_REFRESH, 0UL);
- (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_MDREG_CONFIG, md_reg_value);
- (void)EXMC_DMC_SetCommand(chip, 0UL, EXMC_DMC_CMD_NOP, 0UL);
- }
- /**
- * @brief verify clock frequency.
- * @retval result
- */
- static rt_int32_t _sdram_verify_clock_frequency(void)
- {
- rt_int32_t ret = RT_EOK;
- #if defined (HC32F4A0) || defined (HC32F4A8)
- /* EXCLK max frequency for SDRAM */
- if (CLK_GetBusClockFreq(CLK_BUS_EXCLK) > EXMC_EXCLK_DMC_MAX_FREQ)
- {
- ret = -RT_ERROR;
- }
- #endif
- return ret;
- }
- /**
- * @brief SDRAM initialization.
- * @param None
- * @retval result
- */
- static rt_int32_t _sdram_init(void)
- {
- rt_uint32_t md_reg_value;
- stc_exmc_dmc_init_t stcDmcInit;
- stc_exmc_dmc_chip_config_t stcCsConfig;
- /* verify SDRAM clock frequency */
- if (_sdram_verify_clock_frequency() != RT_EOK)
- {
- LOG_E("EXMC clock frequency is over limit for SDRAM!");
- return -RT_ERROR;
- }
- /* initialization SDRAM port.*/
- rt_hw_board_sdram_init();
- /* enable DMC clock */
- FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_DMC, ENABLE);
- /* enable DMC. */
- EXMC_DMC_Cmd(ENABLE);
- /* configure DMC width && refresh period & chip & timing. */
- (void)EXMC_DMC_StructInit(&stcDmcInit);
- #if defined (HC32F4A0)
- stcDmcInit.u32SampleClock = EXMC_DMC_SAMPLE_CLK_EXTCLK;
- #endif
- stcDmcInit.u32RefreshPeriod = SDRAM_REFRESH_COUNT;
- stcDmcInit.u32ColumnBitsNumber = SDRAM_COLUMN_BITS;
- stcDmcInit.u32RowBitsNumber = SDRAM_ROW_BITS;
- stcDmcInit.u32MemBurst = SDRAM_BURST_LENGTH;
- stcDmcInit.u32AutoRefreshChips = EXMC_DMC_AUTO_REFRESH_4CHIPS;
- stcDmcInit.stcTimingConfig.u8CASL = SDRAM_CAS_LATENCY;
- stcDmcInit.stcTimingConfig.u8DQSS = 0U;
- stcDmcInit.stcTimingConfig.u8MRD = SDRAM_TMDR;
- stcDmcInit.stcTimingConfig.u8RAS = SDRAM_TRAS;
- stcDmcInit.stcTimingConfig.u8RC = SDRAM_TRC;
- stcDmcInit.stcTimingConfig.u8RCD_B = SDRAM_TRCD_B;
- stcDmcInit.stcTimingConfig.u8RCD_P = SDRAM_TRCD_P;
- stcDmcInit.stcTimingConfig.u8RFC_B = SDRAM_TRFC_B;
- stcDmcInit.stcTimingConfig.u8RFC_P = SDRAM_TRFC_P;
- stcDmcInit.stcTimingConfig.u8RP_B = SDRAM_TRP_B;
- stcDmcInit.stcTimingConfig.u8RP_P = SDRAM_TRP_P;
- stcDmcInit.stcTimingConfig.u8RRD = SDRAM_TRRD;
- stcDmcInit.stcTimingConfig.u8WR = SDRAM_TWR;
- stcDmcInit.stcTimingConfig.u8WTR = SDRAM_TWTR;
- stcDmcInit.stcTimingConfig.u8XP = SDRAM_TXP;
- stcDmcInit.stcTimingConfig.u8XSR = SDRAM_TXSR;
- stcDmcInit.stcTimingConfig.u8ESR = SDRAM_TESR;
- (void)EXMC_DMC_Init(&stcDmcInit);
- /* configure DMC address space. */
- stcCsConfig.u32AddrMatch = (SDRAM_BANK_ADDR >> 24);
- stcCsConfig.u32AddrMask = EXMC_DMC_ADDR_MASK_128MB;
- stcCsConfig.u32AddrDecodeMode = EXMC_DMC_CS_DECODE_ROWBANKCOL;
- (void)EXMC_DMC_ChipConfig(SDRAM_CHIP, &stcCsConfig);
- /* SDRAM initialization sequence. */
- md_reg_value = (SDRAM_MODEREG_BURST_TYPE | SDRAM_MODEREG_WRITEBURST_MODE | SDRAM_MODEREG_OPERATING_MODE);
- if (2U == stcDmcInit.stcTimingConfig.u8CASL)
- {
- md_reg_value |= SDRAM_MODEREG_CAS_LATENCY_2;
- }
- else
- {
- md_reg_value |= SDRAM_MODEREG_CAS_LATENCY_3;
- }
- if (EXMC_DMC_BURST_1BEAT == stcDmcInit.u32MemBurst)
- {
- md_reg_value |= SDRAM_MODEREG_BURST_LENGTH_1;
- }
- else if (EXMC_DMC_BURST_2BEAT == stcDmcInit.u32MemBurst)
- {
- md_reg_value |= SDRAM_MODEREG_BURST_LENGTH_2;
- }
- else if (EXMC_DMC_BURST_4BEAT == stcDmcInit.u32MemBurst)
- {
- md_reg_value |= SDRAM_MODEREG_BURST_LENGTH_4;
- }
- else
- {
- md_reg_value |= SDRAM_MODEREG_BURST_LENGTH_8;
- }
- _sdram_initialization_sequence(SDRAM_CHIP, md_reg_value);
- /* switch state from configure to ready */
- EXMC_DMC_SetState(EXMC_DMC_CTRL_STATE_GO);
- EXMC_DMC_SetState(EXMC_DMC_CTRL_STATE_WAKEUP);
- EXMC_DMC_SetState(EXMC_DMC_CTRL_STATE_GO);
- return RT_EOK;
- }
- int rt_hw_sdram_init(void)
- {
- rt_int32_t ret;
- ret = _sdram_init();
- if (RT_EOK != ret)
- {
- LOG_E("SDRAM init failed!");
- return -RT_ERROR;
- }
- #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 ret;
- }
- INIT_BOARD_EXPORT(rt_hw_sdram_init);
- #ifdef DRV_DEBUG
- #ifdef FINSH_USING_MSH
- static int _sdram_test(void)
- {
- rt_uint32_t i;
- rt_uint32_t start_time;
- rt_uint32_t time_cast;
- #if SDRAM_DATA_WIDTH == EXMC_DMC_MEMORY_WIDTH_16BIT
- const char data_width = 2;
- rt_uint16_t data = 0;
- #else
- char data_width = 4;
- rt_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 == EXMC_DMC_MEMORY_WIDTH_16BIT
- *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint16_t)(i % 1000);
- #else
- *(__IO uint32_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint32_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 == EXMC_DMC_MEMORY_WIDTH_16BIT
- data = *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width);
- if (data != i % 1000)
- {
- LOG_E("SDRAM test failed!");
- break;
- }
- #else
- data = *(__IO uint32_t *)(SDRAM_BANK_ADDR + i * data_width);
- if (data != i % 1000)
- {
- LOG_E("SDRAM test failed!");
- break;
- }
- #endif
- }
- if (i >= SDRAM_SIZE / data_width)
- {
- LOG_D("SDRAM test success!");
- }
- return RT_EOK;
- }
- MSH_CMD_EXPORT(_sdram_test, sdram test)
- #endif /* FINSH_USING_MSH */
- #endif /* DRV_DEBUG */
- #endif /* BSP_USING_SDRAM */
- #endif /* BSP_USING_EXMC */
|