cancel
Showing results for 
Search instead for 
Did you mean: 

"Touchgfx + QSPI" : Switching between "Memory mapped mode" and "Indirect mode"

istepne
Associate III

Hi everyone!

On my custom board, STM32F746IGT6, TouchGFX is OK (The QSPI is used as Indirect mode for data storage from the second task). Finally, I need more space for the images and fonts. So, I changed the *.ld linker file by adding;

 QUADSPI (rx)   : ORIGIN = 0x90000000, LENGTH = 16M 

So now, by using CubeProgrammer (via External Loader enabled) can display images again properly. But I can not read QSPI by indirectly which is intended to hold user settings and logging data.

I have already try to search "Switching from read only memory mapped mode to Indirect mode.." topics etc.. but not get success.

I try to use;

//Indirect mode

inDirectModeActiveFlag=1;//to notify other tasks that memory is indirect mode

BSP_QSPI_Init();

BSP_QSPI_Read(....

BSP_QSPI_Write(... .. do something that I want

//And go back to mapped mode

BSP_QSPI_Init();

BSP_QSPI_MemoryMappedMode();

inDirectModeActiveFlag=0;

So, I also put the line;

if (inDirectModeActiveFlag==1) return;

to the Model::tick() function to do not disturb display

Any suggestion or help?

I think that the N25Q128a with 16M must be enogh to store application settings and logging data on itand the image files too.

Murat

4 REPLIES 4
eng23
Senior

Hi @istepne​ 

Touchgfx uses the qspi everytime, so you can't exit from QSPI memory mapped with touchgfx running.

The solution that I found to read and write user data from/in qspi is stopping Touchgfx task > exit memory mapped mode > do read write functions.

Something like this:

osThreadSuspend(defaultTaskHandle);
 
	QUADSPI->CCR &= (~(QUADSPI_CCR_FMODE));
	HAL_MPU_Disable();
 
	QSPIHandle.Instance = QUADSPI;
	QSPIHandle.Init.ClockPrescaler = 1;
	QSPIHandle.Init.FifoThreshold = 4;
	QSPIHandle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
	QSPIHandle.Init.FlashSize = 24;
	QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE;
	QSPIHandle.Init.ClockMode = QSPI_CLOCK_MODE_0;
	QSPIHandle.Init.FlashID = QSPI_FLASH_ID_1;
	QSPIHandle.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
	if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK)
	{
		//Error_Handler();
	}
	/* USER CODE BEGIN QUADSPI_Init 2 */
 
	BSP_QSPI_Init();

After, enable the memory mapped mode and resume touchgfx task:

	BSP_QSPI_MemoryMappedMode();	//ok
	HAL_NVIC_DisableIRQ(QUADSPI_IRQn);
 
	MPU_Region_InitTypeDef MPU_InitStruct;
	MPU_InitStruct.Enable = MPU_REGION_ENABLE;
	MPU_InitStruct.BaseAddress = 0x90000000;
	MPU_InitStruct.Size = MPU_REGION_SIZE_256MB;
	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_NOT_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);
 
	/* Configure the MPU attributes as WT for QSPI (used 16Mbytes) */
	MPU_InitStruct.Enable = MPU_REGION_ENABLE;
	MPU_InitStruct.BaseAddress = 0x90000000;
	MPU_InitStruct.Size = MPU_REGION_SIZE_16MB; /* NOTE! Change this if you change QSPI flash size! */
	MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
	MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
	MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
	MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
	MPU_InitStruct.Number = MPU_REGION_NUMBER3;
	MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
	MPU_InitStruct.SubRegionDisable = 0x00;
	MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
 
	HAL_MPU_ConfigRegion(&MPU_InitStruct);
	HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
 
osThreadResume(defaultTaskHandle);

Anderson

Martin KJELDSEN
Chief III

Another way to achieve what @eng23​ mentions, instead of stopping the task, is to disable the interrupt(s) that drive TouchGFX, do your QSPI work, then re-enable interrupts.

Martin KJELDSEN
Chief III

Those interrupts being the LTDC Interrupt (Parallel RGB) or the Tearing Effect (TE) interrupt (DSI).

istepne
Associate III

Hi Eng23 and Martin.

I spent a whole day by disablng and enabling the mapped mode and testings.

First of all, I started to carry out the used memory addess from 0x00000000 to 0x00FFF000 (last sector of the QSPI 4095) to not to bother the ToucGFX system (which is uses the first addresses when QSPI enabled).

What I found that,

BSP_QSPI_Erase_Block(4095) is not working.

BSP_QSPI_Erase_Block(0x00FFF000); is works for erasing.

And after every compile, flashing the MCU is not enough and the external memory part must also need to be re-flashed again, otherwise not working (I assumed that the images and fonts are just once flashed is enough, but must be re-flashed).

Finally, now, QSPI swicthing operation just once on the startup (by suspending the TouchGFX task), I can get an action and screen seems like OK. But after a few seconds TouchGFX task stops.

I do not want to an additional an E2PROM, My aim to reserve 1Mbyte of the QSPI memory for user actions logging and measurements logging with timestamp.

Martin can you write me the interrupts that I need to stop for proper operation?

I am using 800x480 7" with parallel RGB 16bits and SDRAM with RTOS CMSIS v1 acvtive

I think, for ST discovery kits, there could be an example project in the future

Regards,

Murat