cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H743II FMC + 8080 LCD spurious writes

Piotr S
Associate II
Posted on April 20, 2018 at 11:55

Hello,

I'm interfacingSTM32H743II with 8080 parallel bus LCD. I configured FMC in CubeMX as LCD Interface with 16bit bus and A11 as R/S pin. However I've run into problem with writing commands/data into LCD. A single uint16_t write under 0x68000000 address results in 4 writes to memory, out of which first write is valid data, and rest are 0, as seen on logic analyser snapshot.

0690X0000060AhJQAU.png

Write is performed by following code:

#define COMMAND_POINTER 0x68000000
#define DATA_POINTER 0x68001000
...
static uint16_t * command = (uint16_t *) COMMAND_POINTER;
static uint16_t * data = (uint16_t *) DATA_POINTER;
...
*command = ILI9341_SWRESET; //software reset�?�?�?�?�?�?�?�?�?�?�?

I also tried HAL_SRAM_Write_16b(), but result is the same.

These writes basically compile to strh (Store register halfword) instruction, and executing this single instruction causes 4 write accesses to LCD. After little investigation i noticed, that writes under incremented address, for example 0x68000002 causes valid data only in second write operation, write under 0x68000004 causes valid data only in third write and so on. It's like FMC tries to write whole 64bit memory block at once.

ICache and DCache are disabled, i tried to disable FMC write FIFO, but it doesn't change much. Needless to say this FMC behaviour throws off communication with LCD.

Am I not taking some detail into account? i would like to avoid bitbanging LCD signals or changing HW design.

#stm32h7 #lcd #h7 #fmc
1 ACCEPTED SOLUTION

Accepted Solutions
Piotr S
Associate II
Posted on April 20, 2018 at 17:45

I solved this problem by remapping fmc SRAM to 0xC0000000;

HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAM_SRAM);

Why this works? Memory under 0xC0000000 is accessed as Device memory, as opposed to memory under 

0x60000000

accessed as Normal memory. 'Normal memory allows the load and store of bytes, half-words and words to be arranged by the CPU in an efficient manner (the compiler is not aware of memory region types)'. You can refer to AN4838 and AN4839 for more information.

View solution in original post

18 REPLIES 18
Piotr S
Associate II
Posted on April 20, 2018 at 17:45

I solved this problem by remapping fmc SRAM to 0xC0000000;

HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAM_SRAM);

Why this works? Memory under 0xC0000000 is accessed as Device memory, as opposed to memory under 

0x60000000

accessed as Normal memory. 'Normal memory allows the load and store of bytes, half-words and words to be arranged by the CPU in an efficient manner (the compiler is not aware of memory region types)'. You can refer to AN4838 and AN4839 for more information.
Andrew Berry
Associate II
Posted on April 21, 2018 at 09:22

You can also use the MPU to define arbitrary address ranges as device memory (or apply other constraints) on devices that are so equipped.  I'm not sure what it looks like in HAL, but the below is an example of direct configuration of a memory region via the MPU registers.  The full details are in the ARM Cortex-M7 Devices Generic User Guide: 

http://infocenter.arm.com/help/topic/com.arm.doc.dui0646a/BIHJJABA.html

 

MPU->CTRL =

    MPU_CTRL_PRIVDEFENA_Msk | // allow privileged code to use default memory map

    MPU_CTRL_ENABLE_Msk;

MPU->RNR = 1;

MPU->RBAR = FMC_BANK1_SUB3_BASE_addr & MPU_RBAR_ADDR_Msk;

MPU->RASR =

    MPU_RASR_XN_Msk |

    (19<<MPU_RASR_SIZE_Pos) |

    MPU_RASR_B_Msk | //set region to Device

    (3 << MPU_RASR_AP_Pos) | //full read/write access for privileged and unprivileged code

    MPU_RASR_ENABLE_Msk;
CDew.1
Associate III

@Piotr S​ Thanks for writing up your solution, it worked for me too.

Can you tell me how to do this memory swap between SRAM and SDRAM so that SRAM is at 0xc0000000? It doesn't look like this function "HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAM_SRAM);" is available in the current HAL.

In short, it works for me.

I'm using CubeIDE Version: 1.2.1

Build: 5190_20200115_1224 (UTC)

and the NUCLEO-H743ZI2 board for project generation.

The HAL function is at line 1042 of my_project/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c

/**
  * @brief  Set the FMC Memory Mapping Swapping config.
  * @param  BankMapConfig: Defines the FMC Bank mapping configuration. This parameter can be
            FMC_SWAPBMAP_DISABLE, FMC_SWAPBMAP_SDRAM_SRAM, FMC_SWAPBMAP_SDRAMB2
  * @retval HAL state
  */
void HAL_SetFMCMemorySwappingConfig(uint32_t BankMapConfig)
{
  /* Check the parameter */
  assert_param(IS_FMC_SWAPBMAP_MODE(BankMapConfig));
  MODIFY_REG(FMC_Bank1_R->BTCR[0], FMC_BCR1_BMAP, BankMapConfig);
}

In full:

In the CubeMX project generator, I navigated to:

Pinout & Configuration

-> Categories

-> Connectivity

-> FMC

-> NOR Flash/PSRAM/SRAM/ROM/LCD1 (upper pane)

-> Configuration (lower pane)

-> Bank Mapping

-> Mapping parameters

-> FMC bank mapping

and changed the selected item from "Default mapping" to "NOR/PSRAM bank and SDRAM bank...".

I had to alter my code to replace 0x6000 0000 with 0xc000 0000.

The (new) generated code is:

/* FMC initialization function */
static void MX_FMC_Init(void)
{
 
  /* USER CODE BEGIN FMC_Init 0 */
 
  /* USER CODE END FMC_Init 0 */
 
  FMC_NORSRAM_TimingTypeDef Timing = {0};
  FMC_NORSRAM_TimingTypeDef ExtTiming = {0};
 
  /* USER CODE BEGIN FMC_Init 1 */
 
  /* USER CODE END FMC_Init 1 */
 
  /** Perform the SRAM1 memory initialization sequence
  */
  hsram1.Instance = FMC_NORSRAM_DEVICE;
  hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
  /* hsram1.Init */
  hsram1.Init.NSBank = FMC_NORSRAM_BANK2;
  hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
  hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
  hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
  hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
  hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
  hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
  hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
  hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
  hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_ENABLE;
  hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
  hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
  hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
  hsram1.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;
  hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
  /* Timing */
  Timing.AddressSetupTime = 3;
  Timing.AddressHoldTime = 15;
  Timing.DataSetupTime = 4;
  Timing.BusTurnAroundDuration = 1;
  Timing.CLKDivision = 16;
  Timing.DataLatency = 17;
  Timing.AccessMode = FMC_ACCESS_MODE_A;
  /* ExtTiming */
  ExtTiming.AddressSetupTime = 3;
  ExtTiming.AddressHoldTime = 15;
  ExtTiming.DataSetupTime = 4;
  ExtTiming.BusTurnAroundDuration = 1;
  ExtTiming.CLKDivision = 16;
  ExtTiming.DataLatency = 17;
  ExtTiming.AccessMode = FMC_ACCESS_MODE_A;
 
  if (HAL_SRAM_Init(&hsram1, &Timing, &ExtTiming) != HAL_OK)
  {
    Error_Handler( );
  }
 
  HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAM_SRAM);
 
  /* USER CODE BEGIN FMC_Init 2 */
 
  /* USER CODE END FMC_Init 2 */
}

Where the important line is:

HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAM_SRAM);

I have tested that this generates a sane waveform (in my logic analyser) with only one write instead of four, but the timings may not suit your screen.

Thanks for the info. It looks like that function only exists for the H743 part. I'm using the F746 part and I don't see any option in the CubeMX project generator to do the bank swapping. I just tried a project for the Nucleo board you're using and the option is there. I was able to get my code working properly by following the MPU config recommended so that caching is not allowed for the 0x60000000 address.

The FMC memory remapping is controlled by the SWP_FMC bits in the Memory Remap Register in the SYSCFG module (SYSCFG->MEMRMP). Section 7.2.1 in the STM32F746 Reference Manual. It doesn't at all surprise me that Cube is just missing this feature for some parts, things like that are yet another reason to avoid Cube.

Thanks for that info. Agreed, Cube and also parts of the HAL are quite buggy from what I've seen!

IMO changing this area to Device just covers some other adverse mechanism. While the processor is allowed to rearrange accesses in Normal area in order to optimize, it's not OK to write outright incorrect data! (multiple*reads* would still be OK).

JW