L6406E: No space in execution regions with .ANY selector matching guidrv_stm32f429i_discovery.o(.bss).
#define GUI_NUMBYTES (1024 * 120) // x KByte
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include "stm32f4xx.h"
#include "stm32f4xx_fmc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_dma.h"
#include "misc.h"
#include "delay.h"
#include "fmc_sdram.h"
/**
* @brief FMC SDRAM Mode definition register defines
*/
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
static void FMC_GPIOConfig ( void );
static void SDRAM_Init(void);
static void SDRAM_InitSequence(void);
// Настройка FMC для LCD ( NAND16 mode, nCS=NCE2 )
static void FMC_LCD_Config ( void );
// Инициализация FMC
void FMC_Init ( void )
{
// GPIO configuration for FMC SDRAM bank
FMC_GPIOConfig ( );
// Enable FMC clock
RCC_AHB3PeriphClockCmd ( RCC_AHB3Periph_FMC, ENABLE );
// Настройка SDRAM контроллера
SDRAM_Init ( );
// Разрешить запись в SDRAM
FMC_SDRAMWriteProtectionConfig ( FMC_Bank1_SDRAM, DISABLE );
// Настройка FMC для LCD
FMC_LCD_Config ( );
} // FMC_Init
//////////////////////////////////////////////////
// LCD
// RS = 1 - данные
// RS = 0 - команды
// Maximum timeout value
#define TIMEOUT_MAX 10000
#define DMA_STREAM DMA2_Stream7
#define DMA_CHANNEL DMA_Channel_0
#define DMA_STREAM_CLOCK RCC_AHB1Periph_DMA2
#define DMA_STREAM_IRQ DMA2_Stream7_IRQn
#define DMA_STREAM_STATUS_BIT DMA_IT_TCIF7
#define LCD_BASE ((uint32_t)(0x70000000))
#define LCD_REG_ADDRESS (*(volatile uint16_t *)LCD_BASE )
#define LCD_DATA_ADDRESS (*(volatile uint16_t *)(LCD_BASE+0x10000))
// флаг завершения DMA передачи
static volatile bool isDmaTransferOk;
// Запись в регистр LCD
void FMC_LcdWriteReg ( uint8_t LCD_Reg, uint16_t LCD_RegValue )
{
LCD_REG_ADDRESS = LCD_Reg;
LCD_DATA_ADDRESS = LCD_RegValue;
} // FMC_LcdWriteReg
// Чтение регистра LCD
uint16_t FMC_LcdReadReg ( uint8_t LCD_Reg )
{
// Write 16-bit Index (then Read Reg)
LCD_REG_ADDRESS = LCD_Reg;
// Read 16-bit Reg
return LCD_DATA_ADDRESS;
} // FMC_LcdReadReg
// Запись команды в LCD
void FMC_LcdWriteCmd ( uint16_t val )
{
LCD_REG_ADDRESS = val;
} // FMC_LcdWriteCmd
// Запись данных в LCD
void FMC_LcdWriteData ( uint16_t val )
{
LCD_DATA_ADDRESS = val;
} // FMC_LcdWriteData
// чтение команды из LCD
uint16_t FMC_LcdReadCmd ( void )
{
return LCD_DATA_ADDRESS;
} // FMC_LcdWriteCmd
// чтение данных из LCD
uint16_t FMC_LcdReadData ( void )
{
return LCD_DATA_ADDRESS;
} // FMC_LcdWriteCmd
void FMC_TransferDataDMAToLCD ( void *buffer, uint32_t count, bool isRamAddressIncrement )
{
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
volatile uint32_t Timeout = TIMEOUT_MAX;
// ждать конца предыдущей передачи
// while ( !isDmaTransferOk );
isDmaTransferOk = false;
// Если длина не кратна 4 - не работаем
if ( count % 4 != 0 )
return;
// длина буфера в DWORD
count /= 4;
// Enable DMA lock
RCC_AHB1PeriphClockCmd ( DMA_STREAM_CLOCK, ENABLE );
// Reset DMA Stream registers (for debug purpose)
DMA_DeInit ( DMA_STREAM );
// Check if the DMA Stream is disabled before enabling it.
// Note that this step is useful when the same Stream is used multiple times:
// enabled, then disabled then re-enabled... In this case, the DMA Stream disable
// will be effective only at the end of the ongoing data transfer and it will
// not be possible to re-configure it before making sure that the Enable bit
// has been cleared by hardware. If the Stream is used only once, this step might
// be bypassed.
while ( DMA_GetCmdStatus ( DMA_STREAM ) != DISABLE );
// Configure DMA Stream
DMA_InitStructure.DMA_Channel = DMA_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)buffer;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(&(LCD_DATA_ADDRESS));
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;
DMA_InitStructure.DMA_BufferSize = count;
if ( isRamAddressIncrement )
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
else
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init ( DMA_STREAM, &DMA_InitStructure );
// Enable DMA Stream Transfer Complete interrupt
DMA_ITConfig ( DMA_STREAM, DMA_IT_TC, ENABLE );
// DMA Stream enable
DMA_Cmd ( DMA_STREAM, ENABLE );
// Check if the DMA Stream has been effectively enabled.
// The DMA Stream Enable bit is cleared immediately by hardware if there is an
// error in the configuration parameters and the transfer is no started (ie. when
// wrong FIFO threshold is configured ...)
Timeout = TIMEOUT_MAX;
while ( (DMA_GetCmdStatus(DMA_STREAM) != ENABLE) && (Timeout-- > 0) );
// Check if a timeout condition occurred
if (Timeout == 0)
{ // Manage the error: to simplify the code enter an infinite loop
while (1);
} // if
// Enable the DMA Stream IRQ Channel
NVIC_InitStructure.NVIC_IRQChannel = DMA_STREAM_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init ( &NVIC_InitStructure );
// ждать конца передачи
while ( !isDmaTransferOk );
} // FMC_TransferDataDMAToLCD
/////////////////////////////////////////////////////////////////////////////////
// Внутренние функции
// Прерывание DMA2 по завершению передачи (Используется для LCD)
void DMA2_Stream7_IRQHandler ( void )
{
// Test on DMA Stream Transfer Complete interrupt
/*
if ( DMA_GetITStatus(DMA_STREAM, DMA_IT_TCIF0 ) )
{
// Clear DMA Stream Transfer Complete interrupt pending bit
DMA_ClearITPendingBit ( DMA_STREAM, DMA_IT_TCIF0 );
isDmaTransferOk = true;
} // if
*/
if ( DMA_GetITStatus(DMA_STREAM, DMA_STREAM_STATUS_BIT ) )
{
// Clear DMA Stream Transfer Complete interrupt pending bit
DMA_ClearITPendingBit ( DMA_STREAM, DMA_STREAM_STATUS_BIT );
isDmaTransferOk = true;
} // if
} // DMA2_Stream7_IRQHandler
/**
* @brief Configures the FMC and GPIOs to interface with the SDRAM memory.
* This function must be called before any read/write operation
* on the SDRAM.
* @param None
* @retval None
*/
static void SDRAM_Init ( void )
{
FMC_SDRAMInitTypeDef FMC_SDRAMInitStructure;
FMC_SDRAMTimingInitTypeDef FMC_SDRAMTimingInitStructure;
// FMC Configuration ---------------------------------------------------------
// FMC SDRAM Bank configuration
// Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) -- 1 cycle = 11.11 ns
// TMRD: 2 Clock cycles
FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay = 2;
// TXSR: min=67ns (7x11.11ns) -- 7 cycles
FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7;
// TRAS: min=42ns (4x11.11ns) max=120k (ns) -- 4 cycles
FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime = 4;
// TRC: min=70ns (6x11.11ns) -- 6 cycles
FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay = 6;
// TWR: min=1+ 6ns (1+1x11.11ns) -- 2 cycles
FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime = 2;
// TRP: 18ns => 2x11.11ns -- 2 cycles
FMC_SDRAMTimingInitStructure.FMC_RPDelay = 2;
// TRCD: 18ns => 2x11.11ns -- 2 cycles
FMC_SDRAMTimingInitStructure.FMC_RCDDelay = 2;
// FMC SDRAM control configuration
FMC_SDRAMInitStructure.FMC_Bank = FMC_Bank1_SDRAM; // 0
// Col addressing: [8:0] - 9 bits
FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_9b; // 0x00000001
// Row addressing: [12:0] - 13 bits
FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_13b; // 0x00000008
FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = FMC_SDMemory_Width_16b; // 0x00000010
FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4; // 0x00000040
// CL: Cas Latency = 3 clock cycles
FMC_SDRAMInitStructure.FMC_CASLatency = FMC_CAS_Latency_3; // 0x00000180
FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable; // 0x00000000
// 90 MHz
// FMC_SDRAMInitStructure.FMC_SDClockPeriod = FMC_SDClock_Period_2; // 0x00000800
// 60 MHz
FMC_SDRAMInitStructure.FMC_SDClockPeriod = FMC_SDClock_Period_3; // 0x00000800
FMC_SDRAMInitStructure.FMC_ReadBurst = FMC_Read_Burst_Enable; // 0x00001000
FMC_SDRAMInitStructure.FMC_ReadBurst = FMC_Read_Burst_Disable;
FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_1; // 0x00002000
FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;
// FMC SDRAM bank initialization
FMC_SDRAMInit ( &FMC_SDRAMInitStructure );
// FMC SDRAM device initialization sequence
SDRAM_InitSequence ( );
} // SDRAM_Init
/**
* @brief Configures all SDRAM memory I/Os pins.
* @param None.
* @retval None.
*/
static void FMC_GPIOConfig ( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
// Enable GPIOs clock
RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD |
RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF |
RCC_AHB1Periph_GPIOG, ENABLE );
/* PC, PD, PE, PF, PG
A0 - PF0 + D0 - PD14 +
A1 - PF1 + D1 - PD15 +
A2 - PF2 + D2 - PD0 +
A3 - PF3 + D3 - PD1 +
A4 - PF4 + D4 - PE7 +
A5 - PF5 + D5 - PE8 +
A6 - PF12 + D6 - PE9 +
A7 - PF13 + D7 - PE10 +
A8 - PF14 + D8 - PE11 +
A9 - PF15 + D9 - PE12 +
A10 - PG0 + D10 - PE13 +
A11 - PG1 + D11 - PE14 +
A12 - PG2 + D12 - PE15 +
D13 - PD8 +
BA0 - PG4 + D14 - PD9 +
BA1 - PG5 + D15 - PD10 +
nWE - PC0 FMC_SDNWE +
nCS - PC2 FMC_SDNE0 +
CKE - PC3 FMC_SDCKE0 +
DQML - PE0 FMC_NBL0 +
DQMH - PE1 FMC_NBL1 +
nRAS - PF11 FMC_NRAS +
CLK - PG8 FMC_SDCLK +
nCAS - PG15 FMC_NCAS +
LCD:
// LCD nRD - NOE (PD4)
// LCD nWR - NWE (PD5)
// LCD nCS - NCE2 (PD7)
// LCD RS - CLE (PD11)
PC0, PC2, PC3
PD0, PD1, PD4, PD5, PD7, PD8, PD9, PD10, PD11, PD14, PD15
PE0, PE1, PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15
PF0, PF1, PF2, PF3, PF4, PF5, PF11, PF12, PF13, PF14, PF15
PG0, PG1, PG2, PG4, PG5, PG8, PG15
*/
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
/////////////
// GPIOC
// PC0, PC2, PC3
GPIO_PinAFConfig ( GPIOC, GPIO_PinSource0, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOC, GPIO_PinSource2, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOC, GPIO_PinSource3, GPIO_AF_FMC );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_Init ( GPIOC, &GPIO_InitStructure );
/////////////
/////////////
// GPIOD
// Neaiaeu aey LCD:
// LCD nRD - NOE (PD4)
// LCD nWR - NWE (PD5)
// LCD nCS - NCE2 (PD7)
// LCD RS - CLE (PD11)
// PD0, PD1, PD4, PD5, PD7, PD8, PD9, PD10, PD11, PD14, PD15
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource0, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource1, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource4, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource5, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource7, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource8, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource9, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource10, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource11, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource14, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource15, GPIO_AF_FMC );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 |
GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init ( GPIOD, &GPIO_InitStructure );
/////////////
/////////////
// GPIOE
// PE0, PE1, PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource0, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource1, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource7, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource8, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource9, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource10, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource11, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource12, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource13, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource14, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource15, GPIO_AF_FMC );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init ( GPIOE, &GPIO_InitStructure );
/////////////
/////////////
// GPIOF
// PF0, PF1, PF2, PF3, PF4, PF5, PF11, PF12, PF13, PF14, PF15
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource0, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource1, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource2, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource3, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource4, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource5, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource11, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource12, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource13, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource14, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource15, GPIO_AF_FMC );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 |
GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init ( GPIOF, &GPIO_InitStructure );
/////////////
/////////////
// GPIOG
// PG0, PG1, PG2, PG4, PG5, PG8, PG15
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource0, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource1, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource4, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource5, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource8, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource15, GPIO_AF_FMC);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_4 |
GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_15;
GPIO_Init ( GPIOG, &GPIO_InitStructure );
/////////////
} // SDRAM_GPIOConfig
// Настройка FMC для LCD ( NAND16 mode, nCS=NCE2 )
static void FMC_LCD_Config ( void )
{
FMC_NAND_PCCARDTimingInitTypeDef FMC_NANDTiming;
FMC_NANDInitTypeDef FMC_NAND;
FMC_NANDTiming.FMC_HiZSetupTime = 15; //2;//1;
FMC_NANDTiming.FMC_HoldSetupTime = 15; //2;//2;
FMC_NANDTiming.FMC_SetupTime = 15; //1;//1;
FMC_NANDTiming.FMC_WaitSetupTime = 15; //4;//3;
FMC_NAND.FMC_Bank = FMC_Bank2_NAND;
FMC_NAND.FMC_AttributeSpaceTimingStruct = &FMC_NANDTiming;
FMC_NAND.FMC_CommonSpaceTimingStruct = &FMC_NANDTiming;
FMC_NAND.FMC_ECC = FMC_ECC_Disable;
FMC_NAND.FMC_ECCPageSize = FMC_ECCPageSize_512Bytes;
FMC_NAND.FMC_MemoryDataWidth = FMC_NAND_MemoryDataWidth_16b;
FMC_NAND.FMC_TARSetupTime = 0;
FMC_NAND.FMC_TCLRSetupTime = 0;
FMC_NAND.FMC_Waitfeature = FMC_Waitfeature_Disable;
FMC_NANDInit ( &FMC_NAND );
// FMC Enable
FMC_NANDCmd ( FMC_Bank2_NAND, ENABLE );
} // FMC_LCD_Config
////////////////////////////////////////////////////////////////////////////
// Настройка контроллера SDRAM
static void __Delay ( uint32_t nCount )
{
volatile uint32_t index = 0;
for ( index = (100000 * nCount); index != 0; index -- );
} // __Delay
/**
* @brief Executes the SDRAM memory initialization sequence.
* @param None.
* @retval None.
*/
static void SDRAM_InitSequence ( void )
{
FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;
uint32_t tmpr = 0;
/* Step 3 --------------------------------------------------------------------*/
/* Configure a clock configuration enable command */
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled; // 001 - Clock Config Enabls
// FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1_2;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; // Don't need for 001
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while ( FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET );
/* Send the command */
FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
/* Step 4 --------------------------------------------------------------------*/
/* Insert 100 ms delay */
__Delay(10);
/* Step 5 --------------------------------------------------------------------*/
/* Configure a PALL (precharge all) command */
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL; // 010 - PALL command
// FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1_2;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; // Don't need for 010
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while ( FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET );
/* Send the command */
FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
/* Step 6 --------------------------------------------------------------------*/
/* Configure a Auto-Refresh command */
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh; // 011 - Auto Refresh command
// FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1_2;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 8; // Need for 011 - 8 Auto Refresh Cycles
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while ( FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET );
/* Send the first command */
FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
#if 0
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET );
/* Send the second command */
FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
#endif
/* Step 7 --------------------------------------------------------------------*/
/* Program the external memory mode register - SDCMR, p.1650 */
// Format of reg - Page 47 of MT48LCxxMxx.pdf
/*
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
*/
// = 0x0030 -- CAS latency = 3
// = 0x0200 -- Single location Address
tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_3 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
/* Configure a load Mode register command*/
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode; // 100 - Load Mode Reg
// FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1_2;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; // Don't need for 100
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;
/* Wait until the SDRAM controller is ready */
while ( FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET );
/* Send the command */
FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
/* Step 8 --------------------------------------------------------------------*/
/* Set the refresh rate counter */
#if 0
/* (15.62 us x Freq) - 20 */
/* Set the device refresh counter */
FMC_SetRefreshCount ( 1730 );//730
#endif
/* Set the refresh rate counter */
/* (15.62 us x Freq) - 20 */
/* Set the device refresh counter - SDRTR reg */
FMC_SetRefreshCount ( 1385 );
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET);
} // SDRAM_InitSequence
#define GUI_NUMBYTES (1024 * 120) // x KByte
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include "stm32f4xx.h"
#include "stm32f4xx_fmc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_dma.h"
#include "misc.h"
#include "delay.h"
#include "fmc_sdram.h"
/**
* @brief FMC SDRAM Mode definition register defines
*/
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
static void FMC_GPIOConfig ( void );
static void SDRAM_Init(void);
static void SDRAM_InitSequence(void);
// Настройка FMC для LCD ( NAND16 mode, nCS=NCE2 )
static void FMC_LCD_Config ( void );
// Инициализация FMC
void FMC_Init ( void )
{
// GPIO configuration for FMC SDRAM bank
FMC_GPIOConfig ( );
// Enable FMC clock
RCC_AHB3PeriphClockCmd ( RCC_AHB3Periph_FMC, ENABLE );
// Настройка SDRAM контроллера
SDRAM_Init ( );
// Разрешить запись в SDRAM
FMC_SDRAMWriteProtectionConfig ( FMC_Bank1_SDRAM, DISABLE );
// Настройка FMC для LCD
FMC_LCD_Config ( );
} // FMC_Init
//////////////////////////////////////////////////
// LCD
// RS = 1 - данные
// RS = 0 - команды
// Maximum timeout value
#define TIMEOUT_MAX 10000
#define DMA_STREAM DMA2_Stream7
#define DMA_CHANNEL DMA_Channel_0
#define DMA_STREAM_CLOCK RCC_AHB1Periph_DMA2
#define DMA_STREAM_IRQ DMA2_Stream7_IRQn
#define DMA_STREAM_STATUS_BIT DMA_IT_TCIF7
#define LCD_BASE ((uint32_t)(0x70000000))
#define LCD_REG_ADDRESS (*(volatile uint16_t *)LCD_BASE )
#define LCD_DATA_ADDRESS (*(volatile uint16_t *)(LCD_BASE+0x10000))
// флаг завершения DMA передачи
static volatile bool isDmaTransferOk;
// Запись в регистр LCD
void FMC_LcdWriteReg ( uint8_t LCD_Reg, uint16_t LCD_RegValue )
{
LCD_REG_ADDRESS = LCD_Reg;
LCD_DATA_ADDRESS = LCD_RegValue;
} // FMC_LcdWriteReg
// Чтение регистра LCD
uint16_t FMC_LcdReadReg ( uint8_t LCD_Reg )
{
// Write 16-bit Index (then Read Reg)
LCD_REG_ADDRESS = LCD_Reg;
// Read 16-bit Reg
return LCD_DATA_ADDRESS;
} // FMC_LcdReadReg
// Запись команды в LCD
void FMC_LcdWriteCmd ( uint16_t val )
{
LCD_REG_ADDRESS = val;
} // FMC_LcdWriteCmd
// Запись данных в LCD
void FMC_LcdWriteData ( uint16_t val )
{
LCD_DATA_ADDRESS = val;
} // FMC_LcdWriteData
// чтение команды из LCD
uint16_t FMC_LcdReadCmd ( void )
{
return LCD_DATA_ADDRESS;
} // FMC_LcdWriteCmd
// чтение данных из LCD
uint16_t FMC_LcdReadData ( void )
{
return LCD_DATA_ADDRESS;
} // FMC_LcdWriteCmd
void FMC_TransferDataDMAToLCD ( void *buffer, uint32_t count, bool isRamAddressIncrement )
{
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
volatile uint32_t Timeout = TIMEOUT_MAX;
// ждать конца предыдущей передачи
// while ( !isDmaTransferOk );
isDmaTransferOk = false;
// Если длина не кратна 4 - не работаем
if ( count % 4 != 0 )
return;
// длина буфера в DWORD
count /= 4;
// Enable DMA lock
RCC_AHB1PeriphClockCmd ( DMA_STREAM_CLOCK, ENABLE );
// Reset DMA Stream registers (for debug purpose)
DMA_DeInit ( DMA_STREAM );
// Check if the DMA Stream is disabled before enabling it.
// Note that this step is useful when the same Stream is used multiple times:
// enabled, then disabled then re-enabled... In this case, the DMA Stream disable
// will be effective only at the end of the ongoing data transfer and it will
// not be possible to re-configure it before making sure that the Enable bit
// has been cleared by hardware. If the Stream is used only once, this step might
// be bypassed.
while ( DMA_GetCmdStatus ( DMA_STREAM ) != DISABLE );
// Configure DMA Stream
DMA_InitStructure.DMA_Channel = DMA_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)buffer;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(&(LCD_DATA_ADDRESS));
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;
DMA_InitStructure.DMA_BufferSize = count;
if ( isRamAddressIncrement )
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
else
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init ( DMA_STREAM, &DMA_InitStructure );
// Enable DMA Stream Transfer Complete interrupt
DMA_ITConfig ( DMA_STREAM, DMA_IT_TC, ENABLE );
// DMA Stream enable
DMA_Cmd ( DMA_STREAM, ENABLE );
// Check if the DMA Stream has been effectively enabled.
// The DMA Stream Enable bit is cleared immediately by hardware if there is an
// error in the configuration parameters and the transfer is no started (ie. when
// wrong FIFO threshold is configured ...)
Timeout = TIMEOUT_MAX;
while ( (DMA_GetCmdStatus(DMA_STREAM) != ENABLE) && (Timeout-- > 0) );
// Check if a timeout condition occurred
if (Timeout == 0)
{ // Manage the error: to simplify the code enter an infinite loop
while (1);
} // if
// Enable the DMA Stream IRQ Channel
NVIC_InitStructure.NVIC_IRQChannel = DMA_STREAM_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init ( &NVIC_InitStructure );
// ждать конца передачи
while ( !isDmaTransferOk );
} // FMC_TransferDataDMAToLCD
/////////////////////////////////////////////////////////////////////////////////
// Внутренние функции
// Прерывание DMA2 по завершению передачи (Используется для LCD)
void DMA2_Stream7_IRQHandler ( void )
{
// Test on DMA Stream Transfer Complete interrupt
/*
if ( DMA_GetITStatus(DMA_STREAM, DMA_IT_TCIF0 ) )
{
// Clear DMA Stream Transfer Complete interrupt pending bit
DMA_ClearITPendingBit ( DMA_STREAM, DMA_IT_TCIF0 );
isDmaTransferOk = true;
} // if
*/
if ( DMA_GetITStatus(DMA_STREAM, DMA_STREAM_STATUS_BIT ) )
{
// Clear DMA Stream Transfer Complete interrupt pending bit
DMA_ClearITPendingBit ( DMA_STREAM, DMA_STREAM_STATUS_BIT );
isDmaTransferOk = true;
} // if
} // DMA2_Stream7_IRQHandler
/**
* @brief Configures the FMC and GPIOs to interface with the SDRAM memory.
* This function must be called before any read/write operation
* on the SDRAM.
* @param None
* @retval None
*/
static void SDRAM_Init ( void )
{
FMC_SDRAMInitTypeDef FMC_SDRAMInitStructure;
FMC_SDRAMTimingInitTypeDef FMC_SDRAMTimingInitStructure;
// FMC Configuration ---------------------------------------------------------
// FMC SDRAM Bank configuration
// Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) -- 1 cycle = 11.11 ns
// TMRD: 2 Clock cycles
FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay = 2;
// TXSR: min=67ns (7x11.11ns) -- 7 cycles
FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7;
// TRAS: min=42ns (4x11.11ns) max=120k (ns) -- 4 cycles
FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime = 4;
// TRC: min=70ns (6x11.11ns) -- 6 cycles
FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay = 6;
// TWR: min=1+ 6ns (1+1x11.11ns) -- 2 cycles
FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime = 2;
// TRP: 18ns => 2x11.11ns -- 2 cycles
FMC_SDRAMTimingInitStructure.FMC_RPDelay = 2;
// TRCD: 18ns => 2x11.11ns -- 2 cycles
FMC_SDRAMTimingInitStructure.FMC_RCDDelay = 2;
// FMC SDRAM control configuration
FMC_SDRAMInitStructure.FMC_Bank = FMC_Bank1_SDRAM; // 0
// Col addressing: [8:0] - 9 bits
FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_9b; // 0x00000001
// Row addressing: [12:0] - 13 bits
FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_13b; // 0x00000008
FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = FMC_SDMemory_Width_16b; // 0x00000010
FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4; // 0x00000040
// CL: Cas Latency = 3 clock cycles
FMC_SDRAMInitStructure.FMC_CASLatency = FMC_CAS_Latency_3; // 0x00000180
FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable; // 0x00000000
// 90 MHz
// FMC_SDRAMInitStructure.FMC_SDClockPeriod = FMC_SDClock_Period_2; // 0x00000800
// 60 MHz
FMC_SDRAMInitStructure.FMC_SDClockPeriod = FMC_SDClock_Period_3; // 0x00000800
FMC_SDRAMInitStructure.FMC_ReadBurst = FMC_Read_Burst_Enable; // 0x00001000
FMC_SDRAMInitStructure.FMC_ReadBurst = FMC_Read_Burst_Disable;
FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_1; // 0x00002000
FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;
// FMC SDRAM bank initialization
FMC_SDRAMInit ( &FMC_SDRAMInitStructure );
// FMC SDRAM device initialization sequence
SDRAM_InitSequence ( );
} // SDRAM_Init
/**
* @brief Configures all SDRAM memory I/Os pins.
* @param None.
* @retval None.
*/
static void FMC_GPIOConfig ( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
// Enable GPIOs clock
RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD |
RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF |
RCC_AHB1Periph_GPIOG, ENABLE );
/* PC, PD, PE, PF, PG
A0 - PF0 + D0 - PD14 +
A1 - PF1 + D1 - PD15 +
A2 - PF2 + D2 - PD0 +
A3 - PF3 + D3 - PD1 +
A4 - PF4 + D4 - PE7 +
A5 - PF5 + D5 - PE8 +
A6 - PF12 + D6 - PE9 +
A7 - PF13 + D7 - PE10 +
A8 - PF14 + D8 - PE11 +
A9 - PF15 + D9 - PE12 +
A10 - PG0 + D10 - PE13 +
A11 - PG1 + D11 - PE14 +
A12 - PG2 + D12 - PE15 +
D13 - PD8 +
BA0 - PG4 + D14 - PD9 +
BA1 - PG5 + D15 - PD10 +
nWE - PC0 FMC_SDNWE +
nCS - PC2 FMC_SDNE0 +
CKE - PC3 FMC_SDCKE0 +
DQML - PE0 FMC_NBL0 +
DQMH - PE1 FMC_NBL1 +
nRAS - PF11 FMC_NRAS +
CLK - PG8 FMC_SDCLK +
nCAS - PG15 FMC_NCAS +
LCD:
// LCD nRD - NOE (PD4)
// LCD nWR - NWE (PD5)
// LCD nCS - NCE2 (PD7)
// LCD RS - CLE (PD11)
PC0, PC2, PC3
PD0, PD1, PD4, PD5, PD7, PD8, PD9, PD10, PD11, PD14, PD15
PE0, PE1, PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15
PF0, PF1, PF2, PF3, PF4, PF5, PF11, PF12, PF13, PF14, PF15
PG0, PG1, PG2, PG4, PG5, PG8, PG15
*/
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
/////////////
// GPIOC
// PC0, PC2, PC3
GPIO_PinAFConfig ( GPIOC, GPIO_PinSource0, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOC, GPIO_PinSource2, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOC, GPIO_PinSource3, GPIO_AF_FMC );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_Init ( GPIOC, &GPIO_InitStructure );
/////////////
/////////////
// GPIOD
// Neaiaeu aey LCD:
// LCD nRD - NOE (PD4)
// LCD nWR - NWE (PD5)
// LCD nCS - NCE2 (PD7)
// LCD RS - CLE (PD11)
// PD0, PD1, PD4, PD5, PD7, PD8, PD9, PD10, PD11, PD14, PD15
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource0, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource1, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource4, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource5, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource7, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource8, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource9, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource10, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource11, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource14, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOD, GPIO_PinSource15, GPIO_AF_FMC );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 |
GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init ( GPIOD, &GPIO_InitStructure );
/////////////
/////////////
// GPIOE
// PE0, PE1, PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource0, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource1, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource7, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource8, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource9, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource10, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource11, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource12, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource13, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource14, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOE, GPIO_PinSource15, GPIO_AF_FMC );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init ( GPIOE, &GPIO_InitStructure );
/////////////
/////////////
// GPIOF
// PF0, PF1, PF2, PF3, PF4, PF5, PF11, PF12, PF13, PF14, PF15
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource0, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource1, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource2, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource3, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource4, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource5, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource11, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource12, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource13, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource14, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOF, GPIO_PinSource15, GPIO_AF_FMC );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 |
GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init ( GPIOF, &GPIO_InitStructure );
/////////////
/////////////
// GPIOG
// PG0, PG1, PG2, PG4, PG5, PG8, PG15
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource0, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource1, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource4, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource5, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource8, GPIO_AF_FMC );
GPIO_PinAFConfig ( GPIOG, GPIO_PinSource15, GPIO_AF_FMC);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_4 |
GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_15;
GPIO_Init ( GPIOG, &GPIO_InitStructure );
/////////////
} // SDRAM_GPIOConfig
// Настройка FMC для LCD ( NAND16 mode, nCS=NCE2 )
static void FMC_LCD_Config ( void )
{
FMC_NAND_PCCARDTimingInitTypeDef FMC_NANDTiming;
FMC_NANDInitTypeDef FMC_NAND;
FMC_NANDTiming.FMC_HiZSetupTime = 15; //2;//1;
FMC_NANDTiming.FMC_HoldSetupTime = 15; //2;//2;
FMC_NANDTiming.FMC_SetupTime = 15; //1;//1;
FMC_NANDTiming.FMC_WaitSetupTime = 15; //4;//3;
FMC_NAND.FMC_Bank = FMC_Bank2_NAND;
FMC_NAND.FMC_AttributeSpaceTimingStruct = &FMC_NANDTiming;
FMC_NAND.FMC_CommonSpaceTimingStruct = &FMC_NANDTiming;
FMC_NAND.FMC_ECC = FMC_ECC_Disable;
FMC_NAND.FMC_ECCPageSize = FMC_ECCPageSize_512Bytes;
FMC_NAND.FMC_MemoryDataWidth = FMC_NAND_MemoryDataWidth_16b;
FMC_NAND.FMC_TARSetupTime = 0;
FMC_NAND.FMC_TCLRSetupTime = 0;
FMC_NAND.FMC_Waitfeature = FMC_Waitfeature_Disable;
FMC_NANDInit ( &FMC_NAND );
// FMC Enable
FMC_NANDCmd ( FMC_Bank2_NAND, ENABLE );
} // FMC_LCD_Config
////////////////////////////////////////////////////////////////////////////
// Настройка контроллера SDRAM
static void __Delay ( uint32_t nCount )
{
volatile uint32_t index = 0;
for ( index = (100000 * nCount); index != 0; index -- );
} // __Delay
/**
* @brief Executes the SDRAM memory initialization sequence.
* @param None.
* @retval None.
*/
static void SDRAM_InitSequence ( void )
{
FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;
uint32_t tmpr = 0;
/* Step 3 --------------------------------------------------------------------*/
/* Configure a clock configuration enable command */
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled; // 001 - Clock Config Enabls
// FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1_2;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; // Don't need for 001
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while ( FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET );
/* Send the command */
FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
/* Step 4 --------------------------------------------------------------------*/
/* Insert 100 ms delay */
__Delay(10);
/* Step 5 --------------------------------------------------------------------*/
/* Configure a PALL (precharge all) command */
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL; // 010 - PALL command
// FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1_2;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; // Don't need for 010
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while ( FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET );
/* Send the command */
FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
/* Step 6 --------------------------------------------------------------------*/
/* Configure a Auto-Refresh command */
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh; // 011 - Auto Refresh command
// FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1_2;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 8; // Need for 011 - 8 Auto Refresh Cycles
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while ( FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET );
/* Send the first command */
FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
#if 0
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET );
/* Send the second command */
FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
#endif
/* Step 7 --------------------------------------------------------------------*/
/* Program the external memory mode register - SDCMR, p.1650 */
// Format of reg - Page 47 of MT48LCxxMxx.pdf
/*
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
*/
// = 0x0030 -- CAS latency = 3
// = 0x0200 -- Single location Address
tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_3 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
/* Configure a load Mode register command*/
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode; // 100 - Load Mode Reg
// FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1_2;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; // Don't need for 100
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;
/* Wait until the SDRAM controller is ready */
while ( FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET );
/* Send the command */
FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
/* Step 8 --------------------------------------------------------------------*/
/* Set the refresh rate counter */
#if 0
/* (15.62 us x Freq) - 20 */
/* Set the device refresh counter */
FMC_SetRefreshCount ( 1730 );//730
#endif
/* Set the refresh rate counter */
/* (15.62 us x Freq) - 20 */
/* Set the device refresh counter - SDRTR reg */
FMC_SetRefreshCount ( 1385 );
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus ( FMC_Bank1_SDRAM, FMC_FLAG_Busy ) != RESET);
} // SDRAM_InitSequence
Комментариев нет:
Отправить комментарий