轉(zhuǎn)自http://www.xuebuyuan.com/2055253.html
MCP2515是一SPI轉(zhuǎn)CAN總線的芯片,對于CPU來說,CPU就是主設(shè)備,SPI就是從設(shè)備,所以在內(nèi)核里,MCP2515就是一個SPI設(shè)備,而SPI設(shè)備在內(nèi)核中的結(jié)構(gòu)是對應(yīng)的,是一個spi控制器對應(yīng)一個SPI設(shè)備,也就是一個spi_master對應(yīng)一個spi設(shè)備,而SPI設(shè)備在內(nèi)核中,尤其是新的內(nèi)核中(新的內(nèi)核越來越注重分層和分離的結(jié)構(gòu)),則是在驅(qū)動中填充spi_driver驅(qū)動信息,在板載中填充spi_board_info信息.
要移植好SPI設(shè)備,有幾點是要注意的.
1,make menuconfig中,CONFIG_SPI_S3C54XX和SPI_SPIDEV這兩個及其相關(guān)的選項需要打開,因為第一個是spi控制器(驅(qū)動在dev-spi.c里),第二個就是SPI設(shè)備.
2,當然作為主角的MCP251x.c的驅(qū)動選項頁當然要打開,內(nèi)核中,MCP251X.C這個源碼已經(jīng)包含,在drivers/net/can下,檢查下Makefile和Kconfig,然后menuconfig里打開編譯選項,這一步大概也不會有什么問題.唯一要注意的是在此源碼中,需要改一下DEVICE_NAME這個宏,要跟下面提到的modalias一致,因為這是用來match用的.
3,SPI控制器好了,SPI設(shè)備驅(qū)動有了,那就還差的是SPI控制器配置,SPI的設(shè)備信息等的填充了.在/arch/arm/mach-exynos/下的machine_init函數(shù)所在源碼文件中添加填充
static struct s3c64xx_spi_csinfo spi0_csi[]=//這個結(jié)構(gòu)體用來設(shè)置片選引腳的{[0] = {.line = //片選引腳.set_level = gpio_set_value,.fb_delay = 0x2,},};static struct mcp251x_platform_data mcp251x_info//這個結(jié)構(gòu)體用來設(shè)置振蕩器頻率的,至于剩下的參數(shù)要不要設(shè),需要具體看原理圖的接線情況,頭文件在///include/linux/can/platform/mcp251x.hstatic struct spi_board_info spi0_board_info[]=//這個結(jié)構(gòu)體用來配置SPI設(shè)備,也就是對應(yīng)MCP251X.c這個設(shè)備驅(qū)動用的,注意modalias要對上.{.modalias = ,//要跟mcp251x.c上的DEVICE_NAME宏對上.max_speed_hz = ,//CPU支持最高50MHz,但MCP2515芯片最高只支持到10MHZ,這里要好好權(quán)衡一下.bus_num = ,//SPI總線的選擇,CPU提供3條SPI總線.chip_select = ,//SPI總線上第幾個設(shè)備的選擇.mode = SPI_MODE_0,//關(guān)于CPOL CPHA這2個值得選擇,有4種模式 00 01 10 11.platform_data = &mcp251x_info,//傳給mcp251x.c驅(qū)動用的參數(shù),就是上面的一個結(jié)構(gòu)體..controller_data = &spi0_csi[0],//上面的一結(jié)構(gòu)體,片選所用.irq = ,//mcp2515芯片有一中斷腳連到CPU,把復用后的中斷量復制在此}
這三個結(jié)構(gòu)體填充完后(記得加上相應(yīng)的頭文件),就在static struct platform_device上添加初始化用的設(shè)備的變量exynos_device_spi的地址,這是給machine_init函數(shù)在添加這三個變量的時候用的,
struct clk *sclk = NULL;struct clk *PRnt = NULL;struct device *spi0_dev = &exynos_device_spi0.dev;sclk = clk_get(spi0_dev, "dout_spi0");if (IS_ERR(sclk))dev_err(spi0_dev, "failed to get sclk for SPI-0/n");prnt = clk_get(spi0_dev, "mout_mpll_user");if (IS_ERR(prnt))dev_err(spi0_dev, "failed to get prnt/n");if (clk_set_parent(sclk, prnt))printk(KERN_ERR "Unable to set parent %s of clock %s./n",prnt->name, sclk->name);
clk_set_rate(sclk, 10 * 1000 * 1000);clk_put(sclk);clk_put(prnt);
if (!gpio_request(片選引腳宏地址, 片選引腳名)) {gpio_direction_output(片選引腳宏地址, 1);s3c_gpio_cfgpin(片選引腳宏地址, S3C_GPIO_SFN(1));s3c_gpio_setpull(片選引腳宏地址, S3C_GPIO_PULL_UP);exynos_spi_set_info(0, EXYNOS_SPI_SRCCLK_SCLK,ARRAY_SIZE(spi0_csi));}spi_register_board_info(spi0_board_info, ARRAY_SIZE(spi0_board_info));
而這里主要是注冊SPI設(shè)備和SPI的時鐘配置,配置好這些后正常的話就已經(jīng)把mcp2515的can0設(shè)備驅(qū)動移植好了.如果在這里出了問題,不防先設(shè)置好spidev.c的驅(qū)動,先調(diào)好spi的控制器,再把spidev替換成mcp2515.
4,CAN總線在新版本的內(nèi)核中,并不是以字符設(shè)備的形式出現(xiàn)的,原因內(nèi)核也有說明,主要是因為內(nèi)核把CAN設(shè)備看成了網(wǎng)絡(luò)設(shè)備(當然由于CAN設(shè)備的特殊性,CAN是沒有IP地址可言的),需要用到socketcan協(xié)議,所以要想運行CAN總線,那么就要再menuconfig上打開can的協(xié)議(打開項在Networking support-->CAN bus subsystem support下).
5,內(nèi)核部分完成后,就到Android部分了,由于不是字符設(shè)備,不能對其進行簡單的讀寫操作,所以要用到2個工具,iproute2 和 canutiliproute2在安卓源碼上就有,external/iproute2,而canutil則在網(wǎng)上可以下到,而是用canutil內(nèi)的命令,還需要用到libsocketcan的庫.
調(diào)試總結(jié):在剛開始調(diào)試的時候,spi在內(nèi)核中的框架并不熟悉,困惑于spidev.c和mcp251x.c之間的關(guān)系怎么處理,spi的設(shè)備怎么設(shè)置時鐘,為什么mcp251x.c驅(qū)動調(diào)出來之后再spi下的目錄里沒有mcp251x的字符設(shè)備可供調(diào)用等等.其實spidev跟mcp251x是處于同一位置的spi設(shè)備,都由spi控制器控制,或許是可以在spi0_board_info結(jié)構(gòu)體填充chip_select的時候填上排序的序號,可是最后沒有用上,因為spidev不是一個實質(zhì)的設(shè)備.而spi下沒有mc251x的字符設(shè)備供調(diào)用是因為mcp251x的驅(qū)動節(jié)點在net/can0里,意味著內(nèi)核把它注冊為網(wǎng)絡(luò)設(shè)備.這里在調(diào)試的時候最好還是先用spidev來先調(diào)好spi控制器,因為spidev的驅(qū)動提供了可調(diào)用的 spi下的字符設(shè)備節(jié)點,而在內(nèi)核中,已經(jīng)提供了spi設(shè)備的測試代碼在document/spi下,在編譯好后放到開發(fā)板上,并將spi發(fā)送接收的2條線接上,那么正常的情況下spi就能實現(xiàn)自收自發(fā),這時再去調(diào)試mcp251x.c的驅(qū)動,就可以不用擔心spi在系統(tǒng)上出太大問題了(不過關(guān)于時鐘這一部分,需要好好地配置).然后再測試can接口的時候,iproute2這個工具出現(xiàn)過bitrate這個參數(shù)無法辨認的情況,其實是在iproute2/ip目錄下對iplink_can.c并沒有實際調(diào)用,歸根到底,是在編譯android的時候,某些iplink_can.c內(nèi)某些頭文件沒有順利調(diào)用導致最后ip命令的參數(shù)不支持can,最后吧頭文件的include寫成了相對地址來調(diào)用,就可以了.而對于canutil這個工具,要順利編譯好,也經(jīng)過了一些波折,自己用的編譯器比較多,環(huán)境變量不全,是個挺麻煩的問題,最后自己添加了環(huán)境變量,同時無視了伯克利相關(guān)的庫后,勉強編譯成功了cansend candump canecho和cansequence四個工具去調(diào)用.現(xiàn)在,使用ip link set can0 type can bitrate xxx這些命令來設(shè)置波特率,用cansend和candump來發(fā)送接收,能用示波器看到波形了,但是數(shù)據(jù)在接收那邊還沒能出來,這個在之后得后續(xù)更新原因.
6、本文主要驗證Linux-imx_share/Documentation/spi目錄下spidev_test.c的測試例程,能否正常控制SPI接口。在命令行下輸入ifconfig -a,已經(jīng)出現(xiàn)can0信息

新聞熱點
疑難解答