PL111LCDコントローラーをプログラムするためのベアメタルコードを書き込もうとしています。RealviewARMCortex-A8用にセットアップされたQEMUエミュレーターを使用しています。以前、QEMUの「-serialstdio」オプションを使用して、Linuxターミナルウィンドウに文字を印刷することができました。
PL111ドキュメントを確認しましたが、1つわかりません。PL111コントローラーのLCDUPBASEをセットアップして、フレームバッファーのアドレスをメモリに格納します。しかし、単純にASCII値をフレームバッファーに書き込むと、LCDコントローラーがフレームバッファーを選択して対応する文字を画面に表示しますか、それともASCII値に対して何らかの変換を実行する必要がありますか(既存の標準に従って)フレームバッファに書き込む前に)を認識していませんか?
前者が当てはまる場合、この変換は、コントローラーハードウェアの変換テーブルに従ってコントローラー自体によって処理されますか?背景色などはどうですか?PL111文書はこれについて何も述べていません。このハードルにより、GPUの役割についても考えるようになりました。もし、GPUも持っていたとしたら、それはこのスキームのどこに当てはまり、その役割は正確には何でしょうか。
これらの概念をよりよく理解するのに役立つ優れたリソース、ドキュメント、または本はありますか。私の質問がばかげているように聞こえたら、私を許してください。私は組み込み/周辺機器プログラミングの経験があまりありません。基本的にARMv7アーキテクチャを学び、理解しようとしています。アセンブリプログラミングプリントをQEMUコンソールではなく、QEMUコンソールで印刷できれば素晴らしいと思いました。 Linuxコンソール。(「-serialstdio」オプションを使用)
ここの人たちが私を助けてくれたら本当にありがたいです。ありがとう
/* boot.s */
.section .data
.section .bss
.section .text
.globl _start
_始める:
/ * **割り込みベクタテーブル開始** /
b _RESET_HANDLER /* Reset Handler */
b _UNDEF_HANDLER /* Undef Instruction Handler */
b _SWI_HANDLER /* Software Interrupt Handler */
b _PREFETCHABORT_HANDLER /* Prefect Abort Handler */
b _DATAABORT_HANDLER /* Data Abort Handler */
b _IRQ_HANDLER /* IRQ Handler */
b _FIQ_HANDLER /* FIQ Handler */
/ ***割り込み ベクタテーブルの終了****** /
_FIQ_HANDLER:
b . /* Not implemented yet, so go in infinite loop */
_IRQ_HANDLER:
b . /* _isr_irq /* jump to interrupt service routine */
_DATAABORT_HANDLER:
b . /* Not implemented yet, so go in infinite loop */
_PREFETCHABORT_HANDLER:
b . /* Not implemented yet, so go in infinite loop */
_SWI_HANDLER:
b . /* Not implemented yet, so go in infinite loop */
_UNDEF_HANDLER:
b . /* Not implemented yet, so go in infinite loop */
_RESET_HANDLER:
b _initialize_cpu
cpuinitialize.s =>
.section .data
.section .bss
.section .text
.globl _initialize_cpu
_initialize_cpu:
/*LCD初期化コード*/
.include "ColourLCDPL111.s"
.set SYS_OSC4, 0x1000001C /* Mapped register for OSCCLK4*/
.set SYS_LOCK, 0x10000020 /* reference clock CLCDCLK for PL111*/
movw r0, #:lower16:SYS_LOCK /* Unlocking the register*/
movt r0, #:upper16:SYS_LOCK
movw r1, #0xA05F
str r1, [r0]
movw r2, #:lower16:SYS_OSC4 /* Setting the CLCDCLK frequency 36MHz*/
movt r2, #:upper16:SYS_OSC4
movw r1, #0x2CAC
str r1, [r2]
str r1, [r0] /* Locking the register again*/
movw r0, #:lower16:LCDTiming0_ADDR
movt r0, #:upper16:LCDTiming0_ADDR
movw r1, #:lower16:0x1313A4C4 /* PPL = 49 ; HSW = 3 TODO:change*/
movt r1, #:upper16:0x1313A4C4 /* HBP = 5 ; HFP = 5 */
str r1, [r0]
movw r0, #:lower16:LCDTiming1_ADDR
movt r0, #:upper16:LCDTiming1_ADDR
movw r1, #:lower16:0x0505F657 /* LPP = 600 ; VSW = 2 TODO:change*/
movt r1, #:upper16:0x0505F657 /* VBP = 2 ; VFP = 2 */
str r1, [r0]
movw r0, #:lower16:LCDTiming2_ADDR
movt r0, #:upper16:LCDTiming2_ADDR
movw r1, #:lower16:0x071F1800 /* CPL[25:16] = 799 ; BCD[26] = 1 (PCD Bypassed) */
movt r1, #:upper16:0x071F1800 /* PCD = ignored */
str r1, [r0]
movw r0, #:lower16:LCDUPBASE_ADDR /* Setting up frame buffer address to 0x00000000*/
movt r0, #:upper16:LCDUPBASE_ADDR
mov r1, #0x0
str r1, [r0]
movw r0, #:lower16:LCDControl_ADDR
movt r0, #:upper16:LCDControl_ADDR
movw r1, #0x082B /* Setting up TFT 24Bit Mode */
str r1, [r0]
movw r0, #:lower16:LCDIMSC_ADDR /* LCD interrupts: Disabled for now */
movt r0, #:upper16:LCDIMSC_ADDR
mov r1, #0x00000000
str r1, [r0]
mov r0, #40 /* lets try to print 'A' at frame buffer + 40 */
mov r1, #65
str r1, [r0]
画面全体を実際に白くしたフレームバッファを埋めるためのコードスニペット。単純にi=800を使用し、j = 600x4が機能しなかった場合、ランダムに大きな値10000を取得しました
void PopulateFrameBuffer(void)
{
unsigned int i,j;
unsigned char *ptr = (unsigned char *)0x0;
for(i=0; i<800;i++)
{
for (j=0;j<(600*10000);j++)
{
*ptr++=0xFF;
}
}
}
初期化コードの後、アセンブリからこの関数を呼び出しました。フレームバッファの開始アドレスは0x00000000です