LeMoussel Posted October 26, 2014 Report Posted October 26, 2014 Hi all, I am using the STM32F103 board with 240x320 TFT (ILI9325). I use uGFX in GOS port mode.In file board_ILI9325.h, I use the STM stdperiph library functions to control ILI9325 peripheral.But I have a small problem.With this code there is no display.int main(void){ coord_t width, height; /* Setup STM32 system (clock, PLL and Flash configuration) */ SystemInit(); gfxInit(); // Get the screen size width = gdispGetWidth(); height = gdispGetHeight(); gdispClear(Green); while(TRUE) { gfxSleepMilliseconds(1000); // Wait 1 Sec; }}board_ILI9325.hstatic inline void init_board(GDisplay *g) { // As we are not using multiple displays we set g->board to NULL as we don't use it. g->board = 0; switch(g->controllerdisplay) { case 0: // Set up for Display 0 LCD_Init(); break; }}static inline void write_index(GDisplay *g, uint16_t index) { (void) g; LCD_CS = 0; LCD_RS = 0; GPIOC->ODR = (GPIOC->ODR & 0xff00) | (index & 0x00ff); GPIOB->ODR = (GPIOB->ODR & 0x00ff) | (index & 0xff00); LCD_WR = 0; LCD_WR = 1; LCD_CS = 1;}static inline void write_data(GDisplay *g, uint16_t data) { (void) g; LCD_CS = 0; LCD_RS = 1; GPIOC->ODR = (GPIOC->ODR & 0xff00) | (data & 0x00ff); GPIOB->ODR = (GPIOB->ODR & 0x00ff) | (data & 0xff00); LCD_WR = 0; LCD_WR = 1; LCD_CS = 1;}But with this code, background display is green !int main(void){ coord_t width, height; /* Setup STM32 system (clock, PLL and Flash configuration) */ SystemInit(); gfxInit(); LCD_Init(); // Get the screen size width = gdispGetWidth(); height = gdispGetHeight(); gdispClear(Green); while(TRUE) { gfxSleepMilliseconds(1000); // Wait 1 Sec; }}
Joel Bodenmann Posted October 26, 2014 Report Posted October 26, 2014 Can you fire up your debugger and get a dump (examine) of the GDisplay struct within the init_board() routine?~ Tectu
LeMoussel Posted October 26, 2014 Author Report Posted October 26, 2014 in init_board(GDisplay *g)"g" 0x2000085c g {...} Width 0 Height 0 Orientation GDISP_ROTATE_0 Powermode powerOff Backlight 0 Contrast 0 priv 0x00000000 board 0x00000000 systemdisplay 0 controllerdisplay 0 flags 0 clipx0 0 clipy0 0 clipx1 0 clipy1 0 p {...} x 0 y 0 cx 0 cy 0 x1 0 y1 0 x2 0 y2 0 color 0 ptr 0x00000000 in gdispGClear(GDisplay *g, color_t color)"g" 0x2000085c g {...} Width 240 Height 320 Orientation GDISP_ROTATE_0 Powermode powerOn Backlight 'd' Contrast '2' priv 0x00000000 board 0x00000000 systemdisplay 0 controllerdisplay 0 flags 0 clipx0 0 clipy0 0 clipx1 240 clipy1 320 p {...} x 0 y 0 cx 240 cy 320 x1 0 y1 0 x2 0 y2 0 color 0 ptr 0x00000000
Joel Bodenmann Posted October 26, 2014 Report Posted October 26, 2014 So when I understand you correctly, when you manually issue the LCD_Init() routine after gfxInit(), you still use your board file to write the data, right? Do you still have the LCD_Init() routine within the init_board() routine? If not, can you check if the code in LCD_Init() does actually get executed when init_board() is being called? Does it get stuck somewhere?Sorry, I have no clue what the problem is yet - maybe inmarket will have an idea.~ Tectu
LeMoussel Posted October 27, 2014 Author Report Posted October 27, 2014 when you manually issue the LCD_Init() routine after gfxInit(), you still use your board file to write the data, right?Yes.Do you still have the LCD_Init() routine within the init_board() routine?Yes. LCD_Init() get executed when init_board() is being called.static inline void init_board(GDisplay *g) { // As we are not using multiple displays we set g->board to NULL as we don't use it. g->board = 0; switch(g->controllerdisplay) { case 0: // Set up for Display 0 LCD_Init(); break; }}
inmarket Posted October 27, 2014 Report Posted October 27, 2014 I suspect one of three things...1. It is requiring LCD_Init() to be called twice.2. There is a timing issue and calling it later saves the day, or3. There is some difference in the IO state between the two locations.I would try putting a delay before and after LCD_Init() in the board file, checking the LCD_Init() is actually being called, putting a double call to LCD_Init() in the board file (possibly with a decent delay between them).Another thing to try is to ensure the uGFX startup logo is turned on and see if that displays or you at least get the delay associated with its display (a few seconds I think).Hope that helps.
inmarket Posted October 27, 2014 Report Posted October 27, 2014 Another quick thought...uGFX assumes that the .bss segment has been cleared to zero as per the C standard. The .bss segment stores variables that have not been explicitly initialised in your code at compile time. This task is usually performed by the C runtime before reaching your main function.It is however possible that because you have no C runtime library that your cpu startup code is not clearing the .bss segment. That will cause all sorts of strange issues.This is one of those embedded development traps.
Joel Bodenmann Posted October 27, 2014 Report Posted October 27, 2014 uGFX assumes that the .bss segment has been cleared to zero as per the C standard. The .bss segment stores variables that have not been explicitly initialised in your code at compile time. This task is usually performed by the C runtime before reaching your main function.It is however possible that because you have no C runtime library that your cpu startup code is not clearing the .bss segment. That will cause all sorts of strange issues.This is one of those embedded development traps.We should start a wiki article about these traps in the 'Deverlopers Guide' section.~ Tectu
LeMoussel Posted October 27, 2014 Author Report Posted October 27, 2014 I use base C library -mcpu=cortex-m3; -mthumb; -g; -nostartfiles; -Map=Test_uGFX.map; -O0; --gc-sections; -lm; -lgcc; -lc; -L${linkdir}; -T${linkdir}/arm-gcc-link.ld; If I do static inline void init_board(GDisplay *g) { (void) g;}static inline void post_init_board(GDisplay *g) { (void) g; LCD_Init();}with no call to LCD_Init() in main program, I see uGFX startup logo & background display is green Strange Not ?
Joel Bodenmann Posted October 27, 2014 Report Posted October 27, 2014 You are definitely not supposed to put LCD_Init() into the post_board_init() function. Please do the few things that inmarket suggested.Can you show us the content of your LCD_Init() routine?~ Tectu
LeMoussel Posted October 28, 2014 Author Report Posted October 28, 2014 I do not understand what I need to do more that inmarket has suggested.I directly put LCD_Init() code into post_init_board().board_ILI9325.h/* * This file is subject to the terms of the GFX License. If a copy of * the license was not distributed with this file, you can obtain one at: * * http://ugfx.org/license.html */#ifndef GDISP_LLD_BOARD_H#define GDISP_LLD_BOARD_H#include #define _STDINT_H// IO port operations macro definition#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))// LCD control pin configuration#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n)#define LCD_CS PCout(8)#define LCD_RS PCout(9)#define LCD_WR PCout(10)#define LCD_RD PCout(11)#include "stm32f10x.h"static inline void write_index(GDisplay *g, uint16_t index);static inline void write_data(GDisplay *g, uint16_t data);static inline void write_reg(GDisplay *g, uint16_t reg, uint16_t data);static inline uint16_t read_reg(GDisplay *g, uint16_t reg);static inline void init_board(GDisplay *g) { (void) g;}static inline void post_init_board(GDisplay *g) { (void) g; GPIO_InitTypeDef GPIO_InitStructure; uint16_t DeviceCode; // Open the clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC,ENABLE); // Configuration data IO connected to GPIOB GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // Push-pull output GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // Output IO ports for maximum speed 50MHZ GPIO_Init(GPIOB, &GPIO_InitStructure); // Configuration Control IO connected to PD12.PD13.PD14.PD15/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); write_reg(g, 0x0000, 0x0001); gfxSleepMilliseconds(50); DeviceCode = read_reg(g, 0x0000); //LCD_ReadReg(0x0000); // Check if the LCD is ILI9325 Controller if(DeviceCode == 0x9325 || DeviceCode == 0x9328) { write_reg(g,0x00e5,0x78F0); /* Start Initial Sequence ------------------------------------------------*/ write_reg(g,0x0001,0x0100); // Driver output control (makes it scan top left to bottom right, odd for top half, even for bottom) write_reg(g,0x0002,0x0700); // Line inversion on the LCD Driving Wave Control write_reg(g,0x0003,0x1030); // Entry mode set. Set GRAM write direction and BGR=1. write_reg(g,0x0004,0x0000); // Resizing register write_reg(g,0x0008,0x0202); // (Display control 2) Set 2 lines for both front and back porch (minimum number, helps VSYNC) write_reg(g,0x0009,0x0000); // (Display control 3) Sets 0 frame scan cycle and normal scan. Set non-display area refresh cycle ISC[3] write_reg(g,0x000a,0x0000); // FMARK signal function write_reg(g,0x000c,0x0001); // 16-bit RGB interface (1 transfer/pixel), using internal system clock and system interface write_reg(g,0x000d,0x0000); // Frame Marker at position 0 (starts outputting frame right away) write_reg(g,0x000f,0x0000); // RGB interface polarit. Data input on rising edge of DOTCLK, data written when ENABLE=0,HSPL/VSPL(H/VSYNC pins) Low polarit = active /* Power On sequence -----------------------------------------------------*/ write_reg(g,0x0010,0x0000); // (Power control 1) Enable power supply write_reg(g,0x0011,0x0007); // (Power control 2) Ref. voltage(VciOUT) = Vci1, operating frequency = Fosc in circuit 1 and Fosc/16 in circuit 2 write_reg(g,0x0012,0x0000); // (Power control 3) Enable VGL output, use internal electric volume(VCM) to set VcomH(Vcom center voltage level write_reg(g,0x0013,0x0000); // (Power control 4) VCOM Amplitude = VREG1OUT x 0.90 write_reg(g,0x0007,0x0001); // (Display control 1) Set display to operate, VCOM output to GND gfxSleepMilliseconds(50); // Delay 50ms write_reg(g,0x0010,0x1690); // (Power control 1) Enable power supply(0x10c0) write_reg(g,0x0011,0x0227); gfxSleepMilliseconds(50); write_reg(g,0x0012,0x009d); gfxSleepMilliseconds(50); write_reg(g,0x0013,0x1900); // (Power control 4) VCOM Amplitude = VREG1OUT x 0.90 write_reg(g,0x0029,0x0025); // (Power control 7) VcomH voltage = VREG1OUT x .69 write_reg(g,0x002b,0x000d); // ??Hz frame rate, internal resistor. gfxSleepMilliseconds(50); write_reg(g,0x0020,0x0000); // GRAM horizontal Address write_reg(g,0x0021,0x0000); // GRAM Vertical Address */ gfxSleepMilliseconds(50); write_reg(g,0x0030,0x0007); write_reg(g,0x0031,0x0303); write_reg(g,0x0032,0x0003); write_reg(g,0x0035,0x0206); write_reg(g,0x0036,0x0008); write_reg(g,0x0037,0x0406); write_reg(g,0x0038,0x0304); write_reg(g,0x0039,0x0007); write_reg(g,0x003c,0x0602); write_reg(g,0x003d,0x0008); gfxSleepMilliseconds(50); write_reg(g,0x0050,0x0000); // Set X Star. X starts at 0. write_reg(g,0x0051,0x00ef); // Set X End. X ends at 239. write_reg(g,0x0052,0x0000); // Set Y Star. Y starts at 0. write_reg(g,0x0053,0x013f); // Set Y End. Y ends at 319. write_reg(g,0x0060,0xa700); // (Driver output control) Gate scans at 0, ends after 320 lines write_reg(g,0x0061,0x0001); // (Driver output control) grayscale inversion. write_reg(g,0x006a,0x0000); // (Vertical scroll control) not used write_reg(g,0x0080,0x0000); // Display position for partial image 1 write_reg(g,0x0081,0x0000); // RAM address for start of partial image 1 write_reg(g,0x0082,0x0000); // RAM address for end of partial image 1 write_reg(g,0x0083,0x0000); // Display position for partial image 2 write_reg(g,0x0084,0x0000); // RAM address for start of partial image 2 write_reg(g,0x0085,0x0000); // RAM address for end of partial image 2 write_reg(g,0x0090,0x0010); // (Panel interface control 1) Sets clock number for internal clock write_reg(g,0x0092,0x0600); // (Panel interface control 2) 0 Clocks of overlap when synced write_reg(g,0x0007,0x0133); // (Display control 1) Set display to operate, base image display, normal display }}static inline void setpin_reset(GDisplay *g, bool_t state) { (void) g; (void) state;}static inline void set_backlight(GDisplay *g, uint8_t percent) { (void) g; (void) percent;}static inline void acquire_bus(GDisplay *g) { (void) g;}static inline void release_bus(GDisplay *g) { (void) g;}static inline void write_index(GDisplay *g, uint16_t index) { (void) g; LCD_CS = 0; LCD_RS = 0; GPIOC->ODR = (GPIOC->ODR & 0xff00) | (index & 0x00ff); GPIOB->ODR = (GPIOB->ODR & 0x00ff) | (index & 0xff00); LCD_WR = 0; LCD_WR = 1; LCD_CS = 1;}static inline void write_data(GDisplay *g, uint16_t data) { (void) g; LCD_CS = 0; LCD_RS = 1; GPIOC->ODR = (GPIOC->ODR & 0xff00) | (data & 0x00ff); GPIOB->ODR = (GPIOB->ODR & 0x00ff) | (data & 0xff00); LCD_WR = 0; LCD_WR = 1; LCD_CS = 1;}static inline void write_reg(GDisplay *g, uint16_t reg, uint16_t data){ write_index(g, reg); write_data(g, data);}static inline uint16_t read_reg(GDisplay *g, uint16_t reg){ uint16_t value; write_index(g, reg); // configure pins for reading GPIOB->CRH = (GPIOB->CRH & 0x00000000) | 0x44444444; GPIOC->CRL = (GPIOC->CRL & 0x00000000) | 0x44444444; LCD_CS = 0; LCD_RS = 1; LCD_RD = 0; value = ((GPIOB->IDR&0xff00)|(GPIOC->IDR&0x00ff)); LCD_RD = 1; LCD_CS = 1; // reconfigure back to normal operation GPIOB->CRH = (GPIOB->CRH & 0x00000000) | 0x33333333; GPIOC->CRL = (GPIOC->CRL & 0x00000000) | 0x33333333; return value;}static inline void setreadmode(GDisplay *g) { (void) g;}static inline void setwritemode(GDisplay *g) { (void) g;}static inline uint16_t read_data(GDisplay *g) { (void) g; return 0;}#endif /* GDISP_LLD_BOARD_H */
Joel Bodenmann Posted October 28, 2014 Report Posted October 28, 2014 You are NOT supposed to manipulate any register values of the controller in the board file. The only thing that you are supposed to do in there is to set up the GPIO modes and stuff like that.For starting your post_init_board() routine should be empty and your init_board() should contain all the GPIO code.Your board file should look something like this (just so you have a structural idea - this will not compile):/* * This file is subject to the terms of the GFX License. If a copy of * the license was not distributed with this file, you can obtain one at: * * http://ugfx.org/license.html */#ifndef GDISP_LLD_BOARD_H#define GDISP_LLD_BOARD_Hstatic inline void init_board(GDisplay *g) { (void) g; GPIO_InitTypeDef GPIO_InitStructure; // Open the clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC,ENABLE); // Configuration data IO connected to GPIOB GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // Push-pull output GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // Output IO ports for maximum speed 50MHZ GPIO_Init(GPIOB, &GPIO_InitStructure); // Configuration Control IO connected to PD12.PD13.PD14.PD15/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure);}static inline void post_init_board(GDisplay *g) { (void) g;}static inline void setpin_reset(GDisplay *g, bool_t state) { (void) g; (void) state;}static inline void set_backlight(GDisplay *g, uint8_t percent) { (void) g; (void) percent;}static inline void acquire_bus(GDisplay *g) { (void) g;}static inline void release_bus(GDisplay *g) { (void) g;}static inline void write_index(GDisplay *g, uint16_t index) { (void) g; LCD_CS = 0; LCD_RS = 0; GPIOC->ODR = (GPIOC->ODR & 0xff00) | (index & 0x00ff); GPIOB->ODR = (GPIOB->ODR & 0x00ff) | (index & 0xff00); LCD_WR = 0; LCD_WR = 1; LCD_CS = 1;}static inline void write_data(GDisplay *g, uint16_t data) { (void) g; LCD_CS = 0; LCD_RS = 1; GPIOC->ODR = (GPIOC->ODR & 0xff00) | (data & 0x00ff); GPIOB->ODR = (GPIOB->ODR & 0x00ff) | (data & 0xff00); LCD_WR = 0; LCD_WR = 1; LCD_CS = 1;}static inline void setreadmode(GDisplay *g) { (void) g;}static inline void setwritemode(GDisplay *g) { (void) g;}static inline uint16_t read_data(GDisplay *g) { (void) g; return 0;}#endif /* GDISP_LLD_BOARD_H */~ Tectu
LeMoussel Posted October 28, 2014 Author Report Posted October 28, 2014 I did what you said.Screen is white & uGFX startup logo is not displayed
Joel Bodenmann Posted October 29, 2014 Report Posted October 29, 2014 Now we hit a different problem: We have many issues with the ILI based display drivers because they exist in many different versions. Often you get an ILI9320 instead of an ILI9325 and vice-versa. In order to finally get your display running, please take the initialization code (that are all the write_reg commands in your LCD_Init() routine and replace the ones in the drivers initialization routine (gdisp_lld_init() routine in /drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c) with them.Let us know when you have any questions.We are sorry for this inconvenience but we have not found a good solution to this problem yet. We will add an optional custom initialization code interface in the future.~ Tectu
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now