Nano和原子的HDMI_OUT例程,纯寄存器初始化 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki
- 用Nano的硬件设计+程序,是可以跑的。不过Nano的例程多了个AXI4_Stream_Converter模块,这个看起来不爽
- 用原子的硬件设计+程序,是可以跑的。原子的例程没有AXI4_Stream_Converter模块
- 我的目的是,用原子的硬件设计+Nano的程序,是否可以跑? 结论是不行,需要修改代码。
- 例程路径:A_hdmi_out_wi_wo_sd.rar
- 可以正常运行
//****************************************Copyright (c)***********************************//
//原子哥在线教学平台:www.yuanzige.com
//技术支持:www.openedv.com
//淘宝店铺:http://openedv.taobao.com
//关注微信公众平台微信号:"正点原子",免费获取ZYNQ & FPGA & STM32 & LINUX资料。
//版权所有,盗版必究。
//Copyright(C) 正点原子 2018-2028
//All rights reserved
//----------------------------------------------------------------------------------------
// File name: main.c
// Last modified Date: 2019/10/21 17:58:36
// Last Version: V1.1
// Descriptions: 从SD卡中读取BMP格式的图片,并在HDMI显示器上显示
//----------------------------------------------------------------------------------------
// Created by: 正点原子
// Created date: 2019/10/21 17:58:36
// Version: V1.0
// Descriptions: The original version
//
//----------------------------------------------------------------------------------------
//****************************************************************************************//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"
#include "xaxivdma.h"
#include "xaxivdma_i.h"
#include "display_ctrl_hdmi/display_ctrl.h"
#include "vdma_api/vdma_api.h"
#include "ff.h"
#include "sleep.h"
void init()
{
//配置VDMA
Xil_Out32(0x43000000,0x4);
Xil_Out32(0x43000000,0x10002);
Xil_Out32(0x43000054,0x1680);
Xil_Out32(0x43000058,0x1680);
Xil_Out32(0x4300005c,0x1100000);
Xil_Out32(0x43000000,0x14002);
Xil_Out32(0x43000000,0x14003);
Xil_Out32(0x43000050,0x438);
usleep(1000);
//初始化Display controller
Xil_Out32(0x43c10008,0x800083);
Xil_Out32(0x43c1000c,0x800411);
Xil_Out32(0x43c10010,0x0);
Xil_Out32(0x43c10014,0x82);
Xil_Out32(0x43c10018,0xd2cfa401);
Xil_Out32(0x43c1001c,0x006300ff);
Xil_Out32(0x43c10000,0x1);
usleep(1000);
Xil_Out32(0x43c10008,0x400041);
Xil_Out32(0x43c1000c,0x0000069a);
Xil_Out32(0x43c10010,0x0);
Xil_Out32(0x43c10014,0x000020c4);
Xil_Out32(0x43c10018,0xcfafa401);
Xil_Out32(0x43c1001c,0x00a300ff);
Xil_Out32(0x43c10000,0x0);
Xil_Out32(0x43c10000,0x1);
usleep(1000);
//设置VideoMode
Xil_Out32(0x43c00000,0x2);
Xil_Out32(0x43c0006c,0x0000007f);
Xil_Out32(0x43c00070,0x898);
Xil_Out32(0x43c00074,0x4650465);
Xil_Out32(0x43c00060,0x4380780);
Xil_Out32(0x43c00094,0x4380000);
Xil_Out32(0x43c00078,0x080407d8);
Xil_Out32(0x43c00080,0x0440043b);
Xil_Out32(0x43c0008c,0x0440043b);
Xil_Out32(0x43c00068,0x2);
Xil_Out32(0x43c0007c,0x7800780);
Xil_Out32(0x43c00084,0x07d807d8);
Xil_Out32(0x43c00088,0x7800780);
Xil_Out32(0x43c00090,0x07d807d8);
Xil_Out32(0x43c0007c,0x7800780);
Xil_Out32(0x43c00084,0x07d807d8);
Xil_Out32(0x43c00088,0x7800780);
Xil_Out32(0x43c00090,0x07d807d8);
Xil_Out32(0x43c00000,0x03f7ef02);
Xil_Out32(0x43c00000,0x03f7ef06);
usleep(1000);
}
//宏定义
#define BYTES_PIXEL 3 //像素字节数,RGB888占3个字节
#define DYNCLK_BASEADDR XPAR_AXI_DYNCLK_0_BASEADDR //动态时钟基地址
#define VDMA_ID XPAR_AXIVDMA_0_DEVICE_ID //VDMA器件ID
#define DISP_VTC_ID XPAR_VTC_0_DEVICE_ID //VTC器件ID
//函数声明
void load_sd_bmp(u8 *frame);
//全局变量
XAxiVdma vdma;
DisplayCtrl dispCtrl;
VideoMode vd_mode;
//frame buffer的起始地址
unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR + 0x1000000);
unsigned int lcd_id=0; //LCD ID
int main(void)
{
xil_printf("HDMI Display 1920*1080 \r\n");
//sleep(10);
//设置video参数,分辨率:1920*1080
vd_mode = VMODE_1920x1080;
//配置VDMA
// run_vdma_frame_buffer(&vdma, VDMA_ID, vd_mode.width, vd_mode.height,
// frame_buffer_addr,0, 0,ONLY_READ);
//初始化Display controller
// DisplayInitialize(&dispCtrl, DISP_VTC_ID, DYNCLK_BASEADDR);
//设置VideoMode
// DisplaySetMode(&dispCtrl, &vd_mode);
// DisplayStart(&dispCtrl);
init();
//读取SD卡图片并显示
load_sd_bmp((u8*)frame_buffer_addr);
return 0;
}
//从SD卡中读取BMP图片
void load_sd_bmp(u8 *frame)
{
static FATFS fatfs;
FIL fil;
u8 bmp_head[54];
UINT *bmp_width,*bmp_height,*bmp_size;
UINT br;
int i;
//挂载文件系统
f_mount(&fatfs,"",1);
//打开文件
f_open(&fil,"shatan.bmp",FA_READ);
//移动文件读写指针到文件开头
f_lseek(&fil,0);
//读取BMP文件头
f_read(&fil,bmp_head,54,&br);
xil_printf("fengjing.bmp head: \n\r");
for(i=0;i<54;i++)
xil_printf(" %x",bmp_head[i]);
//打印BMP图片分辨率和大小
bmp_width = (UINT *)(bmp_head + 0x12);
bmp_height = (UINT *)(bmp_head + 0x16);
bmp_size = (UINT *)(bmp_head + 0x22);
xil_printf("\n width = %d, height = %d, size = %d bytes \n\r",
*bmp_width,*bmp_height,*bmp_size);
//读出图片,写入DDR
for(i=*bmp_height-1;i>=0;i--){
f_read(&fil,frame+i*(*bmp_width)*3,(*bmp_width)*3,&br);
}
//关闭文件
f_close(&fil);
Xil_DCacheFlush(); //刷新Cache,数据更新至DDR3中
xil_printf("show bmp\n\r");
}
- 用原子的设计,Nano的程序,不能运行起来,需要修改。修改点有2点,在程序中有说明
如果VDMA的Stream宽度是24,那么这里需要设置为3。 如果VDMA的Stream宽度是32,那么这里需要设置为4。
// --------------------------------------------------------------------
// Copyright (c) 2019 by MicroPhase Technologies Inc.
// --------------------------------------------------------------------
//
// Permission:
//
// MicroPhase grants permission to use and modify this code for use
// in synthesis for all MicroPhase Development Boards.
// Other use of this code, including the selling
// ,duplication, or modification of any portion is strictly prohibited.
//
// Disclaimer:
//
// This VHDL/Verilog or C/C++ source code is intended as a design reference
// which illustrates how these types of functions can be implemented.
// It is the user's responsibility to verify their design for
// consistency and functionality through the use of formal
// verification methods. MicroPhase provides no warranty regarding the use
// or functionality of this code.
//
// --------------------------------------------------------------------
//
// MicroPhase Technologies Inc
// Shanghai, China
//
// web: http://www.microphase.cn/
// email: [email protected]
//
// --------------------------------------------------------------------
// --------------------------------------------------------------------
//
// Major Functions:
//
// --------------------------------------------------------------------
// --------------------------------------------------------------------
//
// Revision History:
// Date By Revision Change Description
//---------------------------------------------------------------------
//2020-02-22 Wang 1.0 Original
//2020- 1.1
// --------------------------------------------------------------------
// --------------------------------------------------------------------
/* ------------------------------------------------------------ */
/* Include File Definitions */
/* ------------------------------------------------------------ */
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"
#include "display_demo.h"
#include "display_ctrl/display_ctrl.h"
#include "display_ctrl/vga_modes.h"
#include "ff.h"
#include "sleep.h"
void init();
/*
* XPAR redefines
*/
#define DYNCLK_BASEADDR XPAR_AXI_DYNCLK_0_BASEADDR
#define VGA_VDMA_ID XPAR_AXIVDMA_0_DEVICE_ID
#define DISP_VTC_ID XPAR_VTC_0_DEVICE_ID
/* ------------------------------------------------------------ */
/* Global Variables */
/* ------------------------------------------------------------ */
/*
* Display Driver struct
*/
DisplayCtrl dispCtrl;
XAxiVdma vdma;
static FIL fil; /* File object */
static FATFS fatfs;
/*
* Frame buffers for video data
*/
u8 frameBuf[DISPLAY_NUM_FRAMES][DEMO_MAX_FRAME] __attribute__ ((aligned (64)));
u8 *pFrames[DISPLAY_NUM_FRAMES]; // array of pointers to the frame buffers
/* ------------------------------------------------------------ */
/* Procedure Definitions */
/* ------------------------------------------------------------ */
unsigned char read_line_buf[1920 * 4];
void bmp_read(char * bmp,u8 *frame,u32 stride)
{
short y,x;
short Ximage;
short Yimage;
u32 iPixelAddr = 0;
FRESULT res;
unsigned char TMPBUF[64];
unsigned int br; // File R/W count
res = f_open(&fil, bmp, FA_OPEN_EXISTING | FA_READ);
if(res != FR_OK)
{
return ;
}
res = f_read(&fil, TMPBUF, 54, &br);
if(res != FR_OK)
{
return ;
}
Ximage=(unsigned short int)TMPBUF[19]*256+TMPBUF[18];
Yimage=(unsigned short int)TMPBUF[23]*256+TMPBUF[22];
iPixelAddr = (Yimage-1)*stride ;
for(y = 0; y < Yimage ; y++)
{
f_read(&fil, read_line_buf, Ximage * 3, &br);
for(x = 0; x < Ximage; x++)
{
frame[x * BYTES_PIXEL + iPixelAddr + 0] = read_line_buf[x * 3 + 0];
frame[x * BYTES_PIXEL + iPixelAddr + 1] = read_line_buf[x * 3 + 1];
frame[x * BYTES_PIXEL + iPixelAddr + 2] = read_line_buf[x * 3 + 2];
}
iPixelAddr -= stride;
}
f_close(&fil);
}
int main(void)
{
//sleep(10);
int i;
int Status;
XAxiVdma_Config *vdmaConfig;
FRESULT rc;
/*
* Initialize an array of pointers to the 3 frame buffers
*/
for (i = 0; i < DISPLAY_NUM_FRAMES; i++)
{
pFrames[i] = frameBuf[i];
}
xil_printf("hello world!\r\n");
/*
* Initialize VDMA driver, get the hardware VDMA configurations
*/
vdmaConfig = XAxiVdma_LookupConfig(VGA_VDMA_ID);
if (vdmaConfig == NULL)
{
xil_printf("No video DMA found for ID %d\r\n", VGA_VDMA_ID);
}
/*
* Use hardware VDMA configurations to initialize the driver
*/
Status = XAxiVdma_CfgInitialize(&vdma, vdmaConfig, vdmaConfig->BaseAddress);
if (Status != XST_SUCCESS)
{
xil_printf("VDMA Configuration Initialization failed %d\r\n", Status);
}
/*
* Initialize the Display controller and start it
*/
VideoMode VMODE = VMODE_1920x1080;
Status = DisplayInitialize(&dispCtrl, &vdma, DISP_VTC_ID, DYNCLK_BASEADDR, pFrames, DEMO_STRIDE, VMODE);
if (Status != XST_SUCCESS)
{
xil_printf("Display Ctrl initialization failed during demo initialization%d\r\n", Status);
}
Status = DisplayStart(&dispCtrl);
if (Status != XST_SUCCESS)
{
xil_printf("Couldn't start display during demo initialization%d\r\n", Status);
}
// init();
rc = f_mount(&fatfs, "0:/", 0);
if (rc != FR_OK)
{
return 0 ;
}
while(0){
char s[30];
memset(s,0,30);
printf("please input picture name:\r\n");
scanf("%s", &s[0]);
printf("%s\r\n",s);
bmp_read(s,dispCtrl.framePtr[dispCtrl.curFrame], DEMO_STRIDE);
Xil_DCacheFlushRange((unsigned int) dispCtrl.framePtr[dispCtrl.curFrame], DEMO_MAX_FRAME);
}
if(0){
char s[30]="shatan.bmp";
bmp_read(s,dispCtrl.framePtr[dispCtrl.curFrame], DEMO_STRIDE);
Xil_DCacheFlushRange((unsigned int) dispCtrl.framePtr[dispCtrl.curFrame], DEMO_MAX_FRAME);
}
if(1){
char s[30]="shatan.bmp";
bmp_read(s,(u8*)0x00126d40, DEMO_STRIDE); /*注意DEMO_STRIDE要设置成1920*3*/
Xil_DCacheFlushRange(0x00126d40, DEMO_MAX_FRAME);
}
return 0;
}
void init()
{
//初始化Display controller
Xil_Out32(0x43000000,0x4);
Xil_Out32(0x43c10008,0x400041);
Xil_Out32(0x43c1000c,0x0000069a);
Xil_Out32(0x43c10010,0x0);
Xil_Out32(0x43c10014,0x000020c4);
Xil_Out32(0x43c10018,0xcfafa401);
Xil_Out32(0x43c1001c,0x00a300ff);
Xil_Out32(0x43c10000,0x1);
usleep(1000);
Xil_Out32(0x43c10008,0x400041);
Xil_Out32(0x43c1000c,0x0000069a);
Xil_Out32(0x43c10010,0x0);
Xil_Out32(0x43c10014,0x000020c4);
Xil_Out32(0x43c10018,0xcfafa401);
Xil_Out32(0x43c1001c,0x00a300ff);
Xil_Out32(0x43c10000,0x0);
Xil_Out32(0x43c10000,0x1);
usleep(1000);
//设置VideoMode
Xil_Out32(0x43c00000,0x2);
Xil_Out32(0x43c0006c,0x0000007f);
Xil_Out32(0x43c00070,0x898);
Xil_Out32(0x43c00074,0x4650465);
Xil_Out32(0x43c00060,0x4380780);
Xil_Out32(0x43c00094,0x4380000);
Xil_Out32(0x43c00078,0x080407d8);
Xil_Out32(0x43c00080,0x0440043b);
Xil_Out32(0x43c0008c,0x0440043b);
Xil_Out32(0x43c00068,0x2);
Xil_Out32(0x43c0007c,0x7800780);
Xil_Out32(0x43c00084,0x07d807d8);
Xil_Out32(0x43c00088,0x7800780);
Xil_Out32(0x43c00090,0x07d807d8);
Xil_Out32(0x43c0007c,0x7800780);
Xil_Out32(0x43c00084,0x07d807d8);
Xil_Out32(0x43c00088,0x7800780);
Xil_Out32(0x43c00090,0x07d807d8);
Xil_Out32(0x43c00000,0x03f7ef02);
Xil_Out32(0x43c00000,0x03f7ef06);
usleep(1000);
//配置VDMA
Xil_Out32(0x43000000,0x10002);
// Xil_Out32(0x43000054,0x1); /*Nano例程的问题出在这里,不能配0x1*/
// Xil_Out32(0x43000058,0x1); /*Nano例程的问题出在这里,不能配0x1*/
Xil_Out32(0x43000054,0x1680);
Xil_Out32(0x43000058,0x1680);
Xil_Out32(0x4300005c,0x00126d40);
Xil_Out32(0x43000000,0x10003);
Xil_Out32(0x43000050,0x438);
Xil_Out32(0x43000028,0x0);
Xil_Out32(0x43000000,0x10001);
usleep(1000);
}