Ⅰ linux 應用層spi怎麼使用dma
DMA不可以自動幫忙發送時鍾信號,但是如果讓spi發送數據並且使用DMA方式,spi可以幫忙自動發送時鍾信號。基於這樣的理論,試了一上午,成功了,很高興。這是在網友的幫助下完成的,現在寫下來分享給大家,將溫暖傳遞下去。
硬體:stm32+cc1101無線模塊(兩者之前通過spi通信)
配置:stm32的spi工作在master模式,當cc1101有數據派游做時,將會給stm32一個外部中斷。
實現方法:配置DMA的兩個通道,分別用於spi發送和spi接收,配置的時候先把其它參數都配置好不要使能DMA,也就是說先不要寫這兩句話:
DMA_Cmd(DMA1_Channel4,
ENABLE);
DMA_Cmd(DMA1_Channel5,
ENABLE);
在表示cc1101數據來臨的外部中斷的中斷處理函數中將DMA打開,這個時候,spi就會向cc1101發送數據(也就是stm32的spi接收來自cc1101數據所磨跡需要的時鍾),發送數據的同時,cc1101數據就會不斷的從cc1101的寄存器裡面跑到SPI_DR裡面。由於已經配置好了接收SPI的DMA,所以數據到來了SPI_DR裡面以後,DMA會自動將數塵衡據幫你拷貝到緩存數組里去,你只需要在用於接收的DMA中斷處理函數裡面將緩存數組里的數據拷出來即可。拷完以後最好把DMA關掉,否則spi會不斷向外發送數據,可能會讓你接回來一些沒用的數據。
Ⅱ linx下如何驅動spi
1、驅動分為平台驅動、控制器驅動、設備驅動、設備。
2、拿到一個開發板後,燒上橡余察系統,那我們基本上就有了平台驅動、控制器驅動。設備驅動基本都有的,官方實現了一個設備驅動,文件是spidev.c,它是一個設備驅動毀數,它會在開機之後自動注冊一個主設備號為153的字元設備。
3、當注冊了SPI設備到系統中時,會根據名字進行匹配,如果名字是spidev則會調用 spidev.c中的probe函數,隨後會在/dev/device/下面生成如spidevx.x的設備文件,通過該設備文件即可操作SPI設備。
4、如何注冊SPI設備到系統。在kernel/arch/arm/mach-xxxx,xxx是板子晶元型號,我用的事 mach-smdk6410.c。在裡面找到spi_board_info結構體位置,例如:
static struct spi_board_info __initdata forlinx6410_mc251x_info[] = {
{
.modalias = "mcp2515",
.platform_data = &mcp251x_info,
.irq = IRQ_EINT(16),
.max_speed_hz = 10*1000*1000,
.bus_num = 1,
.chip_select = 0,
.mode = SPI_MODE_0,
.controller_data=&s3c64xx_spi1_csinfo,
},
};
本結構體就是SPI的板級信息,會在後面被spi_register_board_info()調用,隨後在系統中注冊這個設備。
我們需要做的是添加我們自己的信息
static struct spi_board_info __initdata forlinx6410_mc251x_info[] = {
{
.modalias = "mcp2515",
.platform_data = &mcp251x_info,
.irq = IRQ_EINT(16),
.max_speed_hz = 10*1000*1000,
.bus_num = 1,
.chip_select = 0,
.mode = SPI_MODE_0,
.controller_data=&s3c64xx_spi1_csinfo,
},
{
.modalias = "spidev", //用來匹配設備驅動,SPI的設備驅動叫spidev
.max_speed_hz = 10*1000*1000, //最大速率
.bus_num = 0, //在(0)號匯流排上
.chip_select = 0, //使用片選spi0_cs0
.mode = SPI_MODE_0, //SPI模式
.controller_data=&s3c64xx_spi0_csinfo,//控制器信息 },
};
其中的static struct s3c64xx_spi_csinfo s3c64xx_spi0_csinfo = {
.fb_delay=0x3,
.line=S3C64XX_GPC(3),//這個是片選控制引腳
.set_level=cs_set_level,
};
然後編譯內核下載開發板上,重新啟動過後就能後在/dev下面看到spidev0.0設備文件。
猜想:
寫一個模塊,收到填寫該結構體,然後調用spi_register_board_info()來注冊。我沒有試過,應該是可以的。
5、使用的時候在用戶應用空間中就使用open打開設備文件即可使用。
需要在封裝一次。由於spidev.c僅提供數據接收與發送,但是對於梁茄具體的SPI怎麼發的好像沒有做。
因此我們具體的收發函數應該在此分裝為如下
int fd;
fd=open(device, O_RDWR);
讀函數
輸入:fd文件描述符,addr讀的地址,read_data讀出來數據存放的地址
輸出:成功操作的位元組數,這個沒有做好,需要改
unsigned char read_reg(int fd,unsigned char addr,unsigned char *read_data)
{
int ret=0;
addr=addr<<1;
addr=addr|0x80;
ret=write(fd,&addr,sizeof(unsigned char));
ret|=read(fd,read_data,sizeof(unsigned char));
return ret;
}
寫函數
unsigned char write_reg(int fd,unsigned char addr,unsigned data)
{
int ret=0;
unsigned char buff[2]={0};
buff[0]=addr<<1;
buff[0]=buff[0]&0x7f;
buff[1]=data;
ret=write(fd,&buff,sizeof(buff));
return ret;
}
然後其他具體操作看我們的實際需要了,以上兩個就可以正確讀寫了,你可以先用讀函數讀取設備各個寄存器的默認值,來觀察讀取是否正確。
Ⅲ linux驅動調用spi標准函數spi_sync發送速率慢的問題
/*這是一個簡單的用戶程序與驅動交互的常式*/
void main(void)
{
int testdev;
int i;
char buf[10];
/* 這里是用的open系統調用,是linux內核介面函數,不是庫亮余燃函數,返回fd,詳細請google ,這個open最終會調用驅動中的open函數(代碼流程是這樣的open()->sys_open()->filp_open()->dentry_open()->驅動open)*/
testdev=open("/dev/test",O_RDWR);
if(testdev==-1)
{
printf("Cann'topenfile...../n");
exit(0);
}
printf("buf=0x%x/n",buf);
/*下面的readwrite和ioctl是用戶程序和內核驅動的最直接的交互方式*/
read(testdev,buf,10);
write(testdev,buf,1);
led_ctl.port='G';
led_ctl.bit=5;
led_ctl.value=0;敬虛毀搜
ioctl(testdev,GPIO_IO_SET_GPG,&led_ctl);
printf("%s",buf);
pause();
close(testdev);
Ⅳ linux spi 應用程序。
你所指的spidev.c是SPI的用戶模式設備介面的驅動,可以通過應用程序去操作/dev/spidev*達到與硬體設備的SPI通信,對於操作SPI NOR FLASH,更多是注冊為MTD設備,詳細可參考drivers/mtd/device/m25p80.c,裡面已經有相關實現。
但無論如何,前提是你的內核里已經有SPI控制器的驅動,否則如何通信呢。代碼一般在drivers/spi/里。
那是應該是給spi設備驅動範本吧,可以籍此寫自己的spi設備驅動,沒有設備節點就自己創建個嘛。或者在驅動中添加創建設備節點的函數。
Ⅳ linux下的SPI使用方法是怎樣的
如果linux中已經提供了驅動,並且在/dev/目錄下已經提供了相應的設備文件節點。那麼可以和串口一樣直接打開設置讀寫。如果內核中有驅動,但是沒有生成設備文件節點,那麼只要知道設備的主次設備號,可以使用mknode建立設備文件節點,然後直接來使用。如果沒有驅動就需要自己添加設備驅動了。這個也分兩種情況,看你外設怎麼和你的板子連接的。如果接到板子上的spi控制器上,可以直接編寫通過控制器來控制外設的驅動,這種情況一般生產主控晶元的廠家都已經提供了驅動。如果沒有接到spi控制器上,而是通過gpio連接的外設,你編寫的驅動就需要自己來模擬spi協議來控制外設。
Ⅵ Linux SPI通過設備樹文件添加設備
如上DTS文件片段,SPI Device 節點必須定汪敏慎義在 SPI Master 節點拿肢下,其中 compatible 屬性和 reg 屬性,以上 compatible 屬性用於匹配對應的 Driver 程序,reg 屬性用於指定使用的 SPI Master 的編號,SPI 相關設備樹文件識別見下文講解。
匹困敬配設備樹文件在SPI子系統中有兩個地方:在 spi_register_master() 中匹配和在 device register 時通過內核的通知鏈(notifier_block)來調用設備樹匹配相關程序。
在 device register 時,需配置 CONFIG_OF_DYNAMIC 宏以開啟動態匹配才能夠使用設備樹添加設備,該宏在 menuconfig/Device Drivers/Device Tree and Open Firmware support 中開啟,如下圖:
Ⅶ 14-Linux gpio模擬spi
首先是spidev,要在/dev/下面產生設備文件,需要spidev的支持
使用的是gpio模擬spi,gpio模擬spi的時序原理是bitbang文件實現的,所以這個也需要打開,如果是在openwrt下動態載入的話就是如下兩個配置
如果是直接內核的話是如下兩個
跟I2C的arch層一樣,主要是devices的添加和board_info的添加,如下
對於platform_add_devices,因為是使用spi_gpio,所以name是"spi_gpio"這樣才可以與driver裡面的spi_gpio相互匹配probe到。
因為SPI是可以一個匯流排上面掛多個,然後通過片選腳CS進行硬體切換,所以這變有個num_chipselect需要設置,如果有2個設置就設置2,一個設備就設置1,這邊設置好之後,後面board_info也要有對應的個數,而且片選引腳需要不同。
I2C是通過每個設備有自己不同的地址,通過地址來進行軟體切換。
對於board_info使用的是spidev,drivers/spi/spidev.c文件,該文件的內容是注冊一個spidev驅動。該驅動是一個字元設備驅動。
如果設備與驅動匹配,那麼就會執行spidev_probe()的內容。在spidev_probe()函數中會調用device_create()成功後在 /dev 目錄下就會生成 spidev 相關的設備節點。
這邊有幾個參數要注意:
調試過程想看一些細節的debug信息可以打開內核的動態debug信息,這個在以前的print system裡面有
printk的等級設置成8.
開始
定位到是 spi_gpio_request 的時候報錯
後仿橘者面就將zkernel/3.10.49/arch/mips/mtk/ziroom/zrmt7628.c裡面GPIO的信息調整下, 因為SPI的引腳和LED的引腳號一樣 ,內核不知道哪裡會檢測到。
修改後列印備薯如下:
之後在/dev/下面就生成了spidev1.0的設備
有了/dev/spidev1.0設備之後,就可以在應用成操作改設備收發數據。
在drivers/spi/spidev.c裡面已經封裝好了ioctl的對應介面,根據這些伍禪介面就可以測試使用。
在Documentation/spi/spidev_test.c下面有個應用層的實例,打開看下就清除了。
$(cc) spidev_test.c -o spidev_test生成可執行文件spidev_test
然後拷貝到板子上,將MOSI和MISO短接就可以測試回環數據是否正常。
有邏輯分析儀的接上logic看波形就更加直觀。
gpio模擬SPI:
https://blog.csdn.net/luckywang1103/article/details/70145870
在ARM Linux下使用GPIO模擬SPI時序詳解:
https://blog.csdn.net/yangzheng_yz/article/details/50470577
linux SPI驅動:
https://www.cnblogs.com/xuyh/category/903809.html
Ⅷ 我現在已經把Linux自帶的SPI驅動移植成功了!上層的應用程序如何調用SPI驅動
操作SPI建立的節點文件即可
Ⅸ linux spi應用程序中如何設置片選比如說就是linux自帶的spidev_test.c這個應用,我怎麼設片選
spidev就決定了cs
Ⅹ linux下spi驅動里的spi_write_then_read函數該怎麼使用
水平不行,不一定對,僅供參考哈。
如果只是從AD里讀數據的話,用spi_read就可以了,定義一個8位的緩沖區和一個16位的緩沖區。然後把讀到的2個8bit的數據組合成1個16bit的數據。每次讀到的數據量通過該函數的參數設定。
如果是想實現全雙工,可以使用spi_write_then_read
讀是一樣的,寫的話自己先把16位數據轉換成2個8bit的數據,存放在一個8bit的緩沖區,作為該函數的參數。