SoCFPGAのコントロヌラヌのフレヌムバッファヌ実装の䜜成





ご挚拶



前回、 DMAをFPGAに匕き䞊げるこずに決めたした。

今日、FPGAにプリミティブLCDコントロヌラヌを実装し、このコントロヌラヌで動䜜するフレヌムバッファヌドラむバヌを䜜成したす。



FPGA向けの開発ずLinux向けドラむバヌの䜜成が非垞に簡単ですが、興味深いこずをもう䞀床確認したす。



たた、最埌に小さな䞖論調査がありたす-私はコミュニティの意芋を知りたいです。 難しくなければ、投祚しおください。





そのため、 Cyclone V䞊のHPSには統合グラフィックスコントロヌラヌがありたせん。 ディスプレむなしでは生きおいけたせん- 枬定結果はどこで入手できたすか



もちろん、フレヌムバッファの゜フトりェア実装deferred_ioずダブルバッファリングの圢であらゆる皮類の有甚性が远加されおいるを䜿甚するこずでのみ察応できたす。 しかし、これはすべお同じですが、それほど速くはなく、確かに私たちが遞んだものほど興味深いものではありたせん。



そしお、FPGAで非垞にシンプルでありながら完党に機胜するLCDコントロヌラヌの実装を遞択したす。これにより、ディスプレむにデヌタを曞き蟌むずいう圢でCPUから䞍芁な負荷が取り陀かれたす。



ILI9341チップに基づいたLCDを䜿甚したす。



したがっお、今日の蚈画





建築



Linux フレヌムバッファヌずは䜕ですか

簡単に蚀えば、これは単なるメモリ領域であり、ディスプレむに蚘録されるディスプレむに぀ながる蚘録です。



ナヌザヌスペヌスからのアクセスは、デバむスファむル/ dev / fb [N]を介しお行われたす。

通垞、暙準システムコヌルが実装されおいたす-open、close、read、write、lseek、およびmmap。



ドラむバヌでは、ほずんどの関数が1぀のタスクを実行したす。これは、メモリに保存されおいるフレヌムを曎新するこずです。

ハヌドりェアに実装されおいない堎合、メモリからLCDにデヌタをコピヌする機胜もありたす。



すべおの構造ず機胜に぀いおは、これらの蚘事 リンク1回ずリンク2で詳しく説明されおいたす。

情報を耇補しおも意味がないため、アヌキテクチャに圱響を䞎えるもののみを分析したす。



そのため、メモリ内のデヌタを曎新するように蚭蚈されたいく぀かの関数がありたす。 圌らはわずかに異なる眲名を持っおいたす。 これらの関数を䜿甚するず、フレヌム党䜓ず数ピクセルのみを再描画できたす。



フレヌムを曎新した埌、LCDに分類する必芁がありたす。 圓然、フレヌムの倉曎された郚分のみをコピヌするには、より少ないデヌタの転送が必芁です。 たた、CPUを䜿甚しおデヌタをコピヌした堎合、これを考慮する必芁がありたす。

ただし、コピヌはFPGAのDMAコントロヌラヌによっお実行されるため、これに぀いお心配するこずはなく、フレヌム党䜓を再描画したす。



次の質問は、い぀フレヌムを再描画するかです。 簡単な解決策の1぀は、同期的に、぀たりメモリ内のデヌタを曎新する各関数の最埌にレンダリングを実行するこずです。 これは、mmapを䜿甚する堎合を陀き、すべおの堎合に有効です。

マッピングを実行した埌、ナヌザヌ空間プロセスがメモリの内容を倉曎した時期を刀断するのはそれほど簡単ではありたせん。 この問題はdeferred_ioで解決できたす同時に、曎新され再描画が必芁な特定のメモリペヌゞを定矩したす。 しかし、実装はできるだけシンプルで簡単なものにする必芁があるため、別の方法で行いたす。



FPGAのコントロヌラヌは、n FPSの呚波数でフレヌム党䜓をレンダリングしたす。 そしお、ドラむバヌ関数でメモリを曎新するこずに関しお、これを非同期的に行いたす。 したがっお、ドラむバヌで行う必芁があるのは、LCDずFPGAコントロヌラヌの初期化だけです。 そしお、実装する必芁のないフレヌムバッファメモリにデヌタを曞き蟌んでも、このための暙準機胜がすでにありたす。



FPGAのコントロヌラヌも非垞にシンプルです。 圌の仕事





LCDの説明



LCDに぀いお知る必芁があるのは、LCDを初期化する方法ず、曞き蟌みトランザクションがどのように芋えるかだけです。



ドラむバヌに到達したずきに初期化を怜蚎し、トランザクションを調べたす。

FPGAデヌタ転送甚ずドラむバヌディスプレむ蚭定甚の䞡方に実装する必芁がありたす。



ILI9341は耇数のむンタヌフェむスをサポヌトしおいたす。 私は8080ず呌ばれるIntelのプロセッサヌの名前で最初に登堎した16ビットのパラレルむンタヌフェむスを䜿甚したす。 信号は次のずおりです最初はより䞀般的な名前が瀺され、括匧内はILI9341のデヌタシヌトからの名前です。



曞き蟌みトランザクションは非垞に簡単です。

曞き蟌みトランザクション






読み取りトランザクションはそれほど耇雑ではありたせんが、必芁ないため、考慮したせん。



Linuxドラむバヌ



ドラむバヌには䜕がありたすか



たず、FPGAレゞスタの読み取り/曞き蟌み甚の関数。 私の同僚であるishevchukの 蚘事で、ステヌタス制埡レゞスタずは䜕か、そしおそれらを䜿甚する方法に぀いお詳しく読むこずができたす。

CSRの読み取り/曞き蟌み機胜
static void fpga_write_reg(int reg, u16 val) { iowrite16(val, fpga_regs + 2*reg); } static u16 fpga_read_reg(int reg) { u16 tmp; tmp = ioread16(fpga_regs + 2*reg); return tmp; } static void fpga_set_bit(int reg, int bit) { unsigned long tmp = fpga_read_reg(reg); set_bit(bit, &tmp); fpga_write_reg(reg, tmp); } static void fpga_clear_bit(int reg, int bit) { unsigned long tmp = fpga_read_reg(reg); clear_bit(bit, &tmp); fpga_write_reg(reg, tmp); }
      
      





第二に、コマンドずデヌタをLCDに盎接蚘録する機胜。 ディスプレむを初期化するために䜿甚されたす。

関数は絶察に「䞍噚甚」です-デヌタシヌトに瀺されおいるようにトランザクションを䜜成しおくださいこの蚘事ではそれ以䞊です。

LCDデヌタ/コマンド曞き蟌み機胜
 static void lcd_write_command(u16 val) { /* Write command code */ fpga_write_reg(LCD_DATA_CR, val); /* WR and RS low, RD high */ fpga_write_reg(LCD_CTRL_CR, LCD_CTRL_CR_RD); ndelay(1); /* RS low, WR and RD high */ fpga_write_reg(LCD_CTRL_CR, LCD_CTRL_CR_RD | LCD_CTRL_CR_WR); ndelay(1); /* All control signals high */ fpga_write_reg(LCD_CTRL_CR, LCD_CTRL_CR_RD | LCD_CTRL_CR_WR | LCD_CTRL_CR_RS); } static void lcd_write_data(u16 data) { /* Write data */ fpga_write_reg(LCD_DATA_CR, data); /* WR low, RD and RS high */ fpga_write_reg(LCD_CTRL_CR, LCD_CTRL_CR_RD | LCD_CTRL_CR_RS); ndelay(1); /* All control signals high */ fpga_write_reg(LCD_CTRL_CR, LCD_CTRL_CR_RD | LCD_CTRL_CR_RS | LCD_CTRL_CR_WR); }
      
      





実は、単玔なLCD初期化です。

LCD初期化機胜
 static void lcd_init(struct fb_info *info) { // Clear data fpga_write_reg(LCD_DATA_CR, 0); // All control signals high fpga_write_reg(LCD_CTRL_CR, LCD_CTRL_CR_RD | LCD_CTRL_CR_RS | LCD_CTRL_CR_WR); mdelay(100); lcd_write_command(ILI9341_DISPLAY_ON); lcd_write_command(ILI9341_SLEEP_OUT); lcd_write_command(ILI9341_INVERTION_OFF); lcd_write_command(ILI9341_MEM_ACCESS_CTRL); lcd_write_data(MY | MX | MV | BGR); lcd_write_command(ILI9341_PIXEL_FORMAT); lcd_write_data(0x0055); lcd_write_command(ILI9341_COLUMN_ADDR); lcd_write_data(0x0000); lcd_write_data(0x0000); lcd_write_data((DISPLAY_WIDTH-1) >> 8); lcd_write_data((DISPLAY_WIDTH-1) & 0xFF); lcd_write_command(ILI9341_PAGE_ADDR); lcd_write_data(0x0000); lcd_write_data(0x0000); lcd_write_data((DISPLAY_HEIGHT-1) >> 8); lcd_write_data((DISPLAY_HEIGHT-1) & 0xFF); lcd_write_command(ILI9341_MEM_WRITE); }
      
      





䜿甚されるコマンドに぀いお簡単に説明したす。



ILI9341_DISPLAY_ON0x29およびILI9341_SLEEP_OUT0x11、これは予想倖ですが、ディスプレむをオンにしお起動したす。



ILI9341_MEM_ACCESS_CTRL0x36-これはメモリスキャンの方向の蚭定です。



ILI9341_PIXEL_FORMAT0x3a-画像圢匏。ピクセルあたり16ビットです。



ILI9341_COLUMN_ADDR0x2aおよびILI9341_PAGE_ADDR0x2bは、ディスプレむの䜜業領域を蚭定したす。



ILI9341_MEM_WRITE0x2c-このコマンドは、デヌタトランザクションが埌に続くこずを瀺したす。 この堎合、珟圚の䜍眮は、ILI9341_COLUMN_ADDRずILI9341_PAGE_ADDRを䜿甚しおそれぞれ蚭定された初期の列ず行に蚭定されたす。 各トランザクションの埌、列は自動的に1ず぀増加したす。列が最埌の列ず等しくなるず、次の行ぞの遷移が発生したす。 列ず行の䞡方が最埌に等しくなるず、䜍眮は最初の䜍眮に戻りたす。



したがっお、ILI9341_MEM_WRITEコマンドの埌、FPGAのコントロヌラヌは、他のこずを気にせずに、メモリからLCDにデヌタを単に「埪環」させるこずができたす。



ドラむバヌで最埌に興味があるのは、プロヌブ機胜です。

ドラむバヌプロヌブ機胜
  struct fb_info *info; int ret; u32 vmem_size; unsigned char *vmem; dma_addr_t dma_addr; pdev->dev.dma_mask = &platform_dma_mask; pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); vmem_size = (etn_fb_var.width * etn_fb_var.height * etn_fb_var.bits_per_pixel) / 8; vmem = dmam_alloc_coherent(&pdev->dev, vmem_size, &dma_addr, GFP_KERNEL); if (!vmem) { dev_err(&pdev->dev, "FB: dma_alloc_coherent error\n"); return -ENOMEM; } memset(vmem, 0, vmem_size); info = framebuffer_alloc(0, &pdev->dev); if (!info) return -ENOMEM; info->screen_base = vmem; info->fbops = &etn_fb_ops; info->fix = etn_fb_fix; info->fix.smem_start = dma_addr; info->fix.smem_len = vmem_size; info->var = etn_fb_var; info->flags = FBINFO_DEFAULT; info->pseudo_palette = &etn_fb_pseudo_palette; /* Get FPGA registers address */ fpga_regs = devm_ioremap(&pdev->dev, FPGA_REGS_BASE, REGSIZE); /* Disable refreshing */ fpga_write_reg(LCD_DMA_CR, 0); lcd_init(info); set_dma_addr(dma_addr); set_fps(fps); /* Enable refreshing */ fpga_set_bit(LCD_DMA_CR, LCD_DMA_CR_REDRAW_EN); ret = register_framebuffer(info); if (ret < 0) { framebuffer_release(info); return ret; } platform_set_drvdata(pdev, info); return 0;
      
      





それで䜕が起こっおいたすか

たず、 dmam_alloc_coherent関数を䜿甚しお、DMA互換ゟヌンにメモリを割り圓おたす。 この堎合、遞択した領域を「指す」2぀のアドレスを取埗したす。 1぀はドラむバヌで䜿甚され、2぀目はFPGAに曞き蟌み、DMAコントロヌラヌがこの領域からデヌタを読み取れるようにしたす。



DMAマッピングに぀いお簡単に説明したす。 これらには2぀のタむプがありたす。



䞀貫したマッピングは、プロセッサずデバむスの䞡方で同時に利甚できたす。 アクセスするず、各圓事者は「新鮮な」デヌタを受け取るこずが保蚌されたす。 バッファヌがドラむバヌの存続期間を通じお存圚する堎合に最もよく䜿甚されたす。 䜿甚䟋は、フレヌムバッファメモリです。



ストリヌミングマッピングを䜿甚する堎合、厳密に順番にアクセスできたす。 ほずんどの堎合、それらは1぀の操䜜䞭に䜜成されたす。

理論的には、より生産的かもしれたせん。 䟋は、ネットワヌクパケットの受信/送信です。



プロヌブ機胜に戻りたす。 次に、 fb_infoに入力したす。

次に、ステヌタス制埡レゞスタを読み曞きできるように、FPGAアドレス空間をマップしたす。



その埌、必芁なFPS倀ずDMAアドレスをFPGAに曞き蟌みたす必芁に応じお、ワヌド番号に倉換するこずを忘れないでください。



次に、FPGAでのレンダリングを有効にしお、フレヌムバッファヌを登録したす。 すべお準備完了です





FPGAのモゞュヌル



FPGAのモゞュヌルに到達したした。 ここでも、すべおが簡単です。

実装する必芁があるこずを思い出させおください



圓然、制埡レゞスタはCPUからLCDぞの盎接アクセスを提䟛するために䜿甚されたす。

そしお、通垞のマルチプレクサ-制埡がCPUから来る堎合、レゞスタからの信号はLCDぞのむンタヌフェヌスに切り替えられ、そうでない堎合は-モゞュヌルからFPGAぞの信号。 遞択は、ステヌトマシンの状態によっお異なりたす。これに぀いおは、以䞋で説明したす。

コヌドはプリミティブです

LCDバスMUX
 always_ff @( posedge clk_i ) if( state == IDLE_S ) begin lcd_bus_if.data <= lcd_ctrl_if.data; lcd_bus_if.rd <= lcd_ctrl_if.rd; lcd_bus_if.wr <= lcd_ctrl_if.wr; lcd_bus_if.rs <= lcd_ctrl_if.rs; end else // Send data transactions from FPGA. begin lcd_bus_if.data <= lcd_data_from_fpga; lcd_bus_if.rd <= 1'b1; lcd_bus_if.wr <= lcd_wr_from_fpga; lcd_bus_if.rs <= 1'b1; end
      
      





次のタスクは、メモリからデヌタを読み取り、LCDに曞き蟌むこずです。 ここで少し考える必芁がありたす。

読み取りむンタヌフェむスのスルヌプットは、LCDにデヌタを曞き蟌む速床よりもはるかに倧きいため、連続しおデヌタを読み取るこずはできたせんドキュメントに瀺されおいるタむムスタンプを確認する必芁があるこずに泚意しおください。



぀たり、人為的に読み取り速床を制限する必芁がありたす。 これには次のオプションがありたす。



最初のオプションは、LCD䞊のデヌタに倧きなFPGA芏栌による䞀時停止が発生するずいう事実に぀ながりたす。

適甚された問題50を超えるFPSを取埗する必芁はほずんどありたせんを考慮するず、これで十分である可胜性が十分にありたす。

しかし、それは非垞に䞍噚甚でugいです。 したがっお、このオプションは砎棄したす。



2番目のオプションは、LCDに連続ストリヌムを取埗できるように、メモリからデヌタを読み取るのに必芁な速床を蚈算するこずです。 たた、特に出力ストリヌムの速床の䞀定性に関する厳密な芁件がないこずを考慮するず、非垞に有効なオプションです。 ただし、䞀般的なケヌスでは、読み取りトランザクションの遅延の倉数倀により、バッファを䜿甚しお速床を調敎する必芁がありたす。



3番目のオプションは非垞にシンプルで、かなり信頌性がありたす。 その本質は、メモリから読み取ったデヌタを高速で曞き蟌むFIFOを䜿甚するこずです。 バッファヌのスペヌスがなくなるず、読み取りを䞀時停止したす。 同時に、バッファからデヌタを連続しお読み取り、䞀定の速床でLCDにトランザクションを圢成できたす。 FIFOに堎所が衚瀺されるずすぐに、再びメモリからの読み取りを再開したす。



3番目のオプションを遞択したす。 最初にFIFOが必芁です。

FIFOむンスタンス
  buf_fifo #( .AWIDTH ( FIFO_AWIDTH ), .DWIDTH ( AMM_DATA_W ) ) buf_fifo ( .clock ( clk_i ), .aclr ( ), .wrreq ( fifo_wr_req ), .data ( fifo_wr_data ), .rdreq ( fifo_rd_req ), .q ( fifo_rd_data ), .almost_full ( ), .full ( ), .empty ( fifo_empty ), .usedw ( fifo_usedw ) );
      
      





読み取りを䞀時停止するタむミングを刀断するには、すでにいっぱいになっおいるFIFOの量を知るだけでは䞍十分です。 結局、読み取りトランザクションもあり、それらは珟圚凊理䞭です。 ぀たり、読み取りが既に芁求されおいるが、ただ配信されおいないデヌタです。

そのようなトランザクションの数を珟時点で知る必芁がありたす。 これを行うには、読み取り芁求が実行されるたびに、察応するカりンタヌを増やし、読み取りデヌタの確認を受け取ったら、それを枛らしたす。

保留䞭のトランザクションの蚈算
 // Count of read transactions in progress logic [FIFO_AWIDTH-1:0] pending_read_cnt; always_ff @( posedge clk_i ) case( { read_req_w, amm_if.read_data_val } ) 2'b01: pending_read_cnt <= pending_read_cnt - 1'd1; 2'b10: pending_read_cnt <= pending_read_cnt + 1'd1; endcase
      
      





その結果、「凊理䞭」にFIFOに蚘録された単語ずトランザクションの合蚈がラむンナップの深さにほが等しくなったずきに読み取りを停止したす。 「ほが」50個の自由な単語を遞択したす。

読むのをやめる
 logic stop_reading; assign stop_reading = ( pending_read_cnt + fifo_usedw ) > ( 2**FIFO_AWIDTH - 'd50 );
      
      





Avalon MMでの読み取りトランザクション自䜓の圢成は原始的です。 䞻なこずは、むンタヌフェむスのタむプに応じおアドレスを正しくむンクリメントするこずです fpga2sdramたたはfpga2hps むンタヌフェむスおよび違いの詳现に぀いおは、 こちらを参照しおください 

読み取りトランザクション
 // fpga2sdram used word address, so we must added 1 every time, // fpga2hps used byte address, so we must added 8 (for 64-bit iface). logic [31:0] addr_incr; assign addr_incr = ( USE_WORD_ADDRESS == 1 ) ? 1 : ( AMM_DATA_W >> 3 ); always_ff @( posedge clk_i ) if( state == IDLE_S ) amm_if.address <= lcd_ctrl_if.dma_addr; else if( read_req_w ) amm_if.address <= amm_if.address + addr_incr; // Always read all bytes in word assign amm_if.byte_enable = '1; // We don't use burst now assign amm_if.burst_count = 1; assign amm_if.read = ( state == READ_S ); // Remove Quartus warnings assign amm_if.write_data = '0; assign amm_if.write = 0;
      
      





デヌタを読むこずを孊んだので、今床はLCDにデヌタを曞き蟌む方法を孊ぶ必芁がありたす。 これを行うには、2぀の状態の単玔なステヌトマシンを䜜成したす。FIFOにデヌタがある堎合、マシンはトランザクション送信状態になりたす。 そしお、蚘録が終了するず、IDLEに戻りたす。

LCDに曞き蟌むためのFSM
 enum int unsigned { LCD_IDLE_S, LCD_WRITE_S } lcd_state, lcd_next_state; always_ff @( posedge clk_i ) lcd_state <= lcd_next_state; always_comb begin lcd_next_state = lcd_state; case( lcd_state ) LCD_IDLE_S: begin if( !fifo_empty ) lcd_next_state = LCD_WRITE_S; end LCD_WRITE_S: begin if( lcd_word_cnt == 5'd31 ) lcd_next_state = LCD_IDLE_S; end endcase end assign fifo_rd_req = ( lcd_state == LCD_IDLE_S ) && ( lcd_next_state == LCD_WRITE_S );
      
      





LCDが16ビットのデヌタを転送する前に1぀のトランザクションを芚えおおく必芁があり、FIFOの各ワヌドのサむズは64ビットですfpga2sdram / fpga2hpsむンタヌフェむスの構成によっお異なりたす。 したがっお、読む単語ごずに4぀のトランザクションを圢成したす。

それらを簡単に䜜成できたす。このため、1぀のカりンタヌを䜜成し、その䞭の必芁なビットを䜿甚するだけで十分です。

読み取りトランザクション
 // ILI9341 Data transaction from FPGA: // __ __ __ __ __ __ __ __ __ // clk/4 | __| |__| |__| |__| |__| |__| |__| |__| |__| | // // data | ///< split[0] | split[1] | split[2] | split[3] >//// // // _______________________________________________ // rd | xxxx xxxx // // _____ _____ _____ _____ // wr | xxxx_____| |_____| |_____| |_____| xxxx // // _______________________________________________ // rs | xxxx xxxx logic [3:0][15:0] fifo_rd_data_split; assign fifo_rd_data_split = fifo_rd_data; logic [15:0] lcd_data_from_fpga; logic lcd_wr_from_fpga; logic [4:0] lcd_word_cnt; always_ff @( posedge clk_i ) if( lcd_state == LCD_IDLE_S ) lcd_word_cnt <= '0; else lcd_word_cnt <= lcd_word_cnt + 1'd1; assign lcd_data_from_fpga = fifo_rd_data_split[ lcd_word_cnt[4:3] ]; assign lcd_wr_from_fpga = ( lcd_state == LCD_IDLE_S ) ? 1'b1 : lcd_word_cnt[2];
      
      





ほずんどすべお。 䞊蚘のすべおを管理するメむンステヌトマシンを䜜成したす。

その動䜜のロゞックは単玔です-LCDコントロヌラモゞュヌルがオンになっおいる堎合、1぀のフレヌムを描画する必芁がありたす。

特定のFPSを実装するために、目的のティック数が予想される「䞀時停止状態」がありたす。

その埌、メモリからのデヌタの読み取りが開始されたすデヌタがFIFOに衚瀺されるずすぐにLCDぞの曞き蟌みが自動的に開始されたす。

フレヌム党䜓が読み取られるず、残っおいるのはLCDぞのトランザクションの完了を埅぀こずだけです。

メむンFSM
 logic [31:0] word_cnt; always_ff @( posedge clk_i ) if( state == IDLE_S ) word_cnt <= '0; else if( read_req_w ) word_cnt <= word_cnt + 1'd1; logic reading_is_finished; assign reading_is_finished = ( word_cnt == WORD_IN_FRAME - 1 ) && read_req_w; logic stop_reading; assign stop_reading = ( pending_read_cnt + fifo_usedw ) > ( 2**FIFO_AWIDTH - 'd50 ); logic all_is_finished; assign all_is_finished = ( pending_read_cnt == 0 ) && ( fifo_usedw == 0 ) && ( lcd_state == LCD_IDLE_S ); enum int unsigned { IDLE_S, FPS_DELAY_S, READ_S, WAIT_READIND_S, WAIT_WRITING_S } state, next_state; always_ff @( posedge clk_i ) state <= next_state; // FIXME: // If lcd_ctrl_if.redraw_en == 1 // CPU have one takt for read 0 in lcd_ctrl_if.dma_busy // Fix: add WAIT_WRITING_S -> FPS_DELAY_S path always_comb begin next_state = state; case( state ) IDLE_S: begin if( lcd_ctrl_if.redraw_stb || lcd_ctrl_if.redraw_en ) next_state = FPS_DELAY_S; end FPS_DELAY_S: begin if( fps_delay_done_w ) next_state = READ_S; end READ_S: begin if( reading_is_finished ) next_state = WAIT_WRITING_S; else if( stop_reading ) next_state = WAIT_READIND_S; end WAIT_READIND_S: begin if( !stop_reading ) next_state = READ_S; end WAIT_WRITING_S: begin if( all_is_finished ) next_state = IDLE_S; end endcase end
      
      





これで、LCDコントロヌラヌの準備が敎いたした。



U-bootセットアップ



前の蚘事で 、 fpga2sdramむンタヌフェヌスをオンにするこずはU-bootで行う必芁があるず曞きたした。 そうしないず、読み取りトランザクション䞭に、システムが完党にフリヌズしたす。 これを行うには、環境に次の行を远加したす。

u-boot-env.txt
 ... fpgadata=0x10000000 fpgafile=/lib/firmware/fpga/fpga.rbf fpgaboot=setenv fpga2sdram_handoff 0x3fff; ext2load mmc 0:2 ${fpgadata} ${fpgafile}; fpga load 0 ${fpgadata} ${filesize} bridge_enable_handoff=mw $fpgaintf ${fpgaintf_handoff}; go $fpga2sdram_apply; mw $fpga2sdram ${fpga2sdram_handoff}; mw $axibridge ${axibridge_handoff}; mw $l3remap ${l3remap_handoff} bootcmd=run fpgaboot; run bridge_enable_handoff; run mmcboot ...
      
      





デバッグ



原則ずしお、すべおが問題なく動䜜するはずなので、デバッグするものは䜕もありたせん。

しかし、私たちは少し面倒で、FPGAモゞュヌルのテストベンチを䜜成しなかったので、安心のためにSignalTapでモゞュヌルの動䜜を芋る䟡倀がありたす。



これは、CPUからのトランザクションの倖芳です。





コマンド0x29、0x11、0x36およびデヌタ0xE8の蚘録が衚瀺されたす。 そうです。



したがっお、FPGAからのトランザクションは次のようになりたす。





そしお、ここでも、すべおが蚈画どおりです。



やった FPGAにLCDコントロヌラヌがありたす。

最埌たで読んでくれた人に感謝したす 頑匵っお



䟿利なリンク



githubの゜ヌス

すべおの䜜業が実行されたデバむス

フレヌムバッファヌドラむバヌを蚘述するためのドキュメント

ILI9341ドキュメント



前の蚘事に関するメモ



前回の蚘事では、 fpga2sdramむンタヌフェヌスの垯域幅を枬定したした。

残念ながら、私は間違いを犯したした。 ぀たり、PLLシュレッドは実際の25 MHzではなく125 MHzに蚭定されたした。

このため、PLLの乗数ず陀数の比率は正しく蚈算されたせんでした。

その結果、DDR3は芏定の333 MHzではなく66 MHzで動䜜したした。



正しい係数ず256ビットのむンタヌフェむス幅を䜿甚するず、スルヌプットは玄16〜17 Gbit / sになりたす。これは、幅が32ビットで呚波数が333 MHzのDDR3むンタヌフェむスの理論䞊のスルヌプットに盞圓したす。



おaびしたす



小芏暡な調査



コミュニティの意芋を知りたいです。 難しくなければ、投祚しおください。



All Articles