FSMC. SDRAM driver cleanup. Needs review.

This commit is contained in:
barthess 2014-10-25 15:26:29 +03:00
parent e9f9ddaa12
commit b47ddce74d
3 changed files with 148 additions and 221 deletions

View File

@ -39,16 +39,16 @@
/* Driver local definitions. */
/*===========================================================================*/
#define SDCR2_DONTCARE_BITS (FMC_SDClock_Period_Mask | \
FMC_Read_Burst_Mask | \
FMC_ReadPipe_Delay_Mask)
#define SDTR2_DONTCARE_BITS (FMC_RowCycleDelay_Mask | FMC_RPDelay_Mask)
/*
* FMC SDCRx write protection mask
/**
* FMC_Command_Mode
*/
#define SDCR_WriteProtection_RESET ((uint32_t)0x00007DFF)
#define FMC_Command_Mode_normal ((uint32_t)0x00000000)
#define FMC_Command_Mode_CLK_Enabled ((uint32_t)0x00000001)
#define FMC_Command_Mode_PALL ((uint32_t)0x00000002)
#define FMC_Command_Mode_AutoRefresh ((uint32_t)0x00000003)
#define FMC_Command_Mode_LoadMode ((uint32_t)0x00000004)
#define FMC_Command_Mode_Selfrefresh ((uint32_t)0x00000005)
#define FMC_Command_Mode_PowerDown ((uint32_t)0x00000006)
/*===========================================================================*/
/* Driver exported variables. */
@ -83,13 +83,12 @@ static void _sdram_wait_ready(void) {
/**
* @brief Executes the SDRAM memory initialization sequence.
*
* @param[in] sdramp pointer to the @p SDRAMDriver object
* @param[in] cfgp pointer to the @p SDRAMConfig object
*
* @notapi
*/
static void _sdram_init_sequence(void) {
static void _sdram_init_sequence(const SDRAMConfig *cfgp) {
uint32_t tmp = 0;
uint32_t command_target = 0;
#if STM32_SDRAM_USE_FSMC_SDRAM1
@ -101,58 +100,32 @@ static void _sdram_init_sequence(void) {
/* Step 3: Configure a clock configuration enable command.*/
_sdram_wait_ready();
SDRAMD.sdram->SDCMR = (uint32_t) FMC_Command_Mode_CLK_Enabled |
command_target |
((1 -1) << 5) | // FMC_AutoRefreshNumber = 1
(0 << 9); // FMC_ModeRegisterDefinition = 0
SDRAMD.sdram->SDCMR = FMC_Command_Mode_CLK_Enabled | command_target;
/* Step 4: Insert 10 ms delay.*/
chSysPolledDelayX(MS2ST(10));
/* Step 4: Insert 1 ms delay (tipically 100uS).*/
osalThreadSleepMilliseconds(1);
/* Step 5: Configure a PALL (precharge all) command.*/
_sdram_wait_ready();
SDRAMD.sdram->SDCMR = (uint32_t) FMC_Command_Mode_PALL |
command_target |
((1 -1) << 5) | // FMC_AutoRefreshNumber = 1
(0 << 9); // FMC_ModeRegisterDefinition = 0
SDRAMD.sdram->SDCMR = FMC_Command_Mode_PALL | command_target;
/* Step 6.1: Configure a Auto-Refresh command: send the first command.*/
_sdram_wait_ready();
SDRAMD.sdram->SDCMR = (uint32_t) FMC_Command_Mode_AutoRefresh |
command_target |
((4 -1) << 5) | // FMC_AutoRefreshNumber = 4
(0 << 9); // FMC_ModeRegisterDefinition = 0
SDRAMD.sdram->SDCMR = FMC_Command_Mode_AutoRefresh | command_target |
(cfgp->sdcmr & FMC_SDCMR_NRFS);
/* Step 6.2: Send the second command.*/
SDRAMD.sdram->SDCMR = (uint32_t) FMC_Command_Mode_AutoRefresh |
command_target |
((4 -1) << 5) | // FMC_AutoRefreshNumber = 4
(0 << 9); // FMC_ModeRegisterDefinition = 0
SDRAMD.sdram->SDCMR = FMC_Command_Mode_AutoRefresh | command_target |
(cfgp->sdcmr & FMC_SDCMR_NRFS);
/* Step 7: Program the external memory mode register.*/
_sdram_wait_ready();
tmp = FMC_SDCMR_MRD_BURST_LENGTH_2 |
FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL |
FMC_SDCMR_MRD_CAS_LATENCY_3 |
FMC_SDCMR_MRD_OPERATING_MODE_STANDARD |
FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE;
SDRAMD.sdram->SDCMR = (uint32_t) FMC_Command_Mode_LoadMode |
command_target |
((1 -1) << 5) | // FMC_AutoRefreshNumber = 1
(tmp << 9);
SDRAMD.sdram->SDCMR = FMC_Command_Mode_LoadMode | command_target |
(cfgp->sdcmr & FMC_SDCMR_MRD);
/* Step 8: Set clock.*/
_sdram_wait_ready();
// 64ms/4096=15.625us
#if (STM32_SYSCLK == 180000000)
//15.625us*90MHz=1406-20=1386
SDRAMD.sdram->SDRTR=1386<<1;
#elif (STM32_SYSCLK == 168000000)
//15.625us*84MHz=1312-20=1292
SDRAMD.sdram->SDRTR=1292<<1;
#else
#error No refresh timings for this clock
#endif
SDRAMD.sdram->SDRTR = cfgp->sdrtr;
_sdram_wait_ready();
}
@ -191,15 +164,16 @@ void fsmcSdramStart(SDRAMDriver *sdramp, const SDRAMConfig *cfgp) {
"SDRAM. Invalid state.");
if (sdramp->state == SDRAM_STOP) {
#if STM32_SDRAM_USE_FSMC_SDRAM1
sdramp->sdram->banks[0].SDCR = cfgp->sdcr1;
sdramp->sdram->banks[0].SDTR = cfgp->sdtr1;
#endif
#if STM32_SDRAM_USE_FSMC_SDRAM2
sdramp->sdram->banks[1].SDCR = cfgp->sdcr2;
sdramp->sdram->banks[1].SDTR = cfgp->sdtr2;
#endif
_sdram_init_sequence();
/* Even if you need only bank2 you must properly set up SDCR and SDTR
regitsters for bank1 too. Both banks will be tuned equally assuming
connected memory ICs are equal.*/
sdramp->sdram->banks[0].SDCR = cfgp->sdcr;
sdramp->sdram->banks[0].SDTR = cfgp->sdtr;
sdramp->sdram->banks[1].SDCR = cfgp->sdcr;
sdramp->sdram->banks[1].SDTR = cfgp->sdtr;
_sdram_init_sequence(cfgp);
sdramp->state = SDRAM_READY;
}
@ -219,22 +193,6 @@ void fsmcSdramStop(SDRAMDriver *sdramp) {
}
}
/**
* @brief Enables or disables write protection to the specified SDRAM Bank.
* @param SDRAM_Bank: Defines the FMC SDRAM bank. This parameter can be
* FMC_Bank1_SDRAM or FMC_Bank2_SDRAM.
* @param NewState: new state of the write protection flag.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
//void fsmcSdram_WriteProtectionConfig(SDRAMDriver *sdramp, int state) {
//
// if (state)
// sdramp->sdram->SDCR |= FMC_Write_Protection_Enable;
// else
// sdramp->sdram->SDCR &= SDCR_WriteProtection_RESET;
//}
#endif /* STM32_USE_FSMC_SDRAM */
#endif /* STM32F427xx / STM32F429xx / STM32F437xx / STM32F439xx */

View File

@ -40,142 +40,6 @@
/* Driver constants. */
/*===========================================================================*/
/**
* @defgroup FMC_ColumnBits_Number
* @{
*/
#define FMC_ColumnBits_Number_8b ((uint32_t)0x00000000)
#define FMC_ColumnBits_Number_9b ((uint32_t)0x00000001)
#define FMC_ColumnBits_Number_10b ((uint32_t)0x00000002)
#define FMC_ColumnBits_Number_11b ((uint32_t)0x00000003)
/**
* @}
*/
/**
* @defgroup FMC_RowBits_Number
* @{
*/
#define FMC_RowBits_Number_11b ((uint32_t)0x00000000)
#define FMC_RowBits_Number_12b ((uint32_t)0x00000004)
#define FMC_RowBits_Number_13b ((uint32_t)0x00000008)
/**
* @}
*/
/**
* @defgroup FMC_SDMemory_Data_Width
* @{
*/
#define FMC_SDMemory_Width_8b ((uint32_t)0x00000000)
#define FMC_SDMemory_Width_16b ((uint32_t)0x00000010)
#define FMC_SDMemory_Width_32b ((uint32_t)0x00000020)
/**
* @}
*/
/**
* @defgroup FMC_InternalBank_Number
* @{
*/
#define FMC_InternalBank_Number_2 ((uint32_t)0x00000000)
#define FMC_InternalBank_Number_4 ((uint32_t)0x00000040)
/**
* @}
*/
/**
* @defgroup FMC_CAS_Latency
* @{
*/
#define FMC_CAS_Latency_1 ((uint32_t)0x00000080)
#define FMC_CAS_Latency_2 ((uint32_t)0x00000100)
#define FMC_CAS_Latency_3 ((uint32_t)0x00000180)
/**
* @}
*/
/**
* @defgroup FMC_Write_Protection
* @{
*/
#define FMC_Write_Protection_Disable ((uint32_t)0x00000000)
#define FMC_Write_Protection_Enable ((uint32_t)0x00000200)
/**
* @}
*/
/**
* @defgroup FMC_SDClock_Period
* @{
*/
#define FMC_SDClock_Disable ((uint32_t)0x00000000)
#define FMC_SDClock_Period_2 ((uint32_t)0x00000800)
#define FMC_SDClock_Period_3 ((uint32_t)0x00000C00)
#define FMC_SDClock_Period_Mask ((uint32_t)0x00000C00)
/**
* @}
*/
/**
* @defgroup FMC_Read_Burst
* @{
*/
#define FMC_Read_Burst_Disable ((uint32_t)0x00000000)
#define FMC_Read_Burst_Enable ((uint32_t)0x00001000)
#define FMC_Read_Burst_Mask ((uint32_t)0x00001000)
/**
* @}
*/
/**
* @defgroup FMC_ReadPipe_Delay
* @{
*/
#define FMC_ReadPipe_Delay_0 ((uint32_t)0x00000000)
#define FMC_ReadPipe_Delay_1 ((uint32_t)0x00002000)
#define FMC_ReadPipe_Delay_2 ((uint32_t)0x00004000)
#define FMC_ReadPipe_Delay_Mask ((uint32_t)0x00006000)
/**
* @}
*/
/**
* @defgroup FMC_Command_Mode
* @{
*/
#define FMC_Command_Mode_normal ((uint32_t)0x00000000)
#define FMC_Command_Mode_CLK_Enabled ((uint32_t)0x00000001)
#define FMC_Command_Mode_PALL ((uint32_t)0x00000002)
#define FMC_Command_Mode_AutoRefresh ((uint32_t)0x00000003)
#define FMC_Command_Mode_LoadMode ((uint32_t)0x00000004)
#define FMC_Command_Mode_Selfrefresh ((uint32_t)0x00000005)
#define FMC_Command_Mode_PowerDown ((uint32_t)0x00000006)
/**
* @}
*/
/**
* @brief FMC SDRAM Mode definition register defines
*/
#define FMC_SDCMR_MRD_BURST_LENGTH_1 ((uint16_t)0x0000)
#define FMC_SDCMR_MRD_BURST_LENGTH_2 ((uint16_t)0x0001)
#define FMC_SDCMR_MRD_BURST_LENGTH_4 ((uint16_t)0x0002)
#define FMC_SDCMR_MRD_BURST_LENGTH_8 ((uint16_t)0x0004)
#define FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define FMC_SDCMR_MRD_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define FMC_SDCMR_MRD_CAS_LATENCY_2 ((uint16_t)0x0020)
#define FMC_SDCMR_MRD_CAS_LATENCY_3 ((uint16_t)0x0030)
#define FMC_SDCMR_MRD_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define FMC_SDCMR_MRD_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
#define FMC_RowCycleDelay_Mask ((uint16_t)0x0000000F << 12)
#define FMC_RPDelay_Mask ((uint16_t)0x0000000F << 20)
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
@ -240,14 +104,29 @@ typedef struct SDRAMDriver SDRAMDriver;
* @note It could be empty on some architectures.
*/
typedef struct {
#if STM32_SDRAM_USE_FSMC_SDRAM1
uint32_t sdcr1;
uint32_t sdtr1;
#endif
#if STM32_SDRAM_USE_FSMC_SDRAM2
uint32_t sdcr2;
uint32_t sdtr2;
#endif
/**
* @brief SDRAM control register.
* @note Its value will be used for both banks.
*/
uint32_t sdcr;
/**
* @brief SDRAM timing register.
* @note Its value will be used for both banks.
*/
uint32_t sdtr;
/**
* @brief SDRAM command mode register.
* @note Only its MRD and NRFS bits will be used.
*/
uint32_t sdcmr;
/**
* @brief SDRAM refresh timer register.
* @note Only its COUNT bits will be used.
*/
uint32_t sdrtr;
} SDRAMConfig;
/**

View File

@ -37,6 +37,85 @@ write memtest function using ideas from http://www.memtest86.com/technical.htm
*/
#define USE_INFINITE_MEMTEST FALSE
/*
* FMC SDRAM Mode definition register defines
*/
#define FMC_SDCMR_MRD_BURST_LENGTH_1 ((uint16_t)0x0000)
#define FMC_SDCMR_MRD_BURST_LENGTH_2 ((uint16_t)0x0001)
#define FMC_SDCMR_MRD_BURST_LENGTH_4 ((uint16_t)0x0002)
#define FMC_SDCMR_MRD_BURST_LENGTH_8 ((uint16_t)0x0004)
#define FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define FMC_SDCMR_MRD_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define FMC_SDCMR_MRD_CAS_LATENCY_2 ((uint16_t)0x0020)
#define FMC_SDCMR_MRD_CAS_LATENCY_3 ((uint16_t)0x0030)
#define FMC_SDCMR_MRD_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define FMC_SDCMR_MRD_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
/*
* FMC_ReadPipe_Delay
*/
#define FMC_ReadPipe_Delay_0 ((uint32_t)0x00000000)
#define FMC_ReadPipe_Delay_1 ((uint32_t)0x00002000)
#define FMC_ReadPipe_Delay_2 ((uint32_t)0x00004000)
#define FMC_ReadPipe_Delay_Mask ((uint32_t)0x00006000)
/*
* FMC_Read_Burst
*/
#define FMC_Read_Burst_Disable ((uint32_t)0x00000000)
#define FMC_Read_Burst_Enable ((uint32_t)0x00001000)
#define FMC_Read_Burst_Mask ((uint32_t)0x00001000)
/*
* FMC_SDClock_Period
*/
#define FMC_SDClock_Disable ((uint32_t)0x00000000)
#define FMC_SDClock_Period_2 ((uint32_t)0x00000800)
#define FMC_SDClock_Period_3 ((uint32_t)0x00000C00)
#define FMC_SDClock_Period_Mask ((uint32_t)0x00000C00)
/*
* FMC_ColumnBits_Number
*/
#define FMC_ColumnBits_Number_8b ((uint32_t)0x00000000)
#define FMC_ColumnBits_Number_9b ((uint32_t)0x00000001)
#define FMC_ColumnBits_Number_10b ((uint32_t)0x00000002)
#define FMC_ColumnBits_Number_11b ((uint32_t)0x00000003)
/*
* FMC_RowBits_Number
*/
#define FMC_RowBits_Number_11b ((uint32_t)0x00000000)
#define FMC_RowBits_Number_12b ((uint32_t)0x00000004)
#define FMC_RowBits_Number_13b ((uint32_t)0x00000008)
/*
* FMC_SDMemory_Data_Width
*/
#define FMC_SDMemory_Width_8b ((uint32_t)0x00000000)
#define FMC_SDMemory_Width_16b ((uint32_t)0x00000010)
#define FMC_SDMemory_Width_32b ((uint32_t)0x00000020)
/*
* FMC_InternalBank_Number
*/
#define FMC_InternalBank_Number_2 ((uint32_t)0x00000000)
#define FMC_InternalBank_Number_4 ((uint32_t)0x00000040)
/*
* FMC_CAS_Latency
*/
#define FMC_CAS_Latency_1 ((uint32_t)0x00000080)
#define FMC_CAS_Latency_2 ((uint32_t)0x00000100)
#define FMC_CAS_Latency_3 ((uint32_t)0x00000180)
/*
* FMC_Write_Protection
*/
#define FMC_Write_Protection_Disable ((uint32_t)0x00000000)
#define FMC_Write_Protection_Enable ((uint32_t)0x00000200)
/*
******************************************************************************
* EXTERNS
@ -62,7 +141,7 @@ static const size_t extram_size = 1024*1024;
* SDRAM driver configuration structure.
*/
static const SDRAMConfig sdram_cfg = {
.sdcr1 = (uint32_t) FMC_ColumnBits_Number_9b |
.sdcr = (uint32_t) FMC_ColumnBits_Number_9b |
FMC_RowBits_Number_13b |
FMC_SDMemory_Width_16b |
FMC_InternalBank_Number_4 |
@ -71,13 +150,24 @@ static const SDRAMConfig sdram_cfg = {
FMC_SDClock_Period_3 |
FMC_Read_Burst_Enable |
FMC_ReadPipe_Delay_1,
.sdtr1 = (uint32_t) (2 - 1) | // FMC_LoadToActiveDelay = 2 (TMRD: 2 Clock cycles)
.sdtr = (uint32_t) (2 - 1) | // FMC_LoadToActiveDelay = 2 (TMRD: 2 Clock cycles)
(7 << 4) | // FMC_ExitSelfRefreshDelay = 7 (TXSR: min=70ns (7x11.11ns))
(4 << 8) | // FMC_SelfRefreshTime = 4 (TRAS: min=42ns (4x11.11ns) max=120k (ns))
(7 << 12) | // FMC_RowCycleDelay = 7 (TRC: min=70 (7x11.11ns))
(2 << 16) | // FMC_WriteRecoveryTime = 2 (TWR: min=1+ 7ns (1+1x11.11ns))
(2 << 20) | // FMC_RPDelay = 2 (TRP: 20ns => 2x11.11ns)
(2 << 24) // FMC_RCDDelay = 2 (TRCD: 20ns => 2x11.11ns)
(2 << 24), // FMC_RCDDelay = 2 (TRCD: 20ns => 2x11.11ns)
/* NRFS = 4-1*/
.sdcmr = (3 << 5) | (FMC_SDCMR_MRD_BURST_LENGTH_2 |
FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL |
FMC_SDCMR_MRD_CAS_LATENCY_3 |
FMC_SDCMR_MRD_OPERATING_MODE_STANDARD |
FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE) << 9,
/* if (STM32_SYSCLK == 180000000) ->
64ms/4096=15.625us
15.625us*90MHz=1406-20=1386 */
.sdrtr = 1386 << 1
};
/* benchmarking results in MiB/S */