vivado+zedboard之audio驱动

来源:互联网 发布:北风人工智能百度云 编辑:程序博客网 时间:2024/05/16 18:08
环境:win7 64   vivado 2014.1
开发板:zedboard version d    xc7z020clg484-1
串口软件:SecureCRT
目标:使用vivado进行zedboard的audio测试。从pc获取音频信号,通过开发板处理后输出。通过本实例学习vivado+zedboard软硬件设计的方法,学习控制zedboard外设的方法。本文将介绍实验的过程,并对驱动程序进行分析,简单说明如何驱动audio设备。并简单介绍如何通过SDK来控制外设。
说明:本文参考Xilinx官网教程,筛选audio驱动部分。在“我的资源”提供了fir的源代码,可以生成IP。关于HLS的使用,官网ug871上有详细介绍,可以参考。
正文:
本文将分为以下步骤:
1. 使用Vivado TCL创建一个工程,修改相关参数,完成硬件设计。generate,最后导入到SDK中

2. 在SDK中新建工程,添加文件,编译。下载到ZedBoard上进行调试

3. 驱动程序分析

4. 获取IP信息的方法整理

5. 总结


1. 使用Vivado TCL创建一个工程,修改相关参数,完成硬件设计。generate,最后导入到SDK中

1)找到../audio/src/audio_project_create.tcl,使用notepad++等软件打开,可以修改其中路径以创建工程。默认的将在../audio/下创建pro_audio目录为工作目录。

打开vivado或者shell,输入:cd ../audio/src回车,输入:source audio_project_create.tcl回车。注意zed_audio_ctrl文件夹要放在同一文件夹。此时会自动创建下图设计。


2)打开address editor,查看地址是否已分配。如果未分配则点击左侧“auto assign address”


3)validate design

4)create HDL wrapper(详见上篇OLED驱动)

5)添加约束。在add sources中选择constrains,选择zed_audio_constraints.xdc文件。


6)generate bitstream

7)file->export->export hardware for SDK(注意要打开block design和implement design),勾选launch SDK

2. 在SDK中新建工程,添加文件,编译。下载到ZedBoard上进行调试

8)在SDK中,新建工程test_audio,选择空模板

9)在test_audio->src右击,选择import,选择general->file system->(browse),选择

   audio.h adau1761.h adau1761.c:音频芯片参数定义、音频驱动程序以及相关操作函数(本例操作函数提供的不多,用户可自行编写)

   iic.h iic.c:IIC总线的驱动程序

   test_audio.c:主函数,驱动测试程序

10)添加完毕后,SDK会自动编译程序。出现“'Finished building: test_audio.elf.size'”说明成功。

11)使用音频线(音箱和电脑连接的那个线)连接pc的音频口和zedboard的LINE IN接口,将耳机的音频插头接入LINE OUT接口。使用miniUSB连接J14和J17接口用于串口通信和烧写程序。

12)打开SecureCRT并连接。选择Xilinx tools->Program FPGA,烧写程序,蓝灯DONE亮说明成功。

13)打开PC的音频播放器,随便播放一段音频。run->run as,选择GDB。

14)可以看到串口打印的提示信息。通过开关选择可以进行控制。(这段测试用,不要挑剔哈)

开关SW0、SW1:

00:初始状态;退出函数
01:进入函数,播放音乐(PC的音乐信号一直输入)
11:进入处理函数,噪音(本例)或执行音频处理程序
10:退出程序



3. 驱动程序分析

15)测试程序


从函数的引用关系图中可以看出,首先对IIC、Audio Codec's PLL进行初始化,使能HP jack等。
然后进行流程控制,如果SW0为on,则执行filter_or_bypass_input函数,读取音频信号做进一步处理,根据SW1状态决定是否执行处理,否则直接输出原信号。如果SW0为off,则串口打印当前音频值(按16位显示)。

16)IIC:IicConfig()


main()->IicConfig(XPAR_XIICPS_0_DEVICE_ID);       // XPAR_XIICPS_0_DEVICE_ID=0(xparameters.h)
IicConfig(0)->Config = XIicPs_LookupConfig(0);                        //即查阅下表,得到设备信息
XIicPs_ConfigTable[0]={XPAR_PS7_I2C_1_DEVICE_ID,XPAR_PS7_I2C_1_BASEADDR, XPAR_PS7_I2C_1_I2C_CLK_FREQ_HZ}={0,0xE0005000,111111115},即Config.
Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);    //初始化;对InstancePtr写入从Config获取的相关值,通过XIicPs_GetOptions()函数完成初始化
XIicPs_SetSClk(&Iic, IIC_SCLK_RATE)        //初始化IIC设备的串行时钟频率。IIC_SCLK_RATE=400000(Audio.h)
17)Audio Codec's PLL:AudioPllConfig()
Configures audio codes's internal PLL. With MCLK = 8 MHz it configures the PLL for a VCO frequency = 49.152 MHz, and an audio sample rate of 48 KHz.

首先判断IIC初始化的状态,成功则继续。
AudioWriteToReg(R0_CLOCK_CONTROL, 0x0E);        //向audio controller的一个寄存器写入一个字节;此处R0_CLOCK_CONTROL=0x00(audio.h)
XIicPs_MasterSendPolled()        //发送数据到FIFO等待设备接收;如未接收则发送错误超时信息。


18)HP jack:AudioConfigureJacks()
Configures audio codes's various mixers, ADC's, DAC's, and amplifiers to accept stereo input from line in and push stereo output to line out.
看源代码和datasheet以了解是如何配置audio的

19)音频信号处理:filter_or_bypass_input()    //死循环,直至程序退出
读取IIC总线上的数据经处理后送到IIC总线发出。读写寄存器的函数分别为Xil_in32(),Xil_out32()

首先读取I2S_STATUS_REG寄存器的值(定义见Audio.h->enum i2s_regs),判断IIS总线是否可用。
然后读取I2S_DATA_RX_L_REG、I2S_DATA_RX_R_REG的值右移8位并赋值给u32DataL、u32DataR。( TX代表传送数据,RX是接收数据)
如果SW1为on,则进入处理函数处理,并将处理结果左移8位保存到u32DataL、u32DataR中。
最后发送u32DataL、u32DataR到IIC总线,即写入I2S_DATA_RX_L_REG、I2S_DATA_RX_R_REG寄存器。

对于filter_or_bypass_input()函数,中间最核心的音频数据处理函数本例是随便写的噪音函数,如果想进行FIR、FFT等处理可以自行编写函数。

if(sw_check == 0x03) // SW1=1 SW0=1 then pass the sample through the filter{Sample_L = (u32DataL >> 8);Sample_R = (u32DataR >> 8);<strong>//user_function(Sample_L,Sample_R);</strong>Sample_L = Sample_L<<16;Sample_R = Sample_R<<8;u32DataL = Sample_L << 8;u32DataR = Sample_R << 8;}

关于I2S_STATUS_REG、I2S_DATA_RX_L_REG、I2S_DATA_RX_R_REG等寄存器的操作很重要,是如果通过软件控制外设的方式。

参看部分audio.h程序:

//Audio controller registers//see the user_logic file in its definitionenum i2s_regs {I2S_DATA_RX_L_REG= 0x00 + AUDIO_BASE,I2S_DATA_RX_R_REG= 0x04 + AUDIO_BASE,I2S_DATA_TX_L_REG      = 0x08 + AUDIO_BASE,I2S_DATA_TX_R_REG         = 0x0c + AUDIO_BASE,I2S_STATUS_REG          = 0x10 + AUDIO_BASE,};
这里可以看到这些寄存器的地址,其中audio_base通过:#define AUDIO_BASEXPAR_ZED_AUDIO_CTRL_0_BASEADDR  定义为依赖于vivado设计的地址,通过由vivado自动生成的xparameters.h定义分配的地址值。

那么为什么寄存器定义为代码中的地址值呢?为此本文多方寻找,苦苦思索,猜想应该是使用的zed_audio_ctrl IP核的原因,其中应该包含寄存器分配表,但是如何读取IP呢?没有说明文件,如何获取IP信息呢?下一节再做说明。已经在zed_audio_ctrl文件中找到了其原始定义的user_logic.vhd,可以看到部分代码:

  --    Bus2IP_WrCE/Bus2IP_RdCE   Memory Mapped Register  --                     "1000"   C_BASEADDR + 0x0  --                     "0100"   C_BASEADDR + 0x4  --                     "0010"   C_BASEADDR + 0x8  --                     "0001"   C_BASEADDR + 0xC

    case slv_reg_read_sel is      when "10000" => slv_ip2bus_data <= DataRx_L;      when "01000" => slv_ip2bus_data <= DataRx_R;      when "00100" => slv_ip2bus_data <= DataTx_L;      when "00010" => slv_ip2bus_data <= DataTx_R;      when "00001" => slv_ip2bus_data <= "0000000000000000000000000000000" & data_rdy_bit;      when others => slv_ip2bus_data <= (others => '0');    end case;

通过这两段代码就可以看出audio.h的依据所在了。(ps:个人理解哈)

而对于audio.h的其他定义,如:

//Slave address for the ADAU audio controller#define IIC_SLAVE_ADDR0x76//see ADAU1761 datasheet//I2C Serial Clock frequency in Hertz#define IIC_SCLK_RATE400000//ADAU internal registersenum audio_regs {//see ADAU1761 datasheetR0_CLOCK_CONTROL= 0x00,R1_PLL_CONTROL = 0x02,R2_DIGITAL_MIC_JACK_DETECTION_CONTROL = 0x08,R3_RECORD_POWER_MANAGEMENT= 0x09,R4_RECORD_MIXER_LEFT_CONTROL_0 = 0x0A,R5_RECORD_MIXER_LEFT_CONTROL_1 = 0x0B,R6_RECORD_MIXER_RIGHT_CONTROL_0 = 0x0C,
则来自于ADAU1761芯片的datasheet,读者可以自行查找。

20)小结一下,关于对外设的驱动,本人的理解就是对寄存器的操作,包括地址和配置参数。本分析也就主要是分析寄存器是如何查找的、配置参数的依据是什么。
4. 获取IP核信息的方法

21)在本例中使用的IP,是通过vivado封装工具创建的IP,可重新编辑该IP,查看源文件,一般在“user_logic.v”文件可找到寄存器的定义以及端口说明。

22)对于官网IP,一般可查看相应的document

23)对于通过HLS创建的IP,一般会有“IP_hw.h'”文件,可以获取寄存器的定义信息。比如本例提供的FIR源文件,使用HLS生成IP后会生成\solution1\impl\ip\drivers\..\*_hw.h文件,可以查看以了解寄存器和端口分配。

5. 总结

本文创建了zedboard的audio驱动的软硬件平台并进行了测试,对驱动程序进行了分析,并整理了获取IP和信息的几种方法。本文参考官网实例,旨在分享经验和心得,不喜勿喷,欢迎讨论。转载请注明出处,发文不易啊。:)


0 0
原创粉丝点击