现在的位置: 首页 > 综合 > 正文

TQ2440的学习——IIS接口的使用

2014年06月05日 ⁄ 综合 ⁄ 共 5819字 ⁄ 字号 评论关闭

TQ2440的学习——IIS接口的使用(基本概念和基本功能实验)》中的轮询最大的缺陷就是性能低下,所以开启DMA传输是很大的优势的。虽然比轮询稍微多点代码。

DMA的播放/录音实现和轮询实现的区别在于,轮询需要自己编写数据输出/读取代码,但是DMA方式下不用,只需要指明源地址和目标地址以及数据大小就可以由硬件自动传输数据了,只是要注意的是S3C2440下的DMA使用时候数据大小是有限制的,一次最多可以传输的字节大小为:DSZ×TSZ×TC,DSZ表示的是数据大小(字节1、半字2、字4);TSZ表示的是传输大小(单元传输还是突发传输),TC表示传输计数值(寄存器DCONn的低20位存放的数据),超过这个数据大小的数据就必须要分次进行传输。至于DMA寄存器其它的位的功能描述,可以参见《S3C2440芯片资料DMA阅读笔记——基本概念》中的相关总结。

这段代码是本次试验的相关主控部分。同样,实验的时候现录音再播放:

01      else if(!(no_system_strcmp("iis record play dma",cmd_buf))) 
02      { 
03          no_system_memset(cmd_buf,0,50); 
04          GPBCON = 0x015550
05          GPBUP = 0x7ff
06          GPBDAT = 0x1e4
07          GPEUP = (GPEUP & (~(0x1f))) | 0x1f
08          GPECON = (GPECON & (~(0x3ff))) | 0x2aa
09   
10          uart0_printf("play begin\n\r"); 
11          playsound_dma((unsigned char *)0x31000000,6400 * 400); 
12          uart0_printf("play end\n\r"); 
13      } 
14      else if(!(no_system_strcmp("iis record dma",cmd_buf))) 
15      { 
16          no_system_memset(cmd_buf,0,50); 
17          GPBCON = 0x015550
18          GPBUP = 0x7ff
19          GPBDAT = 0x1e4
20          GPEUP = (GPEUP & (~(0x1f))) | 0x1f
21          GPECON = (GPECON & (~(0x3ff))) | 0x2aa
22   
23          uart0_printf("record begin\n\r"); 
24          record_dma((unsigned char *)0x31000000,6400 * 400); 
25          uart0_printf("record end\n\r"); 
26      } 

这段代码实现了播放一段2声道、44.1KHz音频数据的功能。和轮询方式不同的,这里主要就是配置了IIS和DMA2的寄存器(放音使用通道2):

01  void playsound_dma(unsigned char *buffer,unsigned long int length) 
02  { 
03      DMA_SRC_SIZE = length;//全局变量,会在中断处理中用到 
04   
05      GPBDAT    = (GPBDAT & (~(L3M | L3C | L3D))) | (L3M | L3C); 
06   
07      WriteL3(0x14 + 2,1); 
08      WriteL3(0x60,0); 
09   
10      WriteL3(0x14 + 2,1); 
11      WriteL3(0x10,0); 
12   
13      WriteL3(0x14 + 2,1); 
14      WriteL3(0xc1,0); 
15   
16      IISPSR = PRESCANLER_A(2) | PRESCANLER_B(2); 
17      IISCON = TX_DMA_ENABLE | RX_CH_IDLE_CMD | IIS_PRESCALER; 
18      IISMOD = TX_RX_MODE(TX_MODE) | S_DATA_BIT(BIT16) | MA_CLOCK(FS384) | \ 
19              S_CLOCK(FS32); 
20      IISFCON = TX_FIFO_AC(DMA) | TX_FIFO_EN; 
21      //unsigned long int address = buffer; 
22      DISRC2 = 0x31000000
23      DISRCC2 = (0 << 1) | (0 << 0);//AHB,incresment 
24      DIDST2 = 0x55000010;//FIFO is destination 
25      DIDSTC2 = (0 << 2) | (1 << 1) | (1 << 0);//when 0 interrupt,APB,fixed 
26   
27      DCON2 = (1 << 31) | (0 << 30) | (1 << 29) | (0 << 28) | (0 << 27) | \ 
28          (0 << 24) | (1 << 23) | (1 << 22) | (1 << 20) | \ 
29          ((length > 0x200000)?0xfffff:((length >> 1) & 0xfffff)); 
30      DMASKTRIG2 = (0 << 2) | (1 << 1) | 0
31      IISCON |= 0x1
32  } 

这段代码实现了录制一段2声道、44.1KHz音频数据的功能(使用DMA通道):

01  void record_dma(unsigned char *buffer,unsigned long length) 
02  { 
03      DMA_SRC_SIZE = length; 
04      GPBDAT = (GPBDAT & (~(L3M | L3C | L3D))) | (L3M | L3C); 
05   
06      WriteL3(0x14 + 2,1); 
07      WriteL3(0x60,0); 
08   
09      WriteL3(0x14 + 2,1); 
10      WriteL3(0x10,0); 
11   
12      WriteL3(0x14 + 2,1); 
13      WriteL3(0xc1,0); 
14   
15      WriteL3(0x14 + 2,1); 
16      WriteL3(0xe3,0); 
17   
18      WriteL3(0x14 + 0,1); 
19      WriteL3(0x7b,0); 
20   
21      WriteL3(0xc4,0); 
22      WriteL3(0xf0,0); 
23   
24      WriteL3(0xc0,0); 
25      WriteL3(0xe0,0); 
26   
27      WriteL3(0xc1,0); 
28      WriteL3(0xe0,0); 
29   
30      WriteL3(0xc2,0); 
31      WriteL3(0xf9,0); 
32   
33      IISPSR = PRESCANLER_A(2) | PRESCANLER_B(2); 
34      IISCON = RX_DMA_ENABLE | TX_CH_IDLE_CMD | IIS_PRESCALER; 
35      IISMOD = TX_RX_MODE(RX_MODE) | S_DATA_BIT(BIT16) | \ 
36              MA_CLOCK(FS384) | S_CLOCK(FS32); 
37      IISFCON = RX_FIFO_AC(DMA) | RX_FIFO_EN; 
38   
39      DISRC1 = 0x55000010
40      DISRCC1 = (1 << 1) | (1 << 0);//APB,fixed 
41      DIDST1 = 0x31000000
42      DIDSTC1 = (0 << 2) | (0 << 1) | (0 << 0); 
43      DCON1 = (1 << 31) | (0 << 30) | (1 << 29) | (0 << 28) | (0 << 27) | \ 
44          (2 << 24) | (1 << 23) | (1 << 22) | (1 << 20) | \ 
45          ((length > 0x200000)?0xfffff:((length >> 1) & 0xfffff)); 
46      DMASKTRIG1 = (0 << 2) | (1 << 1) | 0
47      IISCON |= 0x1
48  } 

这段代码是DMA通道中断的处理代码,一次数据传完后就会触发这个中断。中断需要处理的就是判断数据是否传完,传完就关闭DMA和IIS,否则就传输下一片内存的数据,具体的方法是修改源地址,使其偏移到未传输数据的内存起始地址,由于录音和放音使用的是不同的DMA通道,所以中断处理函数都是大体相同的,区别仅仅存在于进入中断后所屏蔽的中断位(这里就以放音的DMA中断为例):

01  void DMA_interrupt(void
02  { 
03      SRCPND |= 0x1 << 19
04      INTPND |= 0x1 << 19
05      /** 
06       *思路:通过计算得出在单元传输模式下(一次一个) 
07       *传送16位数据,最大的一次传送总数为0x200000(因为TC计数器最大为0x100000 
08       *如果数据小于0x200000进入中断的时候数据肯定都已经传完了,这个时候关闭DMAIIS 
09       */ 
10      if(DMA_SRC_SIZE >= 0x200000)//not end 
11      { 
12          DISRC2 += 0x200000
13          DMA_SRC_SIZE -= 0x200000
14          if(0 != DMA_SRC_SIZE)//will end 
15          { 
16              //一次传送的数据为半字 
17              DCON2 = (DCON2 & (~0xfffff)) | ((DMA_SRC_SIZE > 0x200000)?0xfffff:((DMA_SRC_SIZE >> 1) & 0xfffff)); 
18              DMASKTRIG2 = (0 << 2) | (1 << 1) | 0
19          } 
20          else//end DMA_SRC_SIZE == 0 
21          { 
22              IISCON = 0x0
23              IISFCON = 0x0
24              DMASKTRIG2 = 1 << 2
25          } 
26      } 
27      else//DMA_SRC_SIZE < 0x200000 already end 
28      { 
29          IISCON = 0x0
30          IISFCON = 0x0
31          DMASKTRIG2 = 1 << 2
32      } 
33  } 

总结

在配置S3C2440的寄存器的时候,一定要注意寄存器的位宽,如果在C语言中采用的数据类型描述该寄存器的时候,如果数据类型过大或者过小,会造成很奇怪的问题(例子:DMASKTRIGx寄存器在芯片资料上只有3个位,所以在C语言下要定义成unsigned char类型才能正常使用)。IIS在播放不出声音的时候,首先要确定寄存器配置是否正确,然后再看内存空间是否得到正确的访问(不要忘记偏移)。

写到现在,其实最深的感觉是要用一个东西简单,用好确实非常难的。看看S3C2440都出了多少年了,已经算是很落后的芯片了。但是又有多少应用它的产品将它的性能完全发挥出来了?偶然看到新闻上介绍的一个489的平板,看评论上有的说连耍个小鸟砸猪都卡死。那个平板配置了1GHzARM11 CPU啊,应该带了图形加速处理单元吧。真不明白小鸟用了啥复杂的运算还是咋了。想想NDS吧,66MHzARM9 CPU + 33MHzARM7 CPU(在耍NDS游戏的时候还只能用ARM9CPU负责图像处理)。耍最终幻想的时候那画面不比小鸟差吧,还3D且双屏显示带触控。一味的追求高性能硬件又有啥用?结果平板卖的比(水货)NDS卖的还便宜。虽然买这个平板的人大概也没指望多高的性能。但是1GHzCPU只能用来当做玩玩简单游戏的MP4是一件让人很不爽的事。

抱歉!评论已关闭.