cancel
Showing results for 
Search instead for 
Did you mean: 

OCTOSPI line idle level - Weird behaviour

Gabriel_Csefalvay
Associate II

Hi, Community,

I'm trying to understand the OCTOSPI peripheral on my STM32L4P5. I'm new to STM32, but old in embedded. Particularly, I need to know/affect the idle level of the data line of the OCTOSPI. I thought that the last transmitted bit would remain there...

But no, I encountered a really weird behaviour. See for yourself. I created a simple program periodically test sending 16 bytes. The OCTOSPI is set to transmit on 1 data line, data only, no instruction, no address.

 

Test A:

while (1)
{
HAL_Delay(1);
OCTOSPI1->DR = 0xFFFEFFFF;
OCTOSPI1->DR = 0x00010000;
OCTOSPI1->DR = 0x00010000;
OCTOSPI1->DR = 0x00010000;
}

Result: The idle level is High:

DS0002.png

 

Test B:

while (1)
{
HAL_Delay(1);
OCTOSPI1->DR = 0xFFFEFFEF;
OCTOSPI1->DR = 0x00010000;
OCTOSPI1->DR = 0x00010000;
OCTOSPI1->DR = 0x00010000;
}

Result: The idle level is Low:

DS0001.png

 

The difference between A and B is one bit: the MSB of the lowest byte of the first write. It is the first transmitted bit, if I understand correctly.

 

Can somebody explain this? How can that bit affect the idle level?

I think I'm missing something substantial here.

10 REPLIES 10
LCE
Principal

You are doing some "interesting" tests...

I just got the OCTOSPI on a H735-DK working without Cube / HAL, both for Flash and HyperRAM (that was the easy part). There are many pitfalls, so I would not waste time with something like that - unless you want to abuse it for something else. 😉

Without a clock, any data signal's state actually doesn't really matter, as any SPI (that I know of) puts data in / out on the clock edges. 

Anyway, that behavior seems strange indeed.

The OCTOSPI is no simple peripheral, there are so many setting - so how have you set it up?

 


unless you want to abuse it for something else. 

That's exactly what I want. :D I want to generate a VGA video signal, that's why I don't need the clock and why I need control over the idle level.

 

Here is all the configuration code:

OSPIM_CfgTypeDef OSPIM_Cfg_Struct = {0};
hospi1.Instance = OCTOSPI1;
hospi1.Init.FifoThreshold = 8;
hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON;
hospi1.Init.DeviceSize = 32;
hospi1.Init.ChipSelectHighTime = 1;
hospi1.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
hospi1.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
hospi1.Init.ClockPrescaler = 1;
hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;
hospi1.Init.ChipSelectBoundary = 0;
hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;
hospi1.Init.Refresh = 0;
if (HAL_OSPI_Init(&hospi1) != HAL_OK)
{
Error_Handler();
}
OSPIM_Cfg_Struct.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
if (HAL_OSPIM_Config(&hospi1, &OSPIM_Cfg_Struct, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}

 

OCTOSPI1->CCR = HAL_OSPI_DATA_1_LINE; // Sending only data, no instruction or address
OCTOSPI1->DCR3 = 0; //Disable MAXTRAN
OCTOSPI1->DLR = 0xFFFFFFFF; // infinite length
OCTOSPI1->TCR = 0; // no dummy cycles

 

KDJEM.1
ST Employee

Hello @Gabriel_Csefalvay ,

I recommend you to take a look at the errata sheet and precisely section 2.6.3 Data not sampled correctly on reads without DQS and with less than two cycles before the data phase.

Data are not sampled correctly if all the following conditions are met:
Fewer than two cycles are required by the first four phases (command, address, alternate or dummy).
• DQS is disabled (DQSE = 0).
• Data phase is enabled.
• Data are read in Indirect or Memory-mapped mode. 

Workaround
Ensure that there are at least two cycles before the data phase using one of the following methods :
• Send one byte of address in SDR quad-SPI mode (ADMODE = 011, ADSIZE = 00, ADDDTR = 0)
• Send two bytes of address in SDR octal-SPI mode (ADMODE = 100, ADSIZE = 01, ADDDTR = 0)
• Send four bytes of address in DTR octal-SPI mode (ADMODE = 100, ADSIZE = 11, ADDDTR = 1)
• Send two bytes of instruction in DTR quad-SPI mode (IMODE = 011, ISIZE = 01, IDDTR = 1)
• Send one instruction byte in octal followed by one dummy cycle.
• Send one instruction byte in octal followed by one alternate byte in octal

Also, could you please check SSHT and DHQC parameter?

Note that the Sample shifting (SSHT) recommended to be enabled in STR mode and disabled in DTR mode and the Delay hold quarter cycle (DHQC) enabled in DTR mode and disabled in STR mode.

Thank you.

Kaouthar

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

@KDJEM.1 , thanks for the suggestions. A quick test shows that the SSHIFT and DHQC bits don't affect this behavior.

I have read the OCTOSPI section of the errata sheet, but it says nothing about tx. Note that I use the OCTOSPI only for tx, I don't rean any data at all.

Gabriel_Csefalvay
Associate II

So far I found out that writing 8 words of 0x00000000 (32 bytes total) to the DR (data register) resets this behavior, which just happens to be the FIFO buffer size. A coincidence? :]

KDJEM.1
ST Employee

Hi @Gabriel_Csefalvay ,

Thank you for updating post.

Could you please check the TCF and FTF bit in the OCTOSPI_SR and TCIE bit in n OCTOSPI_CR to check if the transfer is completed or not and/or the FIFO threshold has been reached, or if there is any data left in the FIFO after the reads from the external device are complete.

Thank you.

Kaouthar 

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

LCE
Principal

 I want to generate a VGA video signal, that's why I don't need the clock and why I need control over the idle level.

Maybe the regular SPI peripheral might be better suited, a timer in PWM / DMA mode is probably too slow.

What is the maximum bit rate you need?

@KDJEM.1 I can check, just tell WHEN to check. After the 4 bytes sent? NOTE that I'm NOT reading anything from any external device. I don't think we get each other, maybe read my original post once more. By writing 1 word to the DR register, the FIFO won't be full.


@LCE wrote:

Maybe the regular SPI peripheral might be better suited, a timer in PWM / DMA mode is probably too slow.

What is the maximum bit rate you need?


For generating 1080p@60Hz video, I'd need 150Mb/s. That should be doable with the double data rate mode @75MHz.

So far I managed to make the 1080p work in a 1 output px = 2 physical pixels manner (half bitrate, 75Mb/s), and also doubled in the vertical direction. In this way the final resolution is still 960x540, what fits in the RAM comfortably. That is good enough for me, a lot of info can fit on the screen 🙂 Also the image is nice widescreen (not stretched).

This OCTOPUSPI peripheral is a real beast. The regular SPI peripherals can do max. fₚ꜀ₗₖ/2, so it isn't fast enough for this case. Also the 1-byte buffer would make it more prone to errors at such high speeds (in case the DMA misses the deadline for the next data byte) versus the cool 32-byte buffer of the OCTOSPI.

 

So far the workaround for my issue with the idle level is to toggle the output pin between the Alternate Function (OCTOSPI DO) and normal output (set to 0) in a timer interrupt. It's less than ideal.

It looks like the OCTOSPI somehow remembers the oldest bit in the FIFO buffer and it's value will be the idle level of the DO line.