cancel
Showing results for 
Search instead for 
Did you mean: 

Work with FMC (STM32F427)

Pilous Droip
Senior

Hello.

I have Init FMC, but when I try write on it, it doesn´t work.

And I have a problem, data is send double, and timing is wrong. I think I have problem with init. Can anybody help me with init this pheripheral?

And my test write function is here:

#define BANK_ADDR ((uint32_t)0x64000000)
#define FMCWRITE(uAdr,ucVal)\
		*(__IO uint16_t *) (BANK_ADDR + (uAdr))=(ucVal)

Init function is here:

void initFMC(void)
{
	FMC_pins();
 
	LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_FMC);
 
	FMC_NORSRAM_InitTypeDef Init;
	FMC_NORSRAM_TimingTypeDef Timing;
 
	FMC_NORSRAM_TypeDef *Instance;
	FMC_NORSRAM_EXTENDED_TypeDef *Extended;
 
	Instance = FMC_NORSRAM_DEVICE;
	Extended = FMC_NORSRAM_EXTENDED_DEVICE;
 
	Init.NSBank = FMC_NORSRAM_BANK2;
	Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_ENABLE;
	Init.MemoryType = FMC_MEMORY_TYPE_PSRAM;
	Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
	Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
	Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
	Init.WrapMode = FMC_WRAP_MODE_DISABLE;
	Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
	Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
	Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
	Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
	Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
	Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
	Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
 
	/* Timing */
	//Timint 168Mhz = 6ns
	Timing.AddressSetupTime = 11;
	Timing.AddressHoldTime = 2;
	Timing.DataSetupTime = 16;
	Timing.BusTurnAroundDuration = 6;
	Timing.CLKDivision = 16;
	Timing.DataLatency = 17;
	Timing.AccessMode = FMC_ACCESS_MODE_A;
 
	FMC_NORSRAM_Init(Instance, &Init);
	FMC_NORSRAM_Timing_Init(Instance, &Timing, Init.NSBank);
	FMC_NORSRAM_Extended_Timing_Init(Extended, NULL, Init.NSBank, Init.ExtendedMode);
 
	__FMC_NORSRAM_ENABLE(Instance, Init.NSBank);
}

Other function:

ErrorStatus FMC_NORSRAM_Init(FMC_NORSRAM_TypeDef *Device, FMC_NORSRAM_InitTypeDef* Init) {
 
	uint32_t tmpr = 0U;
 
	/* Get the BTCR register value */
	tmpr = Device->BTCR[Init->NSBank];
 
	/* Clear MBKEN, MUXEN, MTYP, MWID, FACCEN, BURSTEN, WAITPOL, WRAPMOD, WAITCFG, WREN,
	 	 	 WAITEN, EXTMOD, ASYNCWAIT, CPSIZE, CBURSTRW and CCLKEN bits */
	tmpr &= ((uint32_t)~(FMC_BCR1_MBKEN     | FMC_BCR1_MUXEN    | FMC_BCR1_MTYP     | \
	                     FMC_BCR1_MWID      | FMC_BCR1_FACCEN   | FMC_BCR1_BURSTEN  | \
						 FMC_BCR1_WAITPOL   | FMC_BCR1_WRAPMOD  | FMC_BCR1_WAITCFG  | \
						 FMC_BCR1_WREN      | FMC_BCR1_WAITEN   | FMC_BCR1_EXTMOD   | \
						 FMC_BCR1_ASYNCWAIT | FMC_BCR1_CPSIZE   | FMC_BCR1_CBURSTRW | \
						 FMC_BCR1_CCLKEN));
 
	/* Set NORSRAM device control parameters */
	  tmpr |= (uint32_t)(Init->DataAddressMux      |\
	                    Init->MemoryType           |\
	                    Init->MemoryDataWidth      |\
	                    Init->BurstAccessMode      |\
	                    Init->WaitSignalPolarity   |\
	                    Init->WrapMode             |\
	                    Init->WaitSignalActive     |\
	                    Init->WriteOperation       |\
	                    Init->WaitSignal           |\
	                    Init->ExtendedMode         |\
	                    Init->AsynchronousWait     |\
	                    Init->PageSize             |\
	                    Init->WriteBurst           |\
	                    Init->ContinuousClock);
 
	if (Init->MemoryType == FMC_MEMORY_TYPE_NOR) {
		tmpr |= (uint32_t) FMC_NORSRAM_FLASH_ACCESS_ENABLE;
	}
 
	Device->BTCR[Init->NSBank] = tmpr;
 
	/* Configure synchronous mode when Continuous clock is enabled for bank2..4 */
	if ((Init->ContinuousClock == FMC_CONTINUOUS_CLOCK_SYNC_ASYNC) && (Init->NSBank != FMC_NORSRAM_BANK1)) {
		Device->BTCR[FMC_NORSRAM_BANK1] |= (uint32_t) (Init->ContinuousClock);
	}
 
	return 0;
}
 
ErrorStatus FMC_NORSRAM_DeInit(FMC_NORSRAM_TypeDef *Device, FMC_NORSRAM_EXTENDED_TypeDef *ExDevice, uint32_t Bank) {
	/* Disable the FMC_NORSRAM device */
	__FMC_NORSRAM_DISABLE(Device, Bank);
 
	/* De-initialize the FMC_NORSRAM device */
	/* FMC_NORSRAM_BANK1 */
	if (Bank == FMC_NORSRAM_BANK1) {
		Device->BTCR[Bank] = 0x000030DB;
	}
	/* FMC_NORSRAM_BANK2, FMC_NORSRAM_BANK3 or FMC_NORSRAM_BANK4 */
	else {
		Device->BTCR[Bank] = 0x000030D2;
	}
 
	Device->BTCR[Bank + 1] = 0x0FFFFFFF;
	ExDevice->BWTR[Bank] = 0x0FFFFFFF;
 
	return 0;
}
 
ErrorStatus FMC_NORSRAM_Timing_Init(FMC_NORSRAM_TypeDef *Device, FMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank) {
	uint32_t tmpr = 0U;
 
	/* Get the BTCR register value */
	tmpr = Device->BTCR[Bank + 1U];
 
	/* Clear ADDSET, ADDHLD, DATAST, BUSTURN, CLKDIV, DATLAT and ACCMOD bits */
	tmpr &= ((uint32_t) ~(FMC_BTR1_ADDSET | FMC_BTR1_ADDHLD | FMC_BTR1_DATAST |
	FMC_BTR1_BUSTURN | FMC_BTR1_CLKDIV | FMC_BTR1_DATLAT |
	FMC_BTR1_ACCMOD));
 
	/* Set FMC_NORSRAM device timing parameters */
	tmpr |= (uint32_t) (Timing->AddressSetupTime 				|\
					  ((Timing->AddressHoldTime) << 4U) 		|\
					  ((Timing->DataSetupTime) << 8U) 			|\
					  ((Timing->BusTurnAroundDuration) << 16U) 	|\
					 (((Timing->CLKDivision) - 1U) << 20U) 		|\
					 (((Timing->DataLatency) - 2U) << 24U) 		|\
					   (Timing->AccessMode));
 
	Device->BTCR[Bank + 1U] = tmpr;
 
	/* Configure Clock division value (in NORSRAM bank 1) when continuous clock is enabled */
	if (FMC_IS_BIT_SET(Device->BTCR[FMC_NORSRAM_BANK1], FMC_BCR1_CCLKEN)) {
		tmpr = (uint32_t) (Device->BTCR[FMC_NORSRAM_BANK1 + 1U] & ~(0x0FU << 20U));
		tmpr |= (uint32_t) (((Timing->CLKDivision) - 1U) << 20U);
		Device->BTCR[FMC_NORSRAM_BANK1 + 1U] = tmpr;
	}
 
	return 0;
}
 
ErrorStatus  FMC_NORSRAM_Extended_Timing_Init(FMC_NORSRAM_EXTENDED_TypeDef *Device, FMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank, uint32_t ExtendedMode)
{
	uint32_t tmpr = 0U;
 
	/* Set NORSRAM device timing register for write configuration, if extended mode is used */
	if (ExtendedMode == FMC_EXTENDED_MODE_ENABLE) {
		/* Get the BWTR register value */
		tmpr = Device->BWTR[Bank];
 
		/* Clear ADDSET, ADDHLD, DATAST, BUSTURN and ACCMOD bits */
		tmpr &= ((uint32_t)~(FMC_BWTR1_ADDSET  | FMC_BWTR1_ADDHLD | FMC_BWTR1_DATAST | FMC_BWTR1_BUSTURN | FMC_BWTR1_ACCMOD));
 
		tmpr |= (uint32_t)(Timing->AddressSetupTime                  |\
		                      ((Timing->AddressHoldTime) << 4U)          |\
		                      ((Timing->DataSetupTime) << 8U)            |\
		                      ((Timing->BusTurnAroundDuration) << 16U)   |\
		                      (Timing->AccessMode));
 
		Device->BWTR[Bank] = tmpr;
	} else {
		Device->BWTR[Bank] = 0x0FFFFFFFU;
	}
 
	return 0;
}

And FMC init:

/** FMC GPIO Configuration
	 PD14  ------> FMC_DA0
	 PD15  ------> FMC_DA1
	 PD0   ------> FMC_DA2
	 PD1   ------> FMC_DA3
	 PE7   ------> FMC_DA4
	 PE8   ------> FMC_DA5
	 PE9   ------> FMC_DA6
	 PE10  ------> FMC_DA7
	 PE11  ------> FMC_DA8
	 PE12  ------> FMC_DA9
	 PE13  ------> FMC_DA10
	 PE14  ------> FMC_DA11
	 PE15  ------> FMC_DA12
	 PD8   ------> FMC_DA13
	 PD9   ------> FMC_DA14
	 PD10  ------> FMC_DA15
	 PD4   ------> FMC_NOE
	 PD5   ------> FMC_NWE
	 PD7   ------> FMC_NE1
	 PG9   ------> FMC_NE2
	 PG10  ------> FMC_NE3
	 PB7   ------> FMC_NL
	 PG6   ------> FMC_RB1
	 */
 
	LL_GPIO_InitTypeDef GPIO_InitStruct;
 
	GPIO_InitStruct.Pin = LL_GPIO_PIN_7 | LL_GPIO_PIN_8 | LL_GPIO_PIN_9 | LL_GPIO_PIN_10 | LL_GPIO_PIN_11 | LL_GPIO_PIN_12 | LL_GPIO_PIN_13 | LL_GPIO_PIN_14
			| LL_GPIO_PIN_15;
	GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
	GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
	GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Alternate = LL_GPIO_AF_12;
	LL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
	GPIO_InitStruct.Pin = LL_GPIO_PIN_8 | LL_GPIO_PIN_9 | LL_GPIO_PIN_10 | LL_GPIO_PIN_14 | LL_GPIO_PIN_15 | LL_GPIO_PIN_0 | LL_GPIO_PIN_1;
	GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
	GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
	GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Alternate = LL_GPIO_AF_12;
	LL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 
	GPIO_InitStruct.Pin = LL_GPIO_PIN_4 | LL_GPIO_PIN_5 | LL_GPIO_PIN_7;
	GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
	GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
	GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Alternate = LL_GPIO_AF_12;
	LL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 
	GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
	GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
	GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
	GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Alternate = LL_GPIO_AF_12;
	LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
	GPIO_InitStruct.Pin = LL_GPIO_PIN_9 | LL_GPIO_PIN_10;
	GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
	GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
	GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Alternate = LL_GPIO_AF_12;
	LL_GPIO_Init(GPIOG, &GPIO_InitStruct);

1 ACCEPTED SOLUTION

Accepted Solutions
Pilous Droip
Senior

I solve it.

#define ADDR_SHIFT(Address) (Bank1_SRAM2_ADDR + (2 * (Address)))
#define FMCWRITE(Address, Data)  (*(__IO uint16_t *)(Address) = (Data))

And now I send write data:

FMCWRITE(ADDR_SHIFT(FMCadress), FMCdata);

View solution in original post

3 REPLIES 3
Pilous Droip
Senior

I solve it.

#define ADDR_SHIFT(Address) (Bank1_SRAM2_ADDR + (2 * (Address)))
#define FMCWRITE(Address, Data)  (*(__IO uint16_t *)(Address) = (Data))

And now I send write data:

FMCWRITE(ADDR_SHIFT(FMCadress), FMCdata);

Pilous Droip
Senior

Write on fmc bus is working. But when I try read from bus sometimes the received value is wrong. And I don't know why... :face_with_steam_from_nose:

#define Bank1_SRAM2_ADDR  ((uint32_t)0x64000000)
#define ADDR_SHIFT(Address) (Bank1_SRAM2_ADDR + (2 * (Address)))
 
#define FMCREAD(uAdr) 	*(__IO uint16_t *)(uAdr)

And I have two function.

  1. write and read data from FMC bus. "simple echo"
void Echo(uint16_t FMCadress, uint16_t  FMCdata) {
 
	InfoPrint("Adress 0x%X ; Data 0x%X", FMCadress, FMCdata);
 
        FMCWRITE(ADDR_SHIFT(adr), dat);
	delay_msec(1);
	if (FMCREAD(ADDR_SHIFT(adr)) == dat)
		InfoPrint("TRUE");
        else
		InfoPrint("FALSE");		
}
  1. And only read function
void readfmc(uint16_t FMCadress)
{
	uint16_t receive = RdXBank(ADDR_SHIFT(FMCadress));
	InfoPrint("receive from: 0x%X data: 0x%X", FMCadress, receive);
}

And sometimes, I receive data from address. But this data have wrong latest bit. Any idea why is my latest bit wrong?

I'm so stupid.... :D

I had disable push pull output.