Jump to content

_gdispInitDriver() doesn't init the ILI9341 driver


Recommended Posts

Posted

Hi,

I'm currently tryying to implement an ILI9341 using an STM32F429, HAL, cmsis_os2 and uGFX, programming in SW4STM32. As i'm working in an RT environment, i declared gfxInit() in the very first task running, which terminates itself after running. Everything compiles fine but thta's during debug that things go south, let me explain.

From peripheral inits to kernel strating, everything's fine. 

In debug mode in gfxInit(), it goes through to _gdispInit() and then gDriverRegister() as intended. But eventhough i changed GDISP_TOTAL_DISPLAYS to 1 instead of 2 by default and defining GDISP_DRIVER_LIST which was set to GDISPVMT_Win32, GDISPVMT_SSD1306  to GDISPVMT_ILI9341 in gdisp_options.h, it won't callback _gdispInitDriver to launch the gdisp_lld_init function and other write functions.

What's the actual problem then ? When calling gdispFillStringBox() and going through it in debug mode, i noticed that the instructions g->p.x through g->p.cy don't actually do anything (the values don't change after those calls according to the debug), same deal when manually calling gdisp_lld_init() in my test thread, with instructions g->g.width through g->g.Contrast, which don't actually change the value in the g struct. This results in the fillarea(g) call from gdispFillStringBox to cycle through 44M values (area = g->p.cx * g->p.cy). Note that when manually calling gdisp_lld_init(), my ILI9341 get reset and initialized fine, but the first gdispFillStringBox() gets pulled into that 44M values for(;;) loop.

I know that GDISP (the default display) and the GDisplay overall struct is a blackbox, but i can't quite understand why internal uGFX calls and API functions can't change the attributes of the GDisplay object.

I'm linking relevant files thereafter.

Thanks in advance for our answer and the time you'll take to help me ! 

Cheers, Arthur 

gdisp_lld_ILI9341.c

/*
 * 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.io/license.html
 */

#include "gfx.h"

#if GFX_USE_GDISP

#if defined(GDISP_SCREEN_HEIGHT) || defined(GDISP_SCREEN_HEIGHT)
	#if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
		#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
	#elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
		COMPILER_WARNING("GDISP: This low level driver does not support setting a screen size. It is being ignored.")
	#endif
	#undef GDISP_SCREEN_WIDTH
	#undef GDISP_SCREEN_HEIGHT
#endif

#define GDISP_DRIVER_VMT			GDISPVMT_ILI9341
#include "gdisp_lld_config.h"
#include "../../../src/gdisp/gdisp_driver.h"

#include "board_ILI9341.h"

/*===========================================================================*/
/* Driver local definitions.                                                 */
/*===========================================================================*/

#define dummy_read(g)				{ volatile gU16 dummy; dummy = read_data(g); (void) dummy; }
#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
#define write_data16(g, data)		{ write_data(g, data >> 8); write_data(g, (gU8)data); }
#define delay(us)					gfxSleepMicroseconds(us)
#define delayms(ms)					gfxSleepMilliseconds(ms)

static void set_viewport(GDisplay *g) {
	write_index(g, 0x2A);
	write_data(g, (g->p.x >> 8));
	write_data(g, (gU8) g->p.x);
	write_data(g, (g->p.x + g->p.cx - 1) >> 8);
	write_data(g, (gU8) (g->p.x + g->p.cx - 1));

	write_index(g, 0x2B);
	write_data(g, (g->p.y >> 8));
	write_data(g, (gU8) g->p.y);
	write_data(g, (g->p.y + g->p.cy - 1) >> 8);
	write_data(g, (gU8) (g->p.y + g->p.cy - 1));
}

/*===========================================================================*/
/* Driver exported functions.                                                */
/*===========================================================================*/

LLDSPEC gBool gdisp_lld_init(GDisplay *g) {
	// No private area for this controller
	g->priv = 0;

	// Initialise the board interface
	init_board(g);

	// Hardware reset
	setpin_reset(g, gTrue);
	gfxSleepMilliseconds(20);
	setpin_reset(g, gFalse);
	gfxSleepMilliseconds(20);

	// Get the bus for the following initialisation commands
	acquire_bus(g);

	write_index(g, 0x01); //software reset
	gfxSleepMilliseconds(5);
	write_index(g, 0x28);
	// display off
	//---------------------------------------------------------
	// magic?
	write_index(g, 0xcf);
	write_data(g, 0x00);
	write_data(g, 0x83);
	write_data(g, 0x30);

	write_index(g, 0xed);
	write_data(g, 0x64);
	write_data(g, 0x03);
	write_data(g, 0x12);
	write_data(g, 0x81);
	write_index(g, 0xe8);
	write_data(g, 0x85);
	write_data(g, 0x01);
	write_data(g, 0x79);
	write_index(g, 0xcb);
	write_data(g, 0x39);
	write_data(g, 0x2c);
	write_data(g, 0x00);
	write_data(g, 0x34);
	write_data(g, 0x02);
	write_index(g, 0xf7);
	write_data(g, 0x20);
	write_index(g, 0xea);
	write_data(g, 0x00);
	write_data(g, 0x00);
	//------------power control------------------------------
	write_index(g, 0xc0); //power control
	write_data(g, 0x26);
	write_index(g, 0xc1); //power control
	write_data(g, 0x11);
	//--------------VCOM
	write_index(g, 0xc5); //vcom control
	write_data(g, 0x35);//35
	write_data(g, 0x3e);//3E
	write_index(g, 0xc7); //vcom control
	write_data(g, 0xbe); // 0x94
	//------------memory access control------------------------
	write_index(g, 0x36);
	// memory access control
	write_data(g, 0x48); //0048 my,mx,mv,ml,BGR,mh,0.0
	write_index(g, 0x3a); // pixel format set
	write_data(g, 0x55);//16bit /pixel
	//----------------- frame rate------------------------------
	write_index(g, 0xb1);
	// frame rate
	write_data(g, 0x00);
	write_data(g, 0x1B); //70
	//----------------Gamma---------------------------------
	write_index(g, 0xf2); // 3Gamma Function Disable
	write_data(g, 0x08);
	write_index(g, 0x26);
	write_data(g, 0x01); // gamma set 4 gamma curve 01/02/04/08

	write_index(g, 0xE0); //positive gamma correction
	write_data(g, 0x1f);
	write_data(g, 0x1a);
	write_data(g, 0x18);
	write_data(g, 0x0a);
	write_data(g, 0x0f);
	write_data(g, 0x06);
	write_data(g, 0x45);
	write_data(g, 0x87);
	write_data(g, 0x32);
	write_data(g, 0x0a);
	write_data(g, 0x07);
	write_data(g, 0x02);
	write_data(g, 0x07);
	write_data(g, 0x05);
	write_data(g, 0x00);
	write_index(g, 0xE1); //negamma correction
	write_data(g, 0x00);
	write_data(g, 0x25);
	write_data(g, 0x27);
	write_data(g, 0x05);
	write_data(g, 0x10);
	write_data(g, 0x09);
	write_data(g, 0x3a);
	write_data(g, 0x78);
	write_data(g, 0x4d);
	write_data(g, 0x05);
	write_data(g, 0x18);
	write_data(g, 0x0d);
	write_data(g, 0x38);
	write_data(g, 0x3a);
	write_data(g, 0x1f);
	//--------------ddram ---------------------
	write_index(g, 0x2a);
	// column set
	// size = 239
	write_data(g, 0x00);
	write_data(g, 0x00);
	write_data(g, 0x00);
	write_data(g, 0xEF);
	write_index(g, 0x2b);
	// page address set
	// size = 319
	write_data(g, 0x00);
	write_data(g, 0x00);
	write_data(g, 0x01);
	write_data(g, 0x3F);
	// write_index(g, 0x34);
	//write_index(g, 0x35);
	// tearing effect off
	// tearing effect on
	// write_index(g, 0xb4); // display inversion
	// write_data(g, 0x00);
	write_index(g, 0xb7); //entry mode set
	write_data(g, 0x07);
	//-----------------display---------------------
	write_index(g, 0xb6);
	// display function control
	write_data(g, 0x0a);
	write_data(g, 0x82);
	write_data(g, 0x27);
	write_data(g, 0x00);
	write_index(g, 0x11); //sleep out
	gfxSleepMilliseconds(100);
	write_index(g, 0x29); // display on
	gfxSleepMilliseconds(100);

    // Finish Init
    post_init_board(g);

 	// Release the bus
	release_bus(g);
	
	/* Turn on the back-light */
	set_backlight(g, GDISP_INITIAL_BACKLIGHT);

	/* Initialise the GDISP structure */
	g->g.Width = (gCoord) GDISP_SCREEN_WIDTH;
	g->g.Height = (gCoord)GDISP_SCREEN_HEIGHT;
	g->g.Orientation = gOrientation0;
	g->g.Powermode = gPowerOn;
	g->g.Backlight = (gCoord)GDISP_INITIAL_BACKLIGHT;
	g->g.Contrast = (gCoord)GDISP_INITIAL_CONTRAST;
	return gTrue;
}

#if GDISP_HARDWARE_STREAM_WRITE
	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
		acquire_bus(g);
		set_viewport(g);
		write_index(g, 0x2C);
	}
	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
		write_data16(g, gdispColor2Native(g->p.color));
	}
	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
		release_bus(g);
	}
#endif

#if GDISP_HARDWARE_STREAM_READ
	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
		acquire_bus(g);
		set_viewport(g);
		write_index(g, 0x2E);
		setreadmode(g);
		dummy_read(g);
	}
	LLDSPEC	gColor gdisp_lld_read_color(GDisplay *g) {
		gU16	data;

		data = read_data(g);
		return gdispNative2Color(data);
	}
	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
		setwritemode(g);
		release_bus(g);
	}
#endif

#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
	LLDSPEC void gdisp_lld_control(GDisplay *g) {
		switch(g->p.x) {
		case GDISP_CONTROL_POWER:
			if (g->g.Powermode == (gPowermode)g->p.ptr)
				return;
			switch((gPowermode)g->p.ptr) {
			case gPowerOff:
			case gPowerSleep:
			case gPowerDeepSleep:
				acquire_bus(g);
				write_reg(g, 0x0010, 0x0001);	/* enter sleep mode */
				release_bus(g);
				break;
			case gPowerOn:
				acquire_bus(g);
				write_reg(g, 0x0010, 0x0000);	/* leave sleep mode */
				release_bus(g);
				break;
			default:
				return;
			}
			g->g.Powermode = (gPowermode)g->p.ptr;
			return;

		case GDISP_CONTROL_ORIENTATION:
			if (g->g.Orientation == (gOrientation)g->p.ptr)
				return;
			switch((gOrientation)g->p.ptr) {
			case gOrientation0:
				acquire_bus(g);
				write_reg(g, 0x36, 0x48);	/* X and Y axes non-inverted */
				release_bus(g);
				g->g.Height = GDISP_SCREEN_HEIGHT;
				g->g.Width = GDISP_SCREEN_WIDTH;
				break;
			case gOrientation90:
				acquire_bus(g);
				write_reg(g, 0x36, 0xE8);	/* Invert X and Y axes */
				release_bus(g);
				g->g.Height = GDISP_SCREEN_WIDTH;
				g->g.Width = GDISP_SCREEN_HEIGHT;
				break;
			case gOrientation180:
				acquire_bus(g);
				write_reg(g, 0x36, 0x88);		/* X and Y axes non-inverted */
				release_bus(g);
				g->g.Height = GDISP_SCREEN_HEIGHT;
				g->g.Width = GDISP_SCREEN_WIDTH;
				break;
			case gOrientation270:
				acquire_bus(g);
				write_reg(g, 0x36, 0x28);	/* Invert X and Y axes */
				release_bus(g);
				g->g.Height = GDISP_SCREEN_WIDTH;
				g->g.Width = GDISP_SCREEN_HEIGHT;
				break;
			default:
				return;
			}
			g->g.Orientation = (gOrientation)g->p.ptr;
			return;

        case GDISP_CONTROL_BACKLIGHT:
            if ((unsigned)g->p.ptr > 100)
            	g->p.ptr = (void *)100;
            set_backlight(g, (unsigned)g->p.ptr);
            g->g.Backlight = (unsigned)g->p.ptr;
            return;

		//case GDISP_CONTROL_CONTRAST:
        default:
            return;
		}
	}
#endif

#endif /* GFX_USE_GDISP */

My test task StartLCDTask in main.c, that has a .stack_size of 1280.

void StartLCDTask(void *argument)
{
		gCoord		width, height, x, y;

		width = height = x = y = 0;
	    // Initialize the display
		HAL_GPIO_WritePin(RST_LCD_GPIO_Port, RST_LCD_Pin, GPIO_PIN_SET);
	    // Get the screen size
		width = gdispGetWidth();
			gFont		font1, font2;
			gCoord		fheight1, fheight2;
			const char	*line1, *line2;
			char		buf[8];

		    // Initialize and clear the display

		    // Get the screen size
		    width = 240;

		    // Get the fonts we want to use
			font1 = gdispOpenFont("DejaVuSans10*");
			font2 = gdispOpenFont("UI1*");
			//font2 = gdispOpenFont("Geosans*");
			//font2 = gdispOpenFont("Free*");
			//font2 = gdispOpenFont("Hellovetica*");
			//font2 = gdispOpenFont("babyblue*");
			//font2 = gdispOpenFont("PF Ronda*");
			//font2 = gdispOpenFont("Apple*");

			y = 0;
			fheight1 = gdispGetFontMetric(font1, gFontHeight)+2;
			fheight2 = gdispGetFontMetric(font2, gFontHeight)+2;

			line1 = "Check out my FONTS STM32F4";
			line2 = "0123456789~!@#$%^&*_-+=(){}[]<>|/\\:;,.?'\"`";

			// Font 1
			gdispFillStringBox(0, y, width,  20, line1, font1, GFX_BLACK, GFX_WHITE, gJustifyCenter);
			y += fheight1+1;
			gdispFillStringBox(0, y, width,  40, line2, font1, GFX_BLACK, GFX_WHITE, gJustifyCenter);
			y += fheight1+1;

			// Font 2
			gdispFillStringBox(0, y, width,  fheight2, line1, font2, GFX_BLACK, GFX_WHITE, gJustifyCenter);
			y += fheight2+1;
			gdispFillStringBox(0, y, width,  fheight2, line2, font2, GFX_BLACK, GFX_WHITE, gJustifyCenter);
			y += fheight2+1;

			// Font 1 drawing White on the (GFX_WHITE) background
			gdispDrawStringBox(0, y, width,  fheight1, line1, font1, GFX_WHITE, gJustifyCenter);
			y += fheight1+1;
			gdispDrawStringBox(0, y, width,  fheight1, line2, font1, GFX_WHITE, gJustifyCenter);
			y += fheight1+1;

				// Show Sizes
			buf[0] = (fheight1-2)/10 + '0';
			buf[1] = (fheight1-2)%10 + '0';
			buf[2] = ',';
			buf[3] = ' ';
			buf[4] = (fheight2-2)/10 + '0';
			buf[5] = (fheight2-2)%10 + '0';
			buf[6] = 0;
			gdispFillStringBox(0, y, width,  fheight1, buf, font1, GFX_RED, GFX_WHITE, gJustifyCenter);

  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END 5 */ 
}

gfxconf.h 

#define GFX_USE_OS_CMSIS2                            GFXON
#define GFX_OS_NO_INIT                               GFXON
#define GFX_USE_GDISP                                GFXON
#define GDISP_NEED_VALIDATION                        GFXON
#define GDISP_NEED_CIRCLE                            GFXON
#define GDISP_NEED_MULTITHREAD                       GFXON
#define GDISP_NEED_STREAMING                         GFXON
#define GDISP_NEED_TEXT                              GFXON
    #define GDISP_NEED_UTF8                          GFXON
    #define GDISP_INCLUDE_FONT_UI1                   GFXON
    #define GDISP_INCLUDE_FONT_DEJAVUSANS10          GFXON
#define GFX_USE_GTIMER                               GFXON

board_ili9341.h

#ifndef _GDISP_LLD_BOARD_H
#define _GDISP_LLD_BOARD_H
#include "main.h"
#define LCD_DC_CMD	HAL_GPIO_WritePin(DC_LCD_GPIO_Port, DC_LCD_Pin, GPIO_PIN_RESET)
#define LCD_DC_DATA	HAL_GPIO_WritePin(DC_LCD_GPIO_Port, DC_LCD_Pin, GPIO_PIN_SET)
#define LCD_RST_SET	HAL_GPIO_WritePin(RST_LCD_GPIO_Port, RST_LCD_Pin, GPIO_PIN_SET)
#define LCD_RST_RES	HAL_GPIO_WritePin(RST_LCD_GPIO_Port, RST_LCD_Pin, GPIO_PIN_RESET)
#define LCD_CS_RES	HAL_GPIO_WritePin(CS_LCD_GPIO_Port, CS_LCD_Pin, GPIO_PIN_RESET)
#define LCD_CS_SET	HAL_GPIO_WritePin(CS_LCD_GPIO_Port, CS_LCD_Pin, GPIO_PIN_SET)
/**
 * SPI configuration structure.
 * Speed 12 MHz, CPHA=0, CPOL=0, 8bits frames, MSb transmitted first.
 * Soft slave select.
 */
SPI_HandleTypeDef hspi4;

static void send_data(gU16 data);

/**
 * @brief   Initialise the board for the display.
 *
 * @param[in] g			The GDisplay structure
 *
 * @note	Set the g->board member to whatever is appropriate. For multiple
 * 			displays this might be a pointer to the appropriate register set.
 *
 * @notapi
 */
static 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 = NULL;
  LCD_CS_SET;
  LCD_DC_CMD;
}
/**
 * @brief   After the initialisation.
 *
 * @param[in] g			The GDisplay structure
 *
 * @notapi
 */
static void post_init_board(GDisplay *g) {
	(void) g;
	LCD_DC_DATA;
}

/**
 * @brief   Set or clear the lcd reset pin.
 *
 * @param[in] g			The GDisplay structure
 * @param[in] state		gTrue = lcd in reset, gFalse = normal operation
 * 
 * @notapi
 */
static void setpin_reset(GDisplay *g, gBool state) {
	(void) g;

	if (state == -1) {
		LCD_RST_RES;
	} else {
		LCD_RST_SET;
	}
}

/**
 * @brief   Set the lcd back-light level.
 *
 * @param[in] g				The GDisplay structure
 * @param[in] percent		0 to 100%
 * 
 * @notapi
 */
static void set_backlight(GDisplay *g, gU8 percent) {
	(void) g;
	(void) percent;
}

/**
 * @brief   Take exclusive control of the bus
 *
 * @param[in] g				The GDisplay structure
 *
 * @notapi
 */
static void acquire_bus(GDisplay *g) {
	(void) g;
	LCD_CS_RES;
}

/**
 * @brief   Release exclusive control of the bus
 *
 * @param[in] g				The GDisplay structure
 *
 * @notapi
 */
static void release_bus(GDisplay *g) {
	(void) g;
	LCD_CS_SET;
}

/**
 * @brief   Send data to the lcd.
 *
 * @param[in] data			The data to send
 * 
 * @notapi
 */
static inline  void send_data(gU16 data) {

	HAL_SPI_Transmit(&hspi4, &data, sizeof(data), HAL_MAX_DELAY);

}

/**
 * @brief   Send data to the index register.
 *
 * @param[in] g				The GDisplay structure
 * @param[in] index			The index register to set
 *
 * @notapi
 */
static inline  void write_index(GDisplay *g, gU16 index) {
	(void) g;


  LCD_DC_CMD;
  send_data(index);
  LCD_DC_DATA;


}

/**
 * @brief   Send data to the lcd with DC control.
 *
 * @param[in] g				The GDisplay structure
 * @param[in] data			The data to send
 * 
 * @notapi
 */
static  inline void write_data(GDisplay *g, gU16 data) {
	(void) g;
	LCD_DC_DATA;
  send_data(data);
}

/**
 * @brief   Set the bus in read mode
 *
 * @param[in] g				The GDisplay structure
 *
 * @notapi
 */
static  inline void setreadmode(GDisplay *g) {
	(void) g;
}

/**
 * @brief   Set the bus back into write mode
 *
 * @param[in] g				The GDisplay structure
 *
 * @notapi
 */
static inline  void setwritemode(GDisplay *g) {
	(void) g;
}

/**
 * @brief   Read data from the lcd.
 * @return	The data from the lcd
 *
 * @param[in] g				The GDisplay structure
 *
 * @notapi
 */
static inline  gU16 read_data(GDisplay *g) {
	(void) g;
	return 0;
}

#endif /* _GDISP_LLD_BOARD_H */

 

Posted

The problem here is a build problem.

GDISP builds in 2 possible modes - single display and multiple display. Which it uses is a complex combination of include paths, variables in gfxconf.h and linking. The build results in quite different code for the two options.

If your gdisp_lld_init is not being called it means you have this process wrong.

First GDISP_TOTAL_DISPLAYS, GDISP_DRIVER_LIST and GDISP_PIXEL_FORMAT should not be defined at all in your gfxconf.h for a single display. Instead the specific driver directory you want to use should be on your compiler INCLUDE path and the specific driver files should be included in the build.

Also, the various _options.h files should not be altered. All your customizations should be in your gfxconf.h file. See the example demo programs and the provided gfx.conf.example file in the top directory.

In general look carefully at the provided build files and the wiki if you have any questions.

Posted (edited)

Hi @inmarket and thank you for the swift reply,

I rolled back the changes made to the gdisp_options.h file after posting my message. 

I followed the wiki using Eclipse at this link and went through the whole process but include paths look like i got everything (see linked image).

I used the single file inclusion, do you think i should consider using the makefile approach ? I'm a bit kinky about what ST is doing with its compiler in SW4STM32.

Thanks again for your time, 

Arthur

image.png.3d18852b5aa27beebc4a6006cd6a0224.png

Edited by Arthur O.
Posted

This looks like GDISP is set to some random value in flash. It is certainly not valid.

The GDISP variable is not initialised until after the first display driver is initialised so don't expect it to be valid until after that.

With regard to eclipse - I don't use it but I know there are many in the community that do. Personally I much prefer the make system - just create a makefile (I can't remember off the top of my head where the master example one is) and it does everything for you.

Posted

Hi again @inmarket and thanks for taking the time,

Thanks for the direction, i'll look into it. I'm not that familiar with makefiles as a whole i'm quite a newbie in C development. Good reason to learn then !

So do you know if the initialized display driver has its own instance of GDisplay type or is it stored in the GDISP variable anyway ? 

Thank you again cheers, Arthur

Posted

Each display driver creates a GDisplay object to hold its run-time data. The first display in the system gets assigned to the GDISP pointer. All drivers, of any type, are maintained in a GDriver list.

In your case because the init process is not happening correctly GDISP is totally invalid.

Posted

Hi @inmarket i found the problem ! I didn't define the heap size in gfxconf.h, hence the invalid adressing and values of the GDISP variable. I defined it as 8192 and it woks like a charm ! I suspect i didn't allocate enough stack either to the thread so that's all fixed now. Thanks again for your time and for the library !

Cheers,

Arthur 

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...