ARM/QEMU PL110

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
foreverska
Posts: 4
Joined: Sat Apr 13, 2019 10:55 pm

ARM/QEMU PL110

Post by foreverska »

I'm attempting to demo some low level graphics stuff for ARM. So I'm targeting what is supposed to be easy graphics, PL110. But so far all it does is sit black. I've attempted to follow the osdev wiki but it doesn't seem to work either. Chief problem is I'm pretty sure qemu changed it's memory map since that was written. I played around with the code a little but didn't see much. So here's mine:

Code: Select all

#include "stdint.h"

#include "uart.h"
#include "utility.h"

volatile unsigned char * const CLCD = (unsigned char *) 0x10120000;

#define CLCDPERIPHID0 0xFE0
#define CLCDPERIPHID1 0xFE4
#define CLCDPERIPHID2 0xFE8
#define CLCDPERIPHID3 0xFEC

void PrintClcdPerifId()
{	 
	char buffer[5];
	
	DEBUG_PRINT("ClcdPerifId: ");
	DEBUG_PRINT(CharToHex(*(CLCD + CLCDPERIPHID0), buffer));
	DEBUG_PRINT(CharToHex(*(CLCD + CLCDPERIPHID1), buffer));
	DEBUG_PRINT(CharToHex(*(CLCD + CLCDPERIPHID2), buffer));
	DEBUG_PRINT(CharToHex(*(CLCD + CLCDPERIPHID3), buffer));
	DEBUG_PRINT("\n");
}

#define CLCDPCELLID0 0xFF0
#define CLCDPCELLID1 0xFF4
#define CLCDPCELLID2 0xFF8
#define CLCDPCELLID3 0xFFC

void PrintClcdCellId()
{
	char buffer[5];
	
	DEBUG_PRINT("ClcdCellId: ");
	DEBUG_PRINT(CharToHex(*(CLCD + CLCDPCELLID0), buffer));
	DEBUG_PRINT(CharToHex(*(CLCD + CLCDPCELLID1), buffer));
	DEBUG_PRINT(CharToHex(*(CLCD + CLCDPCELLID2), buffer));
	DEBUG_PRINT(CharToHex(*(CLCD + CLCDPCELLID3), buffer));
	DEBUG_PRINT("\n");
}

#define LCDTIMING0 	0x0
#define LCDTIMING1 	0x4
#define LCDTIMING2 	0x8
#define LCDTIMING3 	0xC

#define VGATIM0		0x3F1F3F9C
#define VGATIM1		0x090B616F
#define VGATIM2		0x067F1800

#define QVGATIM0	0x0505054C
#define QVGATIM1	0x050514EF
#define QVGATIM2	0x05EF1800

void SetClcdTiming()
{
	uint32_t volatile *pRegister;
	
	DEBUG_PRINT("Setting CLCD timing registers\n");
	
	pRegister = (uint32_t*) CLCD + LCDTIMING0;
	*pRegister = VGATIM0;
	
	pRegister = (uint32_t*) CLCD + LCDTIMING1;
	*pRegister = VGATIM1;
	
	pRegister = (uint32_t*) CLCD + LCDTIMING2;
	*pRegister = VGATIM2;
}

#define LCDCONTROL 	0x1C

#define TFT24BITEN	0x182B

void SetClcdControl()
{
	uint32_t volatile *pRegister;
	
	DEBUG_PRINT("Set CLCD Control Registers\n");
	
	pRegister = (uint32_t *) CLCD + LCDCONTROL;
	
	*pRegister = TFT24BITEN;
}

#define LCDUPBASE 0x10

void SetClcdBuffer(uint32_t frameBufferLoc)
{
	uint32_t volatile *pRegister;
	
	DEBUG_PRINT("Set CLCD Frame Buffer\n");
	
	pRegister = (uint32_t *) CLCD + LCDUPBASE;
	
	*pRegister = frameBufferLoc;
}

#define DEFAULT_BUFFER_LOC 0x200000

void InitClcd()
{
	PrintClcdPerifId();
	PrintClcdCellId();
	
	SetClcdTiming();
	SetClcdBuffer(DEFAULT_BUFFER_LOC);
	SetClcdControl();
	
	uint16_t volatile *fb;
	fb = (uint16_t *) DEFAULT_BUFFER_LOC;
	int x;
	for (x = 0; x < (640 * 480) - 10; ++x)
		fb[x] = 0x1f << (5 + 6) | 0xf << 5;
		
	DEBUG_PRINT("InitCLCD Done\n");
}
DEBUG_PRINT is a UART print which is fed to stdio. I run qemu using

Code: Select all

qemu-system-arm -M versatilepb -m 256M -serial stdio -kernel QG.elf
and the output falls all the way to done so I know it should be doing something but the graphical window stays black.

Code: Select all

Begin System Manager
ClcdPerifId: 10 11 04 00 
ClcdCellId: 0D F0 05 B1 
Setting CLCD timing registers
Set CLCD Frame Buffer
Set CLCD Control Registers
InitCLCD Done
Thanks for any help.
linuxyne
Member
Member
Posts: 211
Joined: Sat Jul 02, 2016 7:02 am

Re: ARM/QEMU PL110

Post by linuxyne »

There might be more differences than I list here, but if versatilepb is the board chosen, then it "has a variant halfway between PL110 and PL111" (according to Linux).

It means that the offsets of the control register and the interrupt-mask register are to be swapped.

Specifically, LCDCONTROL in your case is at 0x18 (and not at 0x1c as your code defines; 0x1c in your code ought to be interrupt-enable mask).
foreverska
Posts: 4
Joined: Sat Apr 13, 2019 10:55 pm

Re: ARM/QEMU PL110

Post by foreverska »

Nearly as soon as I posted this I found someone using 0x18 as CONTROL. Tried it and it worked. :roll:

Thanks for the rhyme to the reason because I was very weirded out by that change.
Post Reply