微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > 嵌入式系统设计讨论 > spi驱动调试(mtk平台移植)

spi驱动调试(mtk平台移植)

时间:10-02 整理:3721RD 点击:
上一篇帖子讲i2c的东西,说实话一个呼吸灯的东西真的没什么好讲,本来调通了之后发几张图一起高潮一下,然而发现并没有什么卵用,基本留出了测试点,后续的东西都差不多。如果有同学这面有什么问题加我好友咱们私下沟通,在3399上面调通了协议,后面有点不想搞了,因为着急想玩安卓7.0,最近也在下载源码,编译什么的又搞了很久,也没搞出什么名堂(心累),然后在联发科的mt6735平台实验了一下(想要源码的私信我)。





接下来准备搞spi了。其实我也好想搞摄像头,然而我这个焊工,飞线非死不可。我看还几个同学和我说这个板子支持几路摄像头,我也挺想试试的,别急。稳一稳(现在手头上工作也比较急,等有时间了拿出来单独玩耍一下)。
书归正传,咱们开始说spi吧,我看到了rk3399里讲的通过设备树添加设备到内核中,当然设备树是可行的,但是wiki里面讲的比较全(其实坑很多的),我就不用那种方法了。

  1. int assist_spi_lcd_module_init(void)
  2. {
  3. //    struct device *dev;
  4.         pr_info("assist_spi_lcd_module_init\n");

  5.         spi_register_board_info(st7789v_spi_board_devs, ARRAY_SIZE(st7789v_spi_board_devs));

  6.         spi_register_driver(&st7789v_spi_driver_l);
  7.         //spi_register_driver(&st7789v_spi_driver_r);
  8.        

  9.         st7789v_add_fs();
  10.         return 0;
  11. }

  12. void  assist_spi_lcd_module_exit(void)
  13. {
  14.         pr_info("assist_spi_lcd_module_exit sure\n");

  15.         spi_unregister_driver(&st7789v_spi_driver_l);
  16.         //spi_unregister_driver(&st7789v_spi_driver_r);
  17.         st7789v_del_fs();
  18.         st7789v_free_buffer();
  19.         st7789v_power_down();
  20.         st7789v_gpio_exit();
  21.        
  22. }

  23. module_init(assist_spi_lcd_module_init);
  24. module_exit(assist_spi_lcd_module_exit);

复制代码

老规矩还是注册出口和入口,入口是加载这个驱动模块时被运行的代码,然后呢,我们就要看init函数里面了,我们使用spi_register_board_info函数来注册设备到内核,如果你使用设备树dts可以省略这一步,然后,注册spi的驱动

  1. static struct spi_board_info st7789v_spi_board_devs[] __initdata = {
  2.         [0] = {
  3.         .modalias = "st7789v_l",
  4. #if 1
  5.         .max_speed_hz = 50 *1000 * 1000,//50 * 1000 *1000,  // 25MHz
  6. #else       
  7.         .max_speed_hz = 56 * 1000 *1000,  // MAX 27MHz  
  8. #endif
  9.         .bus_num = 0,
  10.         .chip_select = 0,
  11.         .mode = SPI_MODE_3,
  12. #if 0          
  13.         .irq             = 3,
  14. #endif               
  15.         },
  16. };

  17. struct spi_device_id spi_id_7789_table = { "st7789v_l", 0 };

  18. static struct spi_driver st7789v_spi_driver_l = {
  19.         .driver = {
  20.                 .name        = "st7789v_l",
  21.                 .bus    = &spi_bus_type,
  22.                 .owner        = THIS_MODULE,
  23.         },
  24.         .probe                = st7789v_spi_probe_l,
  25.         .remove                = st7789v_spi_remove,
  26.         .id_table = &spi_id_7789_table,
  27. };

复制代码

驱动和设备名字相同,或者id_table里面搞一个和设备名字一样的,如果你使用的是设备树,要完成driver成员的of_match_table,把名字和设备树中的compatible相同就可以了,注册完设备之后,如果设备和驱动匹配没有问题呢,就会进入probe函数了。

  1. static int  st7789v_spi_probe_l(struct spi_device *spi)
  2. {
  3.         int ret = 0;
  4.         //int set_bl;
  5.         assist_lcd_spi_device_l = *spi;
  6.         printk("st7789v_spi_probe_l  st7789v_max_speed %d"
  7.                 ,spi->max_speed_hz);
  8.         printk("chip_select %d--master %d\n",spi->chip_select,spi->master->bus_num);// bits_per_word %s mode %u
  9.         printk("bits_per_word %d---mode %d\n",spi->bits_per_word,spi->mode);
  10.         printk("bits_per_word %d---mode %d\n",assist_lcd_spi_device_l.bits_per_word,assist_lcd_spi_device_l.mode);       
  11.         memset(&assist_lcd_info, 0, sizeof(assist_lcd_info_t));
  12.         assist_lcd_info.dev_l = &spi->dev;
  13.         SPI_Init(&assist_lcd_spi_device_l);

  14.         #if USED_FORE_LINE_8BIT_MODE
  15.                 ret = gpio_request(SPI_MISO_PIN,"SPI_LCD_MISO_WR");
  16.                 if(ret < 0){
  17.                         printk("gpio quest fail %d \n",SPI_MISO_PIN);
  18.                         return -1;
  19.                 }
  20.                 gpio_direction_output(SPI_MISO_PIN, 1);
  21.         #endif

  22.         ret = gpio_request(LCD_CS_R_PIN,"LCD_CS_R_PIN");
  23.         if(ret < 0){
  24.                 printk("gpio quest fail %d \n",LCD_CS_R_PIN);
  25.                 return -1;
  26.         }
  27.         gpio_direction_output(LCD_CS_R_PIN, 1);

  28.         ret = gpio_request(LCD_CS_L_PIN,"LCD_CS_L_PIN");
  29.         if(ret < 0){
  30.                 printk("gpio quest fail %d \n",LCD_CS_L_PIN);
  31.                 return -1;
  32.         }

  33.         gpio_direction_output(LCD_CS_L_PIN, 1);

  34.         ret = gpio_request(LCD_RST_PIN,"SPI_LCD_RST");
  35.         if(ret < 0){
  36.                 printk("LCD_RST_PIN gpio quest fail %d \n",LCD_RST_PIN);
  37.                 return -1;
  38.         }
  39.         gpio_direction_output(LCD_RST_PIN, 1);

  40.         ret = gpio_request(LCD_BL_PIN,"SPI_LCD_BL");
  41.         if(ret < 0){
  42.                 printk("gpio quest fail %d \n",LCD_BL_PIN);
  43.                 return -1;
  44.         }

  45.         gpio_direction_output(LCD_BL_PIN, 0);

  46.         ret = gpio_request(GPIO_RESVE3,"GPIO_RESVE3");
  47.         if(ret < 0){
  48.                 printk("gpio quest fail %d \n",GPIO_RESVE3);
  49.                 return -1;}
  50. }

复制代码

probe函数里面最重要的事情莫过于注册对应的gpio和初始化spi总线,spi是不需要设备就可以实现波形的输出的,这就很开心不用费事去连接种种麻烦的线(不过我还是给从设备的线都引出来了)。其实我一点都不想讲硬件原理,因为我硬件水一匹,作为一个驱动工程师,我都不好意思说哈哈,算了,继续。不同平台的优先级是不一样的,有的在注册设备的时候直接就有默认配置,dts里面也会默认的配置,可以不配置就直接用(部分平台哈),在全志和mtk平台dts的优先级非常低,rk3399我没有用dts也是有这个因素的,然后在probe中除了配置gpio意外,要初始化一些东西,像上升下降沿的触发和保持时间

  1. static int SPI_Init(struct spi_device *db)
  2. {
  3.         struct mt_chip_conf* spi_par; // added 2015-12-3
  4.     spi_par = (struct mt_chip_conf *) db->controller_data;
  5.         spi_par->setuptime = 15;//20;//15;
  6.         spi_par->holdtime = 15;// 20;
  7.         spi_par->high_time = 2; //  500     //10--6m   15--4m   20--3m  30--2m  [ 60--1m 120--0.5m  300--0.2m]
  8.         spi_par->low_time = 2;  //500
  9.         spi_par->cs_idletime = 20; //20
  10.         spi_par->rx_mlsb = 1;
  11.         spi_par->tx_mlsb = 1;                 
  12.         spi_par->tx_endian = 0;
  13.         spi_par->rx_endian = 0;
  14.         spi_par->cpol = 0;
  15.         spi_par->cpha = 0;
  16.         spi_par->com_mod = DMA_TRANSFER;
  17.         spi_par->pause = 0;
  18.         spi_par->finish_intr = 1;
  19.         spi_par->deassert = 0;
  20.         spi_setup(db);
  21.         return 0;
  22. }

复制代码

high_time,low_time决定了他的频率,我感觉这样设置要比单纯设置频率稳定的多(毕竟我啥也不懂,多设置点东西总是没错的)。然后写个大概的测试程序,不听的刷一个固定数据。


看一下 波形,这个频率设置的低一些,方便示波器抓。下面是数据,上面是时钟脚的波形,先这样,有后续想调试spi的同学欢迎沟通交流哈


学习学习

给你个赞

谢谢大水逼。哈哈

这是在用spi的接口来做pwm吗,还是说用spi通信

这是在用spi的接口来做pwm吗,还是说用spi通信

当时用gpio来模拟pwm,死活没弄出来,各种调度延时

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top