2015-11-11 10:32 AM
Hi,
I am working on a custom board with the STM32F746IGT6. in witch is a FTDI Parallel-USB converter is connected to the FMC. My problem is that when I try to read data to ''fast'' from the FMC(after a while, and only sometimes) the FMC reads twice for one cycle. And the read function returns the result from the last transfer. This error is only sometimes and I didn't find any relationship with the content of the data. If I slow the velocity in them I pull data (> 2ms) then I have no more errors. The following image showsthesporadically
two reads at the same call. The yellow line is the read trigger. The blue line is the write trigger. Andthe green lineis an output pin that I trigger with software to recognizewhentheread function is called.
static inline u8 FTDI_RX(void){
return (*(__IO u8*) (NOR_MEMORY_ADRESS3 + FSMC_ADD_FTDI)); // (uint32_t)0x68000000 + 8
}
char FTDI_READ(void){
char tmp = 0;
if (FTDI_canRead()) { //READPIN(C, 14)
SETPIN(H, 14); //Green singal on
tmp = FTDI_RX();
RESETPIN(H, 14); //Green singal off
FTDI_mode = 1;
return tmp;
} else {
return 0;
}
}
The FMC configurationisbased on the cube libraries:
NOR_HandleTypeDef hnor1;
FMC_NORSRAM_TimingTypeDef Timing;
hnor1.Instance = FMC_Bank1;
hnor1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
//Duration of the address setup phase
Timing.AddressSetupTime = 7; //0-15 4
//Duration of the address hold phase
Timing.AddressHoldTime = 7; //1-15 3
//Duration of the data setup phase
Timing.DataSetupTime = 20; //1-255 5
//Duration of the bus turnaround phase
Timing.BusTurnAroundDuration = 5; //0-15 1
//Number of AHB clock cycles (HCLK) to build one memory clock cycle (CLK)
Timing.CLKDivision = 3; //2-16 2
//Number of clock cycles to issue to the memory before the first data of the burst
Timing.DataLatency = 3; //2-17 2
Timing.AccessMode = FMC_ACCESS_MODE_A;
/*
- Data/Address MUX = Disable
- Memory Type = SRAM
- Data Width = 16bit
- Write Operation = Enable
- Extended Mode = Enable
- Asynchronous Wait = Disable
*/
hnor1.Init.NSBank = FMC_NORSRAM_BANK3;
hnor1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
hnor1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
hnor1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
hnor1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
hnor1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
hnor1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
hnor1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
hnor1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
hnor1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
hnor1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
hnor1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
hnor1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
hnor1.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE; //
hnor1.Init.PageSize = FMC_PAGE_SIZE_NONE;
// Initialize NOR control Interface
FMC_NORSRAM_Init(hnor1.Instance, &(hnor1.Init));
// Initialize NOR timing Interface
FMC_NORSRAM_Timing_Init(hnor1.Instance, &Timing, hnor1.Init.NSBank);
// Initialize NOR extended mode timing Interface
//FMC_NORSRAM_Extended_Timing_Init(hnor1.Instance, NULL, hnor1.Init.NSBank, hnor1.Init.ExtendedMode);
// Enable the NORSRAM device
(hnor1.Instance)->BTCR[(hnor1.Init.NSBank)] |= FMC_BCR1_MBKEN;
I have already turned the D and I cache off, and got same results.
Inthe erratathere is only an error for synchronous memories in burst mode. Witch I am not using.
STM32F74xxx STM32F75xxx Errata sheet
''2.5 FMC peripheral limitation
2.5.1 Dummy read cycles inserted when reading synchronous memories
Description
When performing a burst read access to a synchronous memory, two dummy read accesses are performed at the end of the burst cycle whatever the type of AHB burst access. However, the extra data values which are read are not used by the FMC and there is no functional failure.
Workaround
None. ''
Does some one have an Idea what I am doing wrong? I apologize for my rusty English. Best regards. Robert #stm32f7-fmc2015-11-11 01:12 PM
Is anything else connected to the FMC, do you use any other bank? Is this the only place where you read from that address range? Do you always read from the same address? Is the write into the same address/address range?
No, I have no idea what it is. JW2015-11-12 02:22 AM
Hi,
> Is anything else connected to the FMC
Yes, I have some shift registers to expand my IOs. But in other addresses. I have already comment away all other calls from the FMC to be sure that there is no collision, without success. I haven't looked yet if by reading the IOs it also does a double read sometimes. (I will try it later) In this case, a double read will not affect the inputs. The problem by the FTDI is that by each read pulls a character from the fifo. So that if the FMC makes a double read the first character get lost.> do you use any other bank?
No.> Is this the only place where you read from that address range?
Yes. Thats why I toggled the pin with the green signal. to verify that no other place calls this function.> Do you always read from the same address?
For the FTDI yes (0x68000000 + 8). I use other addresses for my IO expander. But as previously mentioned I turned all other calls off.> Is the write into the same address/address range?
Yes same as the read (0x68000000 + 8).I think the FMC is trying to make a refresh. or the Hardware detects (don't know how) an error by the first
read and try it again. Is there a configuration for such behave? thanks Robert2015-11-12 03:07 AM
Once again: I don't have an idea what's going on.
Do you have interrupts enabled? Do those interrupts access FMC? Even if not, can you disable them all and observe whether this helps? Can you post disassembled portion of the code where the read happens? Can you produce a minimal example, only reading from FMC in a loop, and observe if this behaviour appears? JW2015-11-12 08:10 AM
Hi Jan,
Thank you for your post. It helped me to locate the problem. In fact the problem is an interrupt intermediately or perhaps between the FMC access. It creates a second read from the same address after the interrupt is ended. To test this I used the following code running in the main function:
1.
SETPIN(H, 14); //green signal high
2.
tmp = (*(__IO uint8_t*) (NOR_MEMORY_ADRESS3)); //yellow signal.
3.
RESETPIN(H, 14); //green signal high
Then at the beginning of my interrupts I turned a second signal (Blue) on and at the end off.
I tested this with the USART_IRQ and the Systick_IRQ, with same result.
The following oscilloscope image shows the behavior:
SETPIN(H, 14);
8001be0: 4b15 ldr r3, [pc, #84] ; (8001c38 <
FTDI_Read
+0x78>)
8001be2: f44f 4280 mov.w r2, #16384 ; 0x4000
8001be6: 619a str r2, [r3, #24]
tmp = FTDI_RX();
8001be8: 4b14 ldr r3, [pc, #80] ; (8001c3c <
FTDI_Read
+0x7c>)
8001bea: 781b ldrb r3, [r3, #0]
8001bec: 73fb strb r3, [r7, #15]
RESETPIN(H, 14);
8001bee: 4b12 ldr r3, [pc, #72] ; (8001c38 <
FTDI_Read
+0x78>)
8001bf0: f04f 4280 mov.w r2, #1073741824 ; 0x40000000
8001bf4: 619a str r2, [r3, #24]
So no indication what could run wrong besides an interrupt handle problem while reading in the FMC.
I suspect that this behavior is the same while writing. But I have not tested it yet.
My solution for now is to turn the interrupts off before the access and to turn them on again after that.
1.
__disable_irq();
2.
tmp = (*(__IO uint8_t*) (NOR_MEMORY_ADRESS3));
3.
__enable_irq();
greetings from Berlin
Robert
2015-11-12 08:55 AM
Robert,
You owe me a beer... 🙂 But this is a nice gotcha. And I think I know the explanation (in fact, I asked the questions above because I read the following yesterday in the night): in the Cortex-M7 TRM, chapter 2.7.1 Exception handling:To minimize interrupt latency, the processor can abandon the majority of multicycle instructions that are executing when the interrupt is recognized. The only exception is a device or strongly-ordered load, or a shared store exclusive operation that starts on the AXI interface. All normal memory transactions are abandoned when an interrupt is recognized. The processor restarts any abandoned operation on return from the interrupt. In M4, only division is abandoned/restarted. LDM/STM are interruptible/continuable (although this behaviour can be optionally switched off) in both. Thus, the M7 trades speed for this ''non-external-device-friendly'' behaviour. Note, that the 60000000-7FFFFFFF area is marked as RAM, non-Device, in the ARMv7 architecture manual (Table B3-1). I see no other workaround except disabling interrupts during the accesses, just as you did. Your relatively high setup etc. settings exacerbated the problem. Luckily, otherwise you might have had the dreaded ''fails once in blue moon'' case. When you have set longer periods for the reads, I guess the problem persisted just its occurence lowered so you did not experience it. Writes can be cached, which can hide this problem - or make it even worse, badly detectable, happening only upon cache exhaustion... I see you have switched off the write caching - can you please try this with both settings and report back, thanks. Jan