 Hello and welcome to this presentation. My name is Bedardin, and in this second part of the video how to customize the TouchGFX template based on the STM32H7B discovery board, we will cover the steps to add an SDRM to the TouchGFX template to be used as a frame buffer in our graphics application. We'll begin by a short introduction followed by an overview of the STM32H7B discovery board and the SDRM memory. Then we will see how to set up the SDRM timings using the STM32QMX and set up the XQ TouchGFX to use double buffering in SDRM. Then at the end, we will finish by a live demo. We will see how to customize the TouchGFX template based on the STM32H7B discovery board to use the SDRM as external frame buffer. The idea of adding the SDRM is to be able to do double buffering on the 640 by 480 display and hence be able to add some cool animations in our graphics application. We will use the following tools, TouchGFX Designer, which is a GUI builder that lets you build the visual appearance of your graphics application. Then we will use STM32QMX, which is a graphical tool that allows a very easy configuration of the STM32 peripherals. Then we will use STM32Q by D to build, load, and debug our graphics project. From hardware standpoint, we will use the STM32H7B discovery board and the display resolution of 640 by 480 from M display. This video will use the STM32H7B3 discovery board. Its main features are STM32H7B3 ARM Cortex M7 based MCU with 2 megabytes of flash memory and 1.4 megabytes of SRAM including 1 megabytes contiguous SRAM that can be used as video buffer for graphics applications. Then the discovery board comes with a 4.3 inches display model and the first part of the video will change the display to 640 by 480. 512 megabit octo-spy flash memory that can be used for graphics assets. And 128 megabit SRAM that we will add to the TETGFX template and use it as a video buffer. The SRAM is IS42S16800 from Integrated Silicon Solutions ISSI. The maximum clock of the SRAM depends on the column adder stroke CAS latency. The CAS latency is the delay between the rate command and the moment the data is available. For our SRAM the CAS latency could be set to 2 clock cycles and the maximum clock would be 100 megahertz. And the CAS latency could be 3 clock cycles and the maximum clock would be 166 megahertz. The SRAM is organized into 4096 rows and 512 columns. For banks, the address bus is 12 bits. The data bus is 16 bits. The SRAM has a self-refresh time of 64 milliseconds that is used to return the data into the SRAM. The SRAM memory specifies some timing values that we will need later to set up the SRAM controller in the STM32. For example, the TRC timing, which is the delay between two refresh commands or two lines of valid commands. We will see later the definitions of each one of these timings. Using STM32QMX, it's very easy to set up the SRAM timings in a graphical way. The flexible memory controller is the interface to access the external memories such as SRAM and NAND. The first step is to set up the clock to the FMC peripheral. Here, I will use PLL2 to set it to 200 megahertz. We will see later that the SRAM clock is derived from this FMC clock. And using 200 megahertz, you can get up to 100 megahertz as clock frequency for the SRAM memory with a divider set to 2. The FMC can support up to two SRAM banks, SRAM1 and SRAM2, 256 megabit each. SRAM1 is mapped at the address 0xC000 and SRAM2 is mapped at the address 0xD000. The SRAM on the discovery kit is connected to the SRAM2 interface. As you can see in the schematic, the clock-enabled 1 signal is connected to the SRAM clock input and the chip-enabled 1 is connected to the SRAM chip select. The SRAM has four internal banks, 12 bits of address, 16 bits of data, and byte-enabled 16 bits. Our SRAM has 512 columns. We need nine bits to code the 512 columns. In QMX, we need to set the number of column address bits tonight. Our SRAM has 4096 rows. We need 12 bits to code the 4096 rows. In QMX, we need to set the number of row address bits to 12. The CAS latency is 2 at 100 megahertz. In QMX, we set the CAS latency to 2 memory clock cycles. We will disable the write protection. The SRAM clock is 100 megahertz at CAS latency of 2. In SRAM, we set the divider to 2. This gets us an SRAM clock of 200 megahertz divided by 2, meaning 100 megahertz. We'll enable the burst rate and set the pipe delay to 2 clock cycles. As I said in slide 7, the SRAM specifies some timing values that we need to provision in SDM32 QMX. We will start by the load mode register to active delay defined as TMRD, which indicates the delay between the load mode register command and the row or refresh command. The data sheet of the memory specifies 12 nanoseconds. And what we need to do is to convert the 12 nanoseconds to a number of memory cycles. So we divide the 12 nanoseconds by the SDM clock period, which is 10 nanoseconds. And then we round to the upper value. And that's the value we set in SDM32 QMX, the 2 here. Second, the exit self-refresh delay defined as TXSR parameter, which is the exit self-refresh to delay between valid commands. The data sheet of the memory specifies 67 nanoseconds. And we convert it to 7 SDM clock cycles. And that's the value we use in SDM32 QMX. Third, the self-refresh time defined as TLS parameter, which is the delay between the line valid and the pre-charge command. The data sheet of the memory specifies 42 nanoseconds. And we convert it to 5 SDM clock cycles. And that's the value we use in SDM32 QMX. After that, the common row cycle delay defined as TRC parameter, which is the delay between two refresh commands or two lines of valid commands. The data sheet of the memory specifies 60 nanoseconds. And we convert it to 6 SDM clock cycles. And that's the value we use in SDM32 QMX. Next, the write recovery time defined as TDPL parameter, which is the delay between writing a command to a pre-charge command. The data sheet of the memory specifies 12 nanoseconds. And when we convert it to SDM clock cycles, we find two, while the specification of the SDM32 requires to have TWR higher than TRAS minus TRCD, which means 5 minus 2, which gives us 3. And that's the value we set in SDM32 QMX. After that, the common row pre-charge delay defined as TRP parameter, which is the delay between pre-charge and line valid commands. The data sheet of the memory specifies 18 nanoseconds. And we convert it to two SDM clock cycles. And that's the value we use in SDM32 QMX. The last parameter is the row to column delay defined as TRCD, which indicates the delay between the line valid commands and the rewrite commands. The data sheet of the memory specifies 18 nanoseconds. And we convert it to two SDM clock cycles. And that's what we use in SDM32 QMX. After the timing configuration, we go to the GPIO settings tab. And we see that the SDM32 QMX default pinout for the SDRM matches the SDM32 H7B discovery board schematic, except the following pins. Clock enable, chip select, and write enable. SDM32 QMX uses PB5 for the clock enable one, while the schematic uses PH7. QMX uses PB6 for the chip enable, while the schematic uses PH6. SDM32 QMX uses PC0 for the write enable, while the schematic uses PH5. So we need to change the pinout configuration in a way to have SDM32 QMX matching the schematic. What we need to do is in the pinout, right click on the pin and change the alternate function to the SDRM signal. In the live demo, we'll see how to do that exactly. After the SDRM configuration, we navigate to execute the GFX and the software packs. And we set the frame buffer strategy to double buffering. With 640 by 480 and the color depth of 16, we need the frame buffer size equal to 614 kilobytes. Having the SDRM available allows us to do double buffering. Then we set the buffer location to buy others to manually specify that the frame buffer will be located in SDRM. SDRM Bank 2 is mapped at 0xD000000, and that's the location of the first frame buffer. We'll place the second frame buffer right after the first frame buffer, meaning 0xD0009600. At this stage, we can generate the code from SDM32 Cubemax. After that, we still need to add the SDRM initialization sequence. And the reason for that is because SDRM does not start trading and directing data immediately after power on. It needs to be initialized in steps, and it's up to the user to add the steps manually. The steps are described in section 23.9.3 SDRM, controller functional description reference menu. The initialization steps are step 1 and step 2, set up the SDRM timing, and that's what we did in the previous steps using SDM32 Cubemax. Step 3, issue a clock-enabled command. Step 4, wait for a minimum of 100 microseconds. Here, we wait for 1 millisecond. Step 5, configure pre-charge old command. Step 6, issue auto-refresh command. Step 7, program the external memory mode. Step 8, set up the refresh counter using the formula, refresh time divided by the number of rows, times the SDRM clock frequency, and then minus 20. And this gives us 1542. These steps are not generated by SDM32 Cubemax. It's up to the user to add them manually. Now we will see, together, how to use the software tools, that GFX designer, SDM32 Cubemax, and SDM32 CubedID to add the SDM to the TouchGFX template based on the SDM32 H7B discovery board. I will use the SDM32 Cubemax project. We used the first video. I will double-click on the IUC file. Here, I have my Cubemax project open. I'll go to Clock Configuration tab. Then, to the PLL2, we set up this multiplier to 200, and then this divided to 1. And here, we get the FMC clock set to 200. Then, we see here the FMC clock max is disabled. I have to enable the FMC from the Pinout and Configuration tab. I go to the Pinout and Configuration tab, Connectivity, and then FMC. I will enable SDM2, and then Clock 1, and Chip Select 1. That's what this schematic uses. Then, I go back to the Clock Configuration tab, and then for the FMC clock, I will use the PLL2R. And here, we have the FMC clock set to 200 megahertz. Here, I need to slow down the Octospot clock. I will use the HCLK3. Then, I go back to the Pinout and Configuration tab to complete the SDM configuration. Our SDM has four internal banks. The address is 12 bits. The data is 16 bits. Byte enable, 16 bits. Then, we set up the number of column address bits. Per the SDM datasheet, it's 9 bits. Number of our address bits is 12. CAS latency is 2 at 100 megahertz. We keep the right protection disabled. Common clock divided by 2. So here, we have the FMC clock and we divide by 2, meaning the SDM clock is 100 megahertz. We enable the burst rate for better performance and two clock cycles for the pipe delay. Then, we need to set up the timing for the memory. The load mode registered to active delay is 2. The exit, self-refresh delay to 7. The self-refresh time to 5. The common row cycle delay to 6. The write recovery time to 3. Common row pre-charge delay to 2. And row to column delay to 2. After the timing configuration, we go to the GPIU settings. And here, we see that the SDM32 KMX default Pinout matches the schematic of the SDM32 H7B discovery board, except for following pins. The clock enable for PB5 and chip select on PB6 and the write enable on PC0. So we need to change the default configuration of the Cubamax. The SDM32 H7B discovery board uses PH7 for the clock enable. Here, we type in PH7. And here, we have the PH7 toggling. Left click on the pin. And here, we set up the FMC clock enable for a PH7. OK. Next pin is the chip select. By default, Cubamax uses PB6, while the schematic uses PH6. So here, we type in PH6. Here, PH6 toggles. Left click. And here, we select chip select for PH6. Then, we have Cubamax using PC0 for the write enable, while the schematic uses PH5. Here, we type in PH5 toggles here. Left click on the pin. And here, we select the SDM write enable. After that, we go to the software packs, and then to X-Cube tech GFX. Here, we need to set up the frame buffer strategy to double buffer. And then buffer location by adders. Start adders for the first frame buffer is D000. Start adders for the second frame buffer is D0009600. And now, we can generate our STM32 Cubamax by clicking on Generate code here. I click Generate code. Here, Cubamax starts generating user source code. OK. The code is successfully generated. I will open the project. I will use the same workspace. I use it in the first video. OK. So now, as I said in the presentation, I still need to add the initialization sequence of the SGR. So I need to go to the main.c file, expand application, user, and main. Here, I have my main function. System clock configuration, CRC, so on and so forth. And here, I have my FMC and that function. So I need to go to the definition of the function and add the SGR initialization sequence. Here, you see here all the SGR configuration we did in using Cubamax. Here, the different timings. And here, I will add the initialization sequence. So this is the SGR initialization sequence we discussed in the presentation. Now, what I will do is I will add a dynamic widget to show the benefit of the double buffering using the SGR. I will go to the TADGFX project and click on the TADGFX file. So here, I want to add a dynamic widget. For example, I will add analog clock, replace it, and then generate the code. I still need to manually add the code to move the needles. And for that, I will go to the TADGFX documentation. You go to Google.com and do search TADGFX analog clock. Here, we have a brief description of the widget. What I need here is the code to move the needles. So this user code. I will copy this code. Go back to PubeID, expand the GUI folder, and then screen one view. Here, we need to go to the header file, right-click, and then open declaration. Here, I will paste the code here. Then go back to the TADGFX documentation and copy the setup screen. Go back to the PubeID. Go to the screen one view, C5. It's a setup screen. We add this code, and then we go back to the documentation. And then we copy this handle tick event. So this code will move the needles every 60 to counter. Place the code here. The name of my view is screen one view, so I need to align it here. And then my widget is analog clock one. So I would add this one here, analog clock one here, and that's it. Now I will build my project. Here, if I go back to the TADGFX designer, I see the name of the widget is analog clock one. That's why I renamed the name of the widget here, analog clock one. Meanwhile, I will connect my board to my laptop to load the code. Now I'm ready to load the code, debuggers and debug. Yeah, the debugger started. OK, now I will execute the code. Here I have my STM32H7B discovery board with the display panel 640 by 480. And here I have the analog clock. You see here the needles moving. Thank you for joining me in today's presentation, and we hope that you enjoyed learning how to customize the TADGFX template.