cancel
Showing results for 
Search instead for 
Did you mean: 

Octospi1 Reading from volatile memory stm32H735

Kvang
Associate III

Hi 

I have configured Octospi1 to Read / Write from my FPGA in memory mapped mode.

The interface works well, but i have a problem that the CPU is not reading from the memory and just use last cached value.

The Variables are set volatile. both the pointer to the struct and each variable.

 

typedef struct

{

volatile uint32_t nFpgaInfo;

volatile uint8_t nBldcEnable;

volatile uint8_t n12VOff;

volatile uint8_t nDurInterfaceTest;

volatile uint8_t nEncOutDiv;

 

volatile uint32_t nuS;

 

}TFTop;

 volatile TFTop* m_pFTop;

i also tried __IO, but that gave the same.

I have set following for the MPU:

 

MPU_Region_InitTypeDef MPU_InitStruct;

/* Disable the MPU */

HAL_MPU_Disable();

/* Configure the MPU attributes as WT for OCTOSPI1 */

MPU_InitStruct.Enable = MPU_REGION_ENABLE;

MPU_InitStruct.BaseAddress = OCTOSPI1_BASE;

MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;

MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;

MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;

MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;

MPU_InitStruct.Number = MPU_REGION_NUMBER2;

MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;

MPU_InitStruct.SubRegionDisable = 0x00;

MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

 

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Enable the MPU */

HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

Can I somehow instruct the CPU / MPU to always read from the Octopspi1?

best Regards

Kristian Vang

 

 

5 REPLIES 5
KDJEM.1
ST Employee

Hello @Kvang ,

 

 I recommend you to take a look at AN4838 and precisely MPU setting example with STM32Cube HAL on Armv6 and Armv7 architectures section and Cortex-M7 constraint speculative prefetch section and at this video.

May this example can help you.

 

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.

Kvang
Associate III

I believe that I have tried almost everything now, not getting anywhere.

My default settings was MPU NOT used and cache disabled and Speculation Disabled.

Kvang_0-1726572285429.png

Would Any MPU setting improve compared to this?

What else can I do?
Im a bit confused about this:


MPU_InitStruct.SubRegionDisable = 0x87; (for the whole region)
if I change this to e.g. 0 then I get a hard fault.

I have Tried Below: (The FPGA is connected to OCTOSPI1)

static void MPU_Config(void)

{

MPU_Region_InitTypeDef MPU_InitStruct;

 

/* Disable the MPU */

HAL_MPU_Disable();

 

/* Configure the MPU as Strongly ordered for not defined regions */

MPU_InitStruct.Enable = MPU_REGION_ENABLE;

MPU_InitStruct.BaseAddress = 0x00;

MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;

MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;

MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;

MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;

MPU_InitStruct.Number = MPU_REGION_NUMBER0;

MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;

MPU_InitStruct.SubRegionDisable = 0x87;

MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

 

HAL_MPU_ConfigRegion(&MPU_InitStruct);

 

/* Configure the MPU attributes as WT for OCTOSPI2 */

MPU_InitStruct.Enable = MPU_REGION_ENABLE;

MPU_InitStruct.BaseAddress = OCTOSPI2_BASE;

MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;

MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;

MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;

MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;

MPU_InitStruct.Number = MPU_REGION_NUMBER1;

MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;

MPU_InitStruct.SubRegionDisable = 0x00;

MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

 

HAL_MPU_ConfigRegion(&MPU_InitStruct);

 

/* Configure the MPU attributes as WT for OCTOSPI1 */

MPU_InitStruct.Enable = MPU_REGION_ENABLE;

MPU_InitStruct.BaseAddress = OCTOSPI1_BASE;

MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;

MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;

MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;

MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;

MPU_InitStruct.Number = MPU_REGION_NUMBER2;

MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;

MPU_InitStruct.SubRegionDisable = 0x00;

MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

 

HAL_MPU_ConfigRegion(&MPU_InitStruct);

 

/* Enable the MPU */

HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}

No matter what I do I hang in loops like this (waiting for a bit to clear):

If I hover over the variable in Debug then it read's 0x0 and then it exit the loop.
only on Read is done prior to this. (the whole point of volatile is to avoid this)

If I have a interrupt running in the background that access the FPGA it appears to work,

because that will trigger the system to read.


while (m_pAdc->nSet & 2);

 

volatile TSpiSingleData* m_pAdc;

 

struct TSpiSingleData

{

volatile uint32_t nWrite;

volatile uint32_t nRead;

volatile uint8_t nSet; // Busy & Auto

//uint8_t nSet2; //extra_cycle(I) & miso_clk_edge(I) & mosi_clk_edge(I);

volatile int8_t n16BitRegs; //0=12bit or 1=16 depending on oversampling

volatile uint16_t nAutoDist;

volatile uint16_t nMonMin; //Are only accessible for ADC where monitor is enabled

volatile uint16_t nMonMax; //Are only accessible for ADC where monitor is enabled

volatile TAdcReg nRegs[8];

};

 

 

Kvang
Associate III

I found the problem, in my playing round I accidently set MPU_INSTRUCTION_ACCESS_ENABLE
WITH MPU_INSTRUCTION_ACCESS_DISABLE and the other setting from above it works and reads from the FPGA is fully volatile :)


/* Configure the MPU attributes as WT for OCTOSPI1 */

MPU_InitStruct.Enable = MPU_REGION_ENABLE;

MPU_InitStruct.BaseAddress = OCTOSPI1_BASE;

MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;

MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;

MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;

MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;

MPU_InitStruct.Number = MPU_REGION_NUMBER2;

MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;

MPU_InitStruct.SubRegionDisable = 0x00;

MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

Kvang
Associate III

Hi All
I came back from vacation and expected to proceed with above problem Being solved.

But apparently after powering off the board, the code is no longer working???   

The exacts same code was working a week ago.

The solution has to related to above. because it stated working after I set the MPU_INSTRUCTION_ACCESS_DISABLE, but now using this code the memory area is not longer seen as volatile, so there has to be more to it somehow.

From the compiler I would believe that this has to be read every time right? But i keep hanging in the while.

When I break then the debugger reads (i can see that in the ILA of the FPGA), i and I can see that the value is 0, so no reason to stay in the while, and it does also exit then. but hangs again next time.

 int CFpgaAdc::ReadReg(int nAdress)

{

m_pAdc->nWrite= ((0x10 << 16) | (nAdress << 8));

while (*((volatile const uint8_t*)&m_pAdc->nSet) & 2);

return (m_pAdc->nRead >> 16);

}

Can you please look at mu MPU_config, it seems correct to me and did work earlier 

 

Any help would be much appreciated 

Kvang
Associate III

I have investigated some more.


I have tried: Strongly ordered, Device, Shared non shared, and Normal.
The only difference i see is when writing. in Normal it write 64bit boundaries filtered with DQS
in Strongly ordered and Device it only write the data.

Read behaves equally in all modes.
Typically the read will read 8 x 32 bit. (Can this be avoided?)
additional reads on next 64bit boundary will reads 2 x 32bit.

While reading in the same 64bit boundary no additional read are made. (This is the problem)
The Variable are defined as volatile and i have tried reading using various different method . lately using a console method where I can be sure that the compiler is not interfering.

as I see it it has to be related to Either the OctoSpi itself or something in the interface form the 64bit Axi-Bus to the Octospi.

If I write any address or read outside the 64bit boundary and go back then the value will be re-read once.

My current Code :

static void MX_OCTOSPI1_Init(void)

{

 

/* USER CODE BEGIN OCTOSPI1_Init 0 */

HAL_OSPI_DeInit(&hospi1);

 

/* USER CODE END OCTOSPI1_Init 0 */

 

OSPIM_CfgTypeDef sOspiManagerCfg = {0};

 

/* USER CODE BEGIN OCTOSPI1_Init 1 */

 

/* USER CODE END OCTOSPI1_Init 1 */

/* OCTOSPI1 parameter configuration*/

hospi1.Instance = OCTOSPI1;

hospi1.Init.FifoThreshold = 1;

hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;

hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_APMEMORY;

hospi1.Init.DeviceSize = 24;

hospi1.Init.ChipSelectHighTime = 1;

hospi1.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;

hospi1.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;

hospi1.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;

hospi1.Init.ClockPrescaler = 30;

hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;

hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;

hospi1.Init.ChipSelectBoundary = 24;

hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_USED;

hospi1.Init.MaxTran = 0;

hospi1.Init.Refresh = 0;

if (HAL_OSPI_Init(&hospi1) != HAL_OK)

{

Error_Handler();

}

sOspiManagerCfg.ClkPort = 1;

sOspiManagerCfg.DQSPort = 1;

sOspiManagerCfg.NCSPort = 1;

sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;

sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;

if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

{

Error_Handler();

}

/* USER CODE BEGIN OCTOSPI1_Init 2 */

 

 

/* USER CODE END OCTOSPI1_Init 2 */

 

}



static void MPU_Config(void)

{

MPU_Region_InitTypeDef MPU_InitStruct;

 

/* Disable the MPU */

HAL_MPU_Disable();

 

/* Configure the MPU attributes as WT for OCTOSPI1 */

MPU_InitStruct.Enable = MPU_REGION_ENABLE;

MPU_InitStruct.BaseAddress = OCTOSPI1_BASE;

MPU_InitStruct.Size = MPU_REGION_SIZE_512MB;

MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;

MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;

MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;

MPU_InitStruct.Number = MPU_REGION_NUMBER0;

MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;

MPU_InitStruct.SubRegionDisable = 0x00;

MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

 

HAL_MPU_ConfigRegion(&MPU_InitStruct);

 

/* Enable the MPU */

HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}

 

#define LINEAR_BURST_READ 0x20

#define LINEAR_BURST_WRITE 0xA0

#define DUMMY_CLOCK_CYCLES_SRAM_READ 6

#define DUMMY_CLOCK_CYCLES_SRAM_WRITE 0

/*----------------------------------------------------------------------*/

/* This function enables memory-mapped mode for Read and Write operations */

void EnableMemMapped(void)

{

OSPI_RegularCmdTypeDef sCommand;

OSPI_MemoryMappedTypeDef sMemMappedCfg;

sCommand.FlashId = HAL_OSPI_FLASH_ID_1;

sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;

sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;

sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;

sCommand.AddressMode = HAL_OSPI_ADDRESS_8_LINES;

sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;

sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;

sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

sCommand.DataMode = HAL_OSPI_DATA_8_LINES;

sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;

sCommand.DQSMode = HAL_OSPI_DQS_ENABLE;

sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

sCommand.Address = 0;

sCommand.NbData = 1;

/* Memory-mapped mode configuration for Linear burst write operations */

sCommand.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG;

sCommand.Instruction = LINEAR_BURST_WRITE;

sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_SRAM_WRITE;

 

if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE)!= HAL_OK) {

Error_Handler();

}

/* Memory-mapped mode configuration for Linear burst read operations */

sCommand.OperationType = HAL_OSPI_OPTYPE_READ_CFG;

sCommand.Instruction = LINEAR_BURST_READ;

sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_SRAM_READ;

 

if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE)!= HAL_OK) {

Error_Handler();

}

/*Disable timeout counter for memory mapped mode*/

sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_ENABLE;

sMemMappedCfg.TimeOutPeriod = 100;

/*Enable memory mapped mode*/

if (HAL_OSPI_MemoryMapped(&hospi1, &sMemMappedCfg) != HAL_OK) {

Error_Handler();

}

}

Hope somebody can help with this