Apalis iMX6 GPIO Speed

Hello All,

I am relatively new to the wide world of Toradex/Embedded Linux (Most of my embedded experience has been in the PIC32/FreeRTOS land) and I am running into an issue. We have a 256x64 OLED display that is connected via GPIO to the apalis iMX6Q with a Preemptive RT Linux Kernel. This GPIO is in an 8-bit configuration. The unfortunate thing is that we are forced to use this horizontal screen in a vertical orientation which now means that for every screen update, 256 * 8 bytes of data must be clocked out to the display. Now I have accomplished this and have a functioning display. However, the maximum refresh that I am able to achieve is ~1.8 Hz. This is really not fast enough, I am hoping to get ~10 Hz. Based on investigation, this is a result of slow execution of Linux’s sysfs file writes and priorities of execution. I have read that there is really no direct way to manipulate the GPIO hardware, that a linux kernel driver is about as close as one could safely get. I have no idea how to accomplish this and I would really like to avoid having to recompile the OS. Below is my write function that is called in a loop to clock out the display data, any thoughts on how to speed this up, or make it such that linux is forced to execute this and only this every time it is called? Thanks!

void WritePort(unsigned char data)
{
	static char in[1] = {0};
	static bool ok;


	// Before we can write the port, we have to ensure that the data buffer
	// on the display is ready for more data.  How this is done depends on
	// whether or not pin 3 is set up for PBUSY or not

	#if NORITAKE_OLED_BUSY_CONNECTED == 1
		// Wait for BUSY line to be de-asserted

		do
		{
			read(fdCFG, in, 1);
		}
		while(!atoi(in));

	#else

		write(dirfd, "in", 2);

		do
		{
			write(fdRD, "0", 1);
			usleep(1);
			read(fdDBUS[7], in, 1);
			ok = in[0];
			write(fdRD, "1", 1);
		}
		while (ok);

		write(dirfd, "out", 3);

	#endif

	if(data & 0x01) write(fdDBUS[0], "1", 1); else write(fdDBUS[0], "0", 1);
	if(data & 0x02) write(fdDBUS[1], "1", 1); else write(fdDBUS[1], "0", 1);
	if(data & 0x04) write(fdDBUS[2], "1", 1); else write(fdDBUS[2], "0", 1);
	if(data & 0x08) write(fdDBUS[3], "1", 1); else write(fdDBUS[3], "0", 1);
	if(data & 0x10) write(fdDBUS[4], "1", 1); else write(fdDBUS[4], "0", 1);
	if(data & 0x20) write(fdDBUS[5], "1", 1); else write(fdDBUS[5], "0", 1);
	if(data & 0x40) write(fdDBUS[6], "1", 1); else write(fdDBUS[6], "0", 1);
	if(data & 0x80) write(fdDBUS[7], "1", 1); else write(fdDBUS[7], "0", 1);

	// Toggle write pin
	usleep(1);
	write(fdWR, "0", 1);
	usleep(1);
	write(fdWR, "1", 1);
}

I’m afraid you will need to write a Linux kernel driver to get speed you are looking for. You can compile driver as module so you can load it without re-compiling an OS. In your case you need a very simple char driver. This is a nice book to start with. Unfortunately it doesn’t cover latest kernel features. So I’d recommend you to read chapters 1-9 an then you can consult with a live doc.

@alex.tx this was the answer I was expecting. Thank you for the prompt response. I guess I need to look into this further. The problem I am foreseeing is how do I do development of a driver. Currently I am using a pc with virtual box (Ubuntu 16.04) and eclipse to debug projects. If I try to add a LKM to the module, it won’t be apart of the toolchain and won’t eclipse throw compilation errors? I may be getting ahead of myself but trying to get everything that needs to happen mapped out

Hi @mmorgan1361

If I try to add a LKM to the module, it won’t be apart of the toolchain and won’t eclipse throw compilation errors? I may be getting ahead of myself but trying to get everything that needs to happen mapped out

I don’t understand what exactly you mean, you need to cross compile the kernel module for the SoM. To do this, you will also need the cross-compile Toolchain as explained here.

Best regards,
Jaski

Good Morning @jaski.tx

I understand that, what I meant was that the LKM would have to be developed independently of the main SoM software correct? As such, there really is not a way to test/debug the LKM and the software that uses it simultaneously? To be completely honest, I have zero experience writing LKM’s and am just trying to understand the development process

Please define “main SoM software”.

HI @mmorgan1361

I understand that, what I meant was that the LKM would have to be developed independently of the main SoM software correct?

I think, you mean with main SoM software Bsp ( kernel, devicetree and rootfs) without application. Yes, the LKM can be developed independently.

As such, there really is not a way to test/debug the LKM and the software that uses it simultaneously?

You can test/debug one part of your code without need of SoM. For the hardware specific Part you must cross-compile the LKM and deploy this to the target.

To be completely honest, I have zero experience writing LKM’s and am just trying to understand the development process

You have to start from some existing examples and then change them for your use-case. All the best.

Best regards,
Jaski