imx6ul spi dma传输分析
imx6ul sdk 里面spi 驱动做的比较完善,会自己判断是否满足dma传输的条件,如果满足dma传输就直接使用dma进行传输了。
那么imx 6ul平台spi使用dma传输的条件是什么呢?其实只要传输的bpw为1,2,4 然后数据长度为32的整数倍就可以使用dma传输了。
imx 进行spi传输相关的代码如下:
static int spi_imx_transfer(struct spi_device *spi,
struct spi_transfer *transfer)
{
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
//Mark by Jason 717628525@qq.com
if (spi_imx->usedma)
return spi_imx_dma_transfer(spi_imx, transfer);
else
return spi_imx_pio_transfer(spi, transfer);
}
通过下面函数判断是否满足进行dma传输的条件:
static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *transfer)
{
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
unsigned int bpw;
if (!master->dma_rx) {
return false;
}
if (!transfer) {
return false;
}
bpw = transfer->bits_per_word;
if (!bpw)
bpw = spi->bits_per_word;
bpw = spi_imx_bytes_per_word(bpw);
if (bpw != 1 && bpw != 2 && bpw != 4) {
return false;
}
if (transfer->len < spi_imx->wml * bpw) {
return false;
}
if (transfer->len % (spi_imx->wml * bpw)) {
return false;
}
return true;
}
为了测试dma与传统spi传输的差异,驱动里面数据发送函数做了些处理:
/**
* @brief LCD底层SPI发送数据函数
*
* @param data 数据的起始地址
* @param size 发送数据大小
*
* @return void
*/
static void LCD_SPI_Send(u8 *data, u32 size)
{
if (!use_dma_flag) {
u32 i;
u32 delta;
delta = size/0xFFFF;
for(i = 0; i<=delta; i++)
{
if( i==delta ) /* 发送最后一帧数据 */ {
//SPI2_WriteData(&data[i*0xFFFF], size%0xFFFF); /SPI2_WriteData/替换linux接口
spi_lcd_st7789_send_data(&data[i*0xFFFF], size%0xFFFF);
} else {/* 超长数据一次发送0xFFFF字节数据 */
//SPI2_WriteData(&data[i*0xFFFF], 0xFFFF); //SPI2_WriteData替换linux接口
spi_lcd_st7789_send_data(&data[i*0xFFFF], 0xFFFF);
}
}
} else {
//printk(KERN_WARNING "%s:%d[dma t1]\n", __FUNCTION__, __LINE__);
if (-1 == dma_split_size) {
spi_lcd_st7789_send_data(data, size);
} else {
if (dma_split_size % 32 != 0) {
printk(KERN_WARNING "dma_split_size shuold be 32x, use in normal mode\n");
}
u32 i;
u32 delta;
delta = size/dma_split_size;
for(i = 0; i<=delta; i++)
{
if( i==delta ) /* 发送最后一帧数据 */ {
spi_lcd_st7789_send_data(&data[i*dma_split_size], size%dma_split_size);
} else {/* 超长数据一次发送0xFFFF字节数据 */
spi_lcd_st7789_send_data(&data[i*dma_split_size], dma_split_size);
}
}
}
}
}
传统模式直接对数据行进65535字节分片处理,如果是dma传输方式,插入模块时候设置了dma_split_size,就用dma_split_size作为分片传输大小。
否则dma传输分片大小直接设置为发送数据大小。
测试dma 模式与普通模式性能:
1. dma模式
insmod lcd_st7789.ko use_dma_flag=1
./test_spi_lcd_st7789 /dev/fb2
dma 模式:
Test drawing GREEN......
data 0xffffe007
[ 68.656193] --->spi_imx_transfer:1154 len:115200 [spi_dma t00] #一帧开始
[ 68.756468] --->spi_imx_transfer:1157 len:115200 [spi_dma t01] #一帧结束
Test drawing BLUE......
data 0x00001f00
[ 69.674976] --->spi_imx_transfer:1154 len:115200 [spi_dma t00]
[ 69.775234] --->spi_imx_transfer:1157 len:115200 [spi_dma t01]
Test drawing WHITE......
data 0xffffffff
[ 70.694087] --->spi_imx_transfer:1154 len:115200 [spi_dma t00]
[ 70.794338] --->spi_imx_transfer:1157 len:115200 [spi_dma t01]
Test drawing Black......
data 0x00000000
[ 71.713737] --->spi_imx_transfer:1154 len:115200 [spi_dma t00]
[ 71.813939] --->spi_imx_transfer:1157 len:115200 [spi_dma t01]
Test write......
#[ 72.726856] --->spi_imx_transfer:1154 len:115200 [spi_dma t00]
[ 72.832990] --->spi_imx_transfer:1157 len:115200 [spi_dma t01]
传输数据长度=240x240x2=115200 240x240为lcd屏宽x高 一个像素rgb565=2 bytes
通过前面时间戳计算一帧传输耗时:756468-656193=100275us=100ms=10Hz
多组计算取均值fps:8.5
dma平均fps:8.5
2. 普通模式测试
insmod lcd_st7789.ko use_dma_flag=0
./test_spi_lcd_st7789 /dev/fb2
Test drawing RED......
data 0x000000f8
[ 154.758112] --->spi_imx_transfer:1166 len:65535[spi_pio t01]
[ 154.764102] --->spi_imx_transfer:1163 len:49665[spi_pio t00]
[ 154.869715] --->spi_imx_transfer:1166 len:49665[spi_pio t01]
Test drawing GREEN......
data 0xffffe007
[ 155.627946] --->spi_imx_transfer:1163 len:65535[spi_pio t00] #一帧开始
[ 155.782548] --->spi_imx_transfer:1166 len:65535[spi_pio t01]
[ 155.788514] --->spi_imx_transfer:1163 len:49665[spi_pio t00]
[ 155.893319] --->spi_imx_transfer:1166 len:49665[spi_pio t01] #一帧结束
Test drawing BLUE......
data 0x00001f00
[ 156.646880] --->spi_imx_transfer:1163 len:65535[spi_pio t00]
[ 156.785073] --->spi_imx_transfer:1166 len:65535[spi_pio t01]
[ 156.790957] --->spi_imx_transfer:1163 len:49665[spi_pio t00]
[ 156.895981] --->spi_imx_transfer:1166 len:49665[spi_pio t01]
Test drawing WHITE......
data 0xffffffff
[ 157.665533] --->spi_imx_transfer:1163 len:65535[spi_pio t00]
[ 157.819960] --->spi_imx_transfer:1166 len:65535[spi_pio t01]
[ 157.825955] --->spi_imx_transfer:1163 len:49665[spi_pio t00]
[ 157.931670] --->spi_imx_transfer:1166 len:49665[spi_pio t01]
Test drawing Black......
data 0x00000000
[ 158.684833] --->spi_imx_transfer:1163 len:65535[spi_pio t00]
[ 158.843126] --->spi_imx_transfer:1166 len:65535[spi_pio t01]
[ 158.849013] --->spi_imx_transfer:1163 len:49665[spi_pio t00]
[ 158.955808] --->spi_imx_transfer:1166 len:49665[spi_pio t01]
Test write......
#[ 159.697439] --->spi_imx_transfer:1163 len:65535[spi_pio t00]
[ 159.857060] --->spi_imx_transfer:1166 len:65535[spi_pio t01]
[ 159.863748] --->spi_imx_transfer:1163 len:49665[spi_pio t00]
[ 159.967410] --->spi_imx_transfer:1166 len:49665[spi_pio t01]
115200= 65535+49665,通过dma类似方法算出平均fps
普通模式平均fps:3.71
3. 测试结果分析
dma 传输模式速度为普通模式的2.29倍,大大加速了数据传播速度
测试还发现dma_split_size 会影响dma的速度,越大dma传输会越快