$> make dep //搜索Linux编译输出与源代码之间的依赖关系并生成依赖文件。 $> make clean //清除构造内核时生成的目标文件、模块文件和临时文件。 $> make zImage //生成压缩的内核映像文件。
图4.5 生成内核
编译通过后,在/usr/local/src/edukit-2410/kernel/arch/arm/boot/目录下生成内核的压缩映像文件为“zImage”,此文件是最后要烧写到开发板的内核映像文件。
图4.6 根目录
4.3.1 内核下载:
1)启动超级终端(波特率为115200),连好串口线,在开机瞬间快速按空格键,进入vivi控制台命令行下;
2)在vivi命令行输入:load flash kernel x(向flash芯片烧写kernel,采用xmodem协议),回车后提示等待;
图4.7 vivi终端显示
15
3)立即选择要发送的文件,比如zImage文件,这里Linux环境下源代码arch/arm/boot目录下的zImage内核映像文件已转移到 windows某目录下。要选择合适的xmodem协议。以上操作完成 后,单击“发送,几分钟后即可发送完毕。
图4.8 zImage的发生文件
图4.9 zImage正在发送图
16
第五章 课程设计功能模块程序设计与交叉编译
5.1 课程设计模块功能
5.1.1 三个模块:
I2S音频总线接口电路 ;音频编解码器芯片udal41; DMA控制器; 5.1.2 工作过程:
麦克风输入的模拟音频信号在音频编解码器中经过A/D转换和编码将模拟信号转换成数字信号,将这些数字信号先传给I2S音频总线接口电路中的FIFO,再由DMA控制器送入DSP中做相应的处理,这是录音的过程;DMA控制器将DSP中存储的信号传送给I2S音频总线接口电路中的FIFO,再发送给音频编解码芯片进行D/A转换,通过耳机输出模拟信号。
5.2 功能模块驱动程序设计
由于目前许多硬件厂商在出售各种产品时,一般都不带Linux下的设备驱动程序,而且编写驱动程序的工作量占整个系统工作量的很大的一部分,这使得Linux下设备驱动程序的开发变得越来越重要。
本课程设计不要求自己编写驱动程序,但要求分析UDAl341TS驱动程序,以便编写出语音采集与播放的应用测试程序,同时为以后编写驱动程序打好基础。嵌入式Linux系统下的IIS音频驱动程序是在/usr/local/src/edukit-2410/drivers/sound 中,3c2410-uda1341.c 文件即是。 5.2.1 关于结构体:
在音频驱动程序中有2个比较重要的结构体: typedef struct {
int size; /* buffer size */
char *start; /* point to actual buffer */(内存虚拟地址起始地址) dma_addr_t dma_addr; /* physical buffer address */(内存物理地址起始地址) struct semaphore sem; /* down before touching the buffer */
int master; /* owner for buffer allocation, contain size when true */(内存大小)
} audio_buf_t; typedef struct {
audio_buf_t *buffers; /* pointer to audio buffer structures */ audio_buf_t *buf; /* current buffer used by read/write */ u_int buf_idx; /* index for the pointer above */
u_int fragsize; /* fragment i.e. buffer size */(音频缓冲区片大小) u_int nbfrags; /* nbr of fragments */(音频缓冲区片数量) dmach_t dma_ch; /* DMA channel (channel2 for audio) */
17
} audio_stream_t;
audio_stream_t是一个管理多缓冲区的结构体,为音频流数据组成了一个环形缓冲区。audio_buf_t管理一段内存,audio_stream_t管理N个audio_buf_t。 音频驱动的两个file_operations结构定义如下:
static struct file_operations smdk2410_audio_fops = { llseek: smdk2410_audio_llseek, write: smdk2410_audio_write, read: smdk2410_audio_read, poll: smdk2410_audio_poll, ioctl: smdk2410_audio_ioctl, open: smdk2410_audio_open, release: smdk2410_audio_release };
static struct file_operations smdk2410_mixer_fops = { ioctl: smdk2410_mixer_ioctl, open: smdk2410_mixer_open, release: smdk2410_mixer_release };
这里定义了两种类型设备的file_operations结构,前者是DSP设备,后者是混频器设备。Linux 内核内部通过file结构识别设备,通过file_operations数据结构体提供文件系统的入口点函数,也就是访问设备驱动程序里的函数。file_operations结构体原型是在
read()、write()、open()和ioctl()是struct file_operations结构体中的接口函数。 1) read()函数:由已打开的文件读取数据,即播放。
(1)函数定义:ssize_t read(struct file *file, char *buffer, size_t count, loff_t * ppos);
(2)函数说明:把参数file所指的文件传送count个字节到buffer指针所指的内存中;若参数count为0,则read()不会有作用并返回0;
(3)返回值:返回值为实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。 如果正确会返回实际读到的字节数,最好能将返回值与参数count作比较,若返回的字节数比要求读取的字节数少,则有可能读到了文件尾、从管道(pipe)或终端机读取,或者是read()被信号中断了读取动作。当有错误发生时则返回-1,错误代码存入errno中,而文件读写位置则无法预期;
2)write()函数:将数据写入已打开的文件内,即录音。
(1)函数定义:ssize_t write (struct file *file, const char *buffer, size_t count, loff_t * ppos);
18

