目录

  • 一、步骤
  • 二、修改设备树
  • 三、编写驱动代码
    • 1、引脚连线
    • 2、编写Makefile文件
    • 3、编写驱动
  • 四、编写驱动测试代码
  • 五、测试

小屏幕:

  • 240x240分辨率
  • 1.3inch大

效果图:

一、步骤

  • 修改设备树
  • 编译出.dtb文件
  • 通过网络更新开发板上的设备树文件
  • 编写驱动
  • 编译出.ko文件
  • 编写驱动测试文件
  • 编译出驱动测试可执行文件
  • 小屏幕正确插线
  • 安装驱动模块.ko–小屏幕刷屏
  • 测试驱动测试可执行文件
  • 完成

二、修改设备树

在imx6ull-alientek-emmc.dts上添加:

//增加引脚控制节点
/{ // 根节点...... // 其他代码ipsRes {#address-cells = <1>;#size-cells = <1>;compatible = "liefyuan-ipsRes";pinctrl-names = "default";pinctrl-0 = <&pinctrl_ipsRes>;res-gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;status = "okay";};ipsDc {#address-cells = <1>;#size-cells = <1>;compatible = "liefyuan-ipsDc";pinctrl-names = "default";pinctrl-0 = <&pinctrl_ipsDc>;dc-gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;status = "okay";};...... // 其他代码};
//功能引脚节点
&iomuxc {pinctrl-names = "default";pinctrl-0 = <&pinctrl_hog_1>;......//其他代码pinctrl_ipsRes: ipsRes {    //屏幕复位u引脚fsl,pins = <MX6UL_PAD_GPIO1_IO01__GPIO1_IO01        0x10B0 /* LED0 */>;};  pinctrl_ipsDc: ipsDc {      //屏幕dc(data or command)u引脚fsl,pins = <MX6UL_PAD_GPIO1_IO04__GPIO1_IO04        0x10B0 >;};......//其他代码};//节点追加内容
&ecspi3 {fsl,spi-num-chipselects = <1>;cs-gpio = <&gpio1 20 GPIO_ACTIVE_LOW>; /* cant't use cs-gpios! */pinctrl-names = "default";pinctrl-0 = <&pinctrl_ecspi3>;status = "okay";spidev: ipsTft@0 {compatible = "alientek,ipsTft";spi-max-frequency = <1000000000>;reg = <0>;};
};

查看imx6ull.dtsi文件可以看到这个节点:

/ {......//其他代码soc {#address-cells = <1>;#size-cells = <1>;compatible = "simple-bus";interrupt-parent = <&gpc>;ranges;......//其他代码aips1: aips-bus@02000000 {compatible = "fsl,aips-bus", "simple-bus";#address-cells = <1>;#size-cells = <1>;reg = <0x02000000 0x100000>;ranges;spba-bus@02000000 {compatible = "fsl,spba-bus", "simple-bus";#address-cells = <1>;#size-cells = <1>;reg = <0x02000000 0x40000>;ranges;......//其他代码ecspi3: ecspi@02010000 {#address-cells = <1>;#size-cells = <0>;compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";reg = <0x02010000 0x4000>;interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clks IMX6UL_CLK_ECSPI3>,<&clks IMX6UL_CLK_ECSPI3>;clock-names = "ipg", "per";dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;dma-names = "rx", "tx";status = "disabled";};};};};
};

因此要想从开发板上看到这个节点就得:

/sys/firmware/devicetree/base/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02010000 # ls
#address-cells           dma-names                pinctrl-0
#size-cells              dmas                     pinctrl-names
clock-names              fsl,spi-num-chipselects  reg
clocks                   interrupts               status
compatible               ipsTft@0
cs-gpio                  name

三、编写驱动代码

1、引脚连线

因此引脚连线:

TFT屏 Mini板外接IO口 描述
GND GND
VCC 3.3V
SCL 20 UART2_CTR
SDA 18 UART2_RXD
RES 07 GPIO 1
DC 10 GPIO 4
BLK NC NC

2、编写Makefile文件

Makefile

KERNELDIR := /home/liefyuan/linux/project_drivers/kernelCURRENT_PATH := $(shell pwd)obj-m := tft.obuild : kernel_moduleskernel_modules: $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean: $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

3、编写驱动

tft.c

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/spi/spi.h> #define ipsTft_CNT 1
#define ipsTft_NAME "ipsTft" #define LCD_W 240
#define LCD_H 240 #define WHITE              0xFFFF
#define BLACK            0x0000
#define BLUE             0x001F
#define BRED             0XF81F
#define GRED             0XFFE0
#define GBLUE            0X07FF
#define RED              0xF800
#define MAGENTA          0xF81F
#define GREEN            0x07E0
#define CYAN             0x7FFF
#define YELLOW           0xFFE0
#define BROWN            0XBC40
#define BRRED            0XFC07
#define GRAY             0X8430  u8 buf[9] = { RED, GREEN, BLUE, WHITE, BLACK, YELLOW, GRAY, BRRED, CYAN
}; struct ipsTft_dev { dev_t devid;             /* 设备号 */ struct cdev cdev;         /* cdev */ struct class *class;     /* 类 */ struct device *device;      /* 设备 */ struct device_node *nd;    /* 设备节点 */ int major;                   /* 主设备号 */ void *private_data;          /* 私有数据 */ int dc_gpio;             /* 片选所使用的GPIO编号 */ int res_gpio;               /* ips屏幕复位引脚 */ int cs_gpio;                /* 共用磁力计的cs */
}; static struct ipsTft_dev ipsTftdev; void ipsTft_reginit(struct ipsTft_dev *dev); //1.3寸屏幕
struct spi_lcd_cmd { u8  reg_addr;  // command u8  len;       //需要从spi_lcd_datas数组里发出数据字节数 int delay_ms;  //此命令发送数据完成后,需延时多久
} spi_lcd_cmd_t;struct spi_lcd_cmd_t cmds[] = { {0x36, 1, 30}, {0x3A, 1, 30}, {0xB2, 5, 30}, {0xB7, 1, 30}, {0xBB, 1, 30}, {0xC0, 1, 30}, {0xC2, 1, 30}, {0xC3, 1, 30}, {0xC4, 1, 30}, {0xC6, 1, 30}, {0xD0, 2, 30}, {0xE0, 14, 30}, {0xE1, 14, 30}, {0x21, 0, 30}, {0x11, 0, 120}, {0x29, 0, 30},
}; u8 spi_lcd_datas[] = { 0x00, 0x05, 0x0c,0x0c,0x00,0x33,0x33, 0x35, 0x19, 0x2c, 0x01, 0x12, 0x20, 0x0F, 0xA4,0xA1, 0xD0,0x04,0x0D,0x11,0x13,0x2B,0x3F,0x54,0x4C,0x18,0x0D,0x0B,0x1F,0x23, 0xD0,0x04,0x0C,0x11,0x13,0x2C,0x3F,0x44,0x51,0x2F,0x1F,0x1F,0x20,0x23
};
/* * @description  : 向ipsTft多个寄存器写入数据 * @param - dev:  ipsTft设备 * @param - reg:  要写入的寄存器首地址 * @param - val:  要写入的数据缓冲区 * @param - len:  要写入的数据长度 * @return      :   操作结果 */
static s32 ipsTft_write_regs(struct ipsTft_dev *dev,u8 *buf, u8 len)
{ int ret; struct spi_message m; struct spi_transfer *t; struct spi_device *spi = (struct spi_device *)dev->private_data; t = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);    /* 申请内存 */ t->tx_buf = buf;         /* 要写入的数据 */ t->len = len;              /* 写入的字节数 */ spi_message_init(&m);      /* 初始化spi_message */ spi_message_add_tail(t, &m);/* 将spi_transfer添加到spi_message队列 */ ret = spi_sync(spi, &m);  /* 同步发送 */ kfree(t);                    /* 释放内存 */ return ret;
}
/* * @description  : 向ipsTft指定寄存器写入指定的值,写一个寄存器 * @param - dev:  ipsTft设备 * @param - reg:  要写的寄存器 * @param - data: 要写入的值 * @return   :    无 */
static void ipsTft_write_onereg(struct ipsTft_dev *dev, u8 buf)
{ ipsTft_write_regs(dev,&buf, 1); //spi_write(dev,&buf, 1);
}
/* funciton: 写一个命令
*/
void write_command(struct ipsTft_dev *dev, u8 cmd)
{ // dc , command:0 gpio_set_value(dev->dc_gpio, 0); ipsTft_write_onereg(dev,cmd);
}
/* funciton: 写一个数据
*/
void write_data(struct ipsTft_dev *dev, u8 data)
{ gpio_set_value(dev->dc_gpio, 1); ipsTft_write_onereg(dev,data);
}
/* funciton: 写一些数据
*/
static void write_datas(struct ipsTft_dev *dev, int data,int len)
{ gpio_set_value(dev->dc_gpio, 1); ipsTft_write_regs(dev,(u8 *)&data,len);
}
/* * @description      : 打开设备 * @param - inode    : 传递给驱动的inode * @param - filp  : 设备文件,file结构体有个叫做private_data的私有成员变量 *                    一般在open的时候将private_data向私有设备结构体赋值。 * @return             : 0 成功;其他 失败 */
static int ipsTft_open(struct inode *inode, struct file *filp)
{ filp->private_data = &ipsTftdev; /* 设置私有数据 */ // TODO somethingreturn 0;
}
/* * @description      : 关闭/释放设备 * @param - filp  : 要关闭的设备文件(文件描述符) * @return            : 0 成功;其他 失败 */
static int ipsTft_release(struct inode *inode, struct file *filp)
{ return 0;
}
/* ipsTft操作函数 */
static const struct file_operations ipsTft_ops = { .owner = THIS_MODULE, .open = ipsTft_open, .release = ipsTft_release,
}; void Address_set(struct ipsTft_dev *dev,unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)
{ write_command(dev,0x2a); write_data(dev,x1>>8); write_data(dev,x1); write_data(dev,x2>>8); write_data(dev,x2); write_command(dev,0x2b); write_data(dev,y1>>8); write_data(dev,y1); write_data(dev,y2>>8); write_data(dev,y2); write_command(dev,0x2C);
}
/* 刷屏函数
*/
void LCD_Clear(struct ipsTft_dev *dev,u16 Color)
{ u16 i,j; Address_set(dev,0,0,LCD_W-1,LCD_H-1); write_command(dev,0x2C); for(i=0;i<LCD_W;i++) { for (j=0;j<LCD_H;j++) { //write_datas(dev,0xF800,2);       //全红 write_data(dev,Color>>8); write_data(dev,Color); } }
}
/* * ipsTft内部寄存器初始化函数 * @param     : 无 * @return  : 无 */
void ipsTft_reginit(struct ipsTft_dev *dev)
{ int i, j, n; gpio_set_value(ipsTftdev.res_gpio, 0); mdelay(20); gpio_set_value(ipsTftdev.res_gpio, 1); mdelay(20); n = 0; // n用于记录数据数组spi_lcd_datas的位置 //发命令,并发出命令所需的数据 for (i = 0; i < ARRAY_SIZE(cmds); i++) //命令 { write_command(dev, cmds[i].reg_addr); for (j = 0; j < cmds[i].len; j++) //发出命令后,需要发出的数据 if(cmds[i].len!=0) write_data(dev, spi_lcd_datas[n++]); if (cmds[i].delay_ms) //如有延时则延时 mdelay(cmds[i].delay_ms); } n=0; LCD_Clear(dev,RED); // 安装驱动模块的时候刷个红色的屏printk("ips init finish!\n");
} /* * @description     : spi驱动的probe函数,当驱动与 *                    设备匹配以后此函数就会执行 * @param - client  : spi设备 * @param - id      : spi设备ID * */
static int ipsTft_probe(struct spi_device *spi)
{ int ret = 0; /* 1、构建设备号 */ if (ipsTftdev.major) { ipsTftdev.devid = MKDEV(ipsTftdev.major, 0); register_chrdev_region(ipsTftdev.devid, ipsTft_CNT, ipsTft_NAME); } else { alloc_chrdev_region(&ipsTftdev.devid, 0, ipsTft_CNT, ipsTft_NAME); ipsTftdev.major = MAJOR(ipsTftdev.devid); } /* 2、注册设备 */ cdev_init(&ipsTftdev.cdev, &ipsTft_ops); cdev_add(&ipsTftdev.cdev, ipsTftdev.devid, ipsTft_CNT); /* 3、创建类 */ ipsTftdev.class = class_create(THIS_MODULE, ipsTft_NAME); if (IS_ERR(ipsTftdev.class)) { return PTR_ERR(ipsTftdev.class); } /* 4、创建设备 */ ipsTftdev.device = device_create(ipsTftdev.class, NULL, ipsTftdev.devid, NULL, ipsTft_NAME); if (IS_ERR(ipsTftdev.device)) { return PTR_ERR(ipsTftdev.device); } /* 获取设备树中的spi3外设节点 -- 查询imx6ull.dtsi设备树头文件文件*/ipsTftdev.nd = of_find_node_by_path("/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02010000"); if(ipsTftdev.nd == NULL) { printk("ecspi3 node not find!\r\n"); return -EINVAL; } /* 获取设备树中的gpio属性 */ /* 获取设备树中CS信号节点 */ ipsTftdev.cs_gpio = of_get_named_gpio(ipsTftdev.nd, "cs-gpio", 0); if(ipsTftdev.cs_gpio < 0) { printk("can't get cs-gpio"); return -EINVAL; } /* 获取设备树中RES复位信号节点 */ ipsTftdev.nd = of_find_node_by_path("/ipsRes"); if(ipsTftdev.nd == NULL) { printk("res-gpio node not find!\r\n"); return -EINVAL; } ipsTftdev.res_gpio = of_get_named_gpio(ipsTftdev.nd, "res-gpio", 0); if(ipsTftdev.res_gpio < 0) { printk("can't get res-gpio"); return -EINVAL; } /* 获取设备树中DC数据命令控制信号节点 */ ipsTftdev.nd = of_find_node_by_path("/ipsDc"); if(ipsTftdev.nd == NULL) { printk("ipsDcgpio node not find!\r\n"); return -EINVAL; } ipsTftdev.dc_gpio = of_get_named_gpio(ipsTftdev.nd, "dc-gpio", 0); if(ipsTftdev.dc_gpio < 0) { printk("can't get ipsDc-gpio"); return -EINVAL; } /* 设置GPIO1_IO20为输出,并且输出高电平 */ ret = gpio_direction_output(ipsTftdev.cs_gpio, 1); if(ret < 0) { printk("can't set cs gpio!\r\n"); } ret = gpio_direction_output(ipsTftdev.res_gpio, 1); if(ret < 0) { printk("can't set res gpio!\r\n"); } ret = gpio_direction_output(ipsTftdev.dc_gpio, 1); if(ret < 0) { printk("can't set dc gpio!\r\n"); } /*初始化spi_device */ spi->mode = SPI_MODE_2; /*MODE0,CPOL=0,CPHA=0 */spi_setup(spi); ipsTftdev.private_data = spi; /* 设置私有数据 */ /* 初始化ipsTft内部寄存器 */ ipsTft_reginit(&ipsTftdev); return 0;
}
/* * @description     : spi驱动的remove函数,移除spi驱动的时候此函数会执行 * @param - client  : spi设备 * @return          : 0,成功;其他负值,失败 */
static int ipsTft_remove(struct spi_device *spi)
{ /* 删除设备 */ cdev_del(&ipsTftdev.cdev); unregister_chrdev_region(ipsTftdev.devid, ipsTft_CNT); /* 注销掉类和设备 */ device_destroy(ipsTftdev.class, ipsTftdev.devid); class_destroy(ipsTftdev.class); return 0;
}
/* 传统匹配方式ID列表 */
static const struct spi_device_id ipsTft_id[] = { {"alientek,ipsTft", 0}, {}
};
/* 设备树匹配列表 */
static const struct of_device_id ipsTft_of_match[] = { { .compatible = "alientek,ipsTft" }, { /* Sentinel */ }
};
/* SPI驱动结构体 */
static struct spi_driver ipsTft_driver = { .probe = ipsTft_probe, .remove = ipsTft_remove, .driver = { .owner = THIS_MODULE, .name = "ipsTft", .of_match_table = ipsTft_of_match, }, .id_table = ipsTft_id,
};
/* * @description  : 驱动入口函数 * @param      : 无 * @return      : 无 */
static int __init ipsTft_init(void)
{ return spi_register_driver(&ipsTft_driver);
}
/* * @description  : 驱动出口函数 * @param      : 无 * @return      : 无 */
static void __exit ipsTft_exit(void)
{ spi_unregister_driver(&ipsTft_driver);
}
module_init(ipsTft_init);
module_exit(ipsTft_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("liefyuan");

四、编写驱动测试代码

tftTestApp.c

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/ioctl.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include <poll.h>
#include <sys/select.h>
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
/** @description       : main主程序* @param - argc   : argv数组元素个数* @param - argv    : 具体参数* @return            : 0 成功;其他 失败*/
int main(int argc, char *argv[])
{int fd;char *filename;int ret = 0;if (argc != 2) {printf("Error Usage!\r\n");return -1;}filename = argv[1];fd = open(filename, O_RDWR);if(fd < 0) {printf("can't open file %s\r\n", filename);return -1;}else{printf("open the ips!\n");}close(fd);  /* 关闭文件 */  return 0;
}
/lib/modules/4.1.15/kernel/drivers/tft # ./tftTestApp /dev/ipsTft
open the ips!

五、测试

安装驱动模块:

  • 执行depmod
  • 执行modprobe tft.ko
  • 运行./tftTestApp /dev/ipsTft

安装前:ls /dev

/ # ls /dev
autofs              ram13               tty37
bus                 ram14               tty38
console             ram15               tty39
cpu_dma_latency     ram2                tty4
dri                 ram3                tty40
fb0                 ram4                tty41
full                ram5                tty42
fuse                ram6                tty43
hwrng               ram7                tty44
i2c-0               ram8                tty45
i2c-1               ram9                tty46
iio:device0         random              tty47
input               rfkill              tty48
kmsg                rtc0                tty49
loop-control        snd                 tty5
loop0               tty                 tty50
loop1               tty0                tty51
loop2               tty1                tty52
loop3               tty10               tty53
loop4               tty11               tty54
loop5               tty12               tty55
loop6               tty13               tty56
loop7               tty14               tty57
mem                 tty15               tty58
memory_bandwidth    tty16               tty59
mmcblk1             tty17               tty6
mmcblk1boot0        tty18               tty60
mmcblk1boot1        tty19               tty61
mmcblk1p1           tty2                tty62
mmcblk1p2           tty20               tty63
mmcblk1rpmb         tty21               tty7
mxc_asrc            tty22               tty8
network_latency     tty23               tty9
network_throughput  tty24               ttymxc0
null                tty25               ttymxc2
ppp                 tty26               ubi_ctrl
pps0                tty27               urandom
pps1                tty28               vcs
ptmx                tty29               vcs1
ptp0                tty3                vcsa
ptp1                tty30               vcsa1
pts                 tty31               video0
ram0                tty32               watchdog
ram1                tty33               watchdog0
ram10               tty34               zero
ram11               tty35               ðA-é
ram12               tty36

安装模块:

/lib/modules/4.1.15/kernel/drivers/tft # depmod
/lib/modules/4.1.15/kernel/drivers/tft # modprobe tft.ko
ips init finish!

如果在线插好的情况下,使用modprobe tft.ko之后TFT屏就会刷一次屏,刷屏完成以后就打印出ips init finish!

安装后:ls /dev – 多了一个ipsTft

/ # ls /dev
autofs              ram12               tty36
bus                 ram13               tty37
console             ram14               tty38
cpu_dma_latency     ram15               tty39
dri                 ram2                tty4
fb0                 ram3                tty40
full                ram4                tty41
fuse                ram5                tty42
hwrng               ram6                tty43
i2c-0               ram7                tty44
i2c-1               ram8                tty45
iio:device0         ram9                tty46
input               random              tty47
ipsTft              rfkill              tty48
kmsg                rtc0                tty49
loop-control        snd                 tty5
loop0               tty                 tty50
loop1               tty0                tty51
loop2               tty1                tty52
loop3               tty10               tty53
loop4               tty11               tty54
loop5               tty12               tty55
loop6               tty13               tty56
loop7               tty14               tty57
mem                 tty15               tty58
memory_bandwidth    tty16               tty59
mmcblk1             tty17               tty6
mmcblk1boot0        tty18               tty60
mmcblk1boot1        tty19               tty61
mmcblk1p1           tty2                tty62
mmcblk1p2           tty20               tty63
mmcblk1rpmb         tty21               tty7
mxc_asrc            tty22               tty8
network_latency     tty23               tty9
network_throughput  tty24               ttymxc0
null                tty25               ttymxc2
ppp                 tty26               ubi_ctrl
pps0                tty27               urandom
pps1                tty28               vcs
ptmx                tty29               vcs1
ptp0                tty3                vcsa
ptp1                tty30               vcsa1
pts                 tty31               video0
ram0                tty32               watchdog
ram1                tty33               watchdog0
ram10               tty34               zero
ram11               tty35               ðA-é

如上,出现了节点了就可以进行驱动测试了:

/lib/modules/4.1.15/kernel/drivers/tft # ./tftTestApp /dev/ipsTft
open the ips!

完成基本测试!

常用操作:

  • 将编译出来的.ko文件复制到nfs文件夹下:cp tft.ko /home/liefyuan/linux/nfs/rootfs/lib/modules/4.1.15/kernel/drivers/tft/

增加了一个小功能,当使用命令./tftTestApp /dev/ipsTft时屏幕会刷新蓝绿黑白三种颜色。

static int ipsTft_open(struct inode *inode, struct file *filp)
{ filp->private_data = &ipsTftdev; /* 设置私有数据 */ LCD_Clear(&ipsTftdev,BLUE); mdelay(20);LCD_Clear(&ipsTftdev,GREEN);mdelay(20);LCD_Clear(&ipsTftdev,BLACK);mdelay(20);LCD_Clear(&ipsTftdev,WHITE);return 0;
}

嵌入式Linux--驱动ST7789驱动芯片的TFT屏(一)相关推荐

  1. 嵌入式Linux驱动笔记(二十四)------framebuffer之使用spi-tft屏幕(上)

    你好!这里是风筝的博客, 欢迎和我一起交流. 最近入手了一块spi接口的tft彩屏,想着在我的h3板子上使用framebuffer驱动起来. 我们知道: Linux抽象出FrameBuffer这个设备 ...

  2. 嵌入式Linux驱动大全问世,十年磨一剑,视频!服务!新老客户都有大折扣!

    对于学习嵌入式Linux,韦东山老师整理了三条学习路线,适合与不同阶段的学员. 三条嵌入式学习路线 路线一:单片机路线 使用KEL.HAL库来快速的掌握单片机开发 路线二:深入学习单片机/RTOS/U ...

  3. 华清远见嵌入式Linux驱动开发培训班

    课程背景 开放的 Linux 受到广泛的欢迎,得到越来越多公司的支持,但是阻碍 Linux 在各个领域广泛应用的主要因素就是内核/驱动高端人才极度缺乏,Linux源代码中85%是设备驱动,嵌入式系统中 ...

  4. 嵌入式linux驱动开发之移远4G模块EC800驱动移植指南

    回顾下移远4G模块移植过程, 还是蛮简单的.一通百通,无论是其他4G模块都是一样的.这里记录下过程,分享给有需要的人.环境使用正点原子的imax6ul开发板,板子默认支持中兴和移远EC20的驱动,这里 ...

  5. 嵌入式linux硬件成本,嵌入式Linux驱动和固件有何区别?供应商是如何用固件压缩成本的?...

    原标题:嵌入式Linux驱动和固件有何区别?供应商是如何用固件压缩成本的? 作为一个驱动开发者, 你可能发现你面对一个设备必须在它能支持工作前下载固件到它里面. 硬件市场的许多地方的竞争是如此得强烈, ...

  6. 嵌入式Linux驱动笔记(十八)------浅析V4L2框架之ioctl【转】

    转自:https://blog.csdn.net/Guet_Kite/article/details/78574781 权声明:本文为 风筝 博主原创文章,未经博主允许不得转载!!!!!!谢谢合作 h ...

  7. linux驱动日志格式,( 转)嵌入式Linux驱动Makefile

    天气: 晴朗 心情: 高兴 ( 转)嵌入式Linux驱动开发笔记 1.1        模块的编译 Linux驱动一般以模块module的形式来加载,首先需要把驱动编译成模块的形式.简单的例子, Be ...

  8. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之Pinctrl子系统和GPIO子系统的使用

    文章目录 前言 1.Pinctrl子系统 1.1.为什么有Pinctrl子系统 1.2.重要的概念 1.3.代码中怎么引用pinctrl 2.GPIO子系统 2.1.为什么有GPIO子系统 2.2.在 ...

  9. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之按键驱动框架

    文章目录 前言 1.APP怎么读取按键值 1.1.查询方式 1.2.休眠-唤醒方式 1.3.poll方式 1.3.异步通知方式 1.5. 驱动程序提供能力,不提供策略 2.按键驱动程序框架--查询方式 ...

最新文章

  1. 虚拟化管理的两大棘手之处
  2. git创建本地版本仓库及注意事项
  3. OpenLayers学习笔记2——坐标转换问题
  4. Mysql 索引 总结 —— 概述 || 索引优势劣势|| 索引结构(索引是在MySQL的存储引擎层中实现的)|| BTREE 结构||B+TREE 结构||MySQL中的B+Tree||索引分类
  5. 【读书笔记】练习的心态
  6. linux笔记之 rpm常用参数 ,yum安装编译器,httpd服务的开关
  7. linux cp 时 略过文件,CentOS下执行cp命令式提示略过文件夹
  8. SRAM,SDRAM,网卡
  9. 右值引用、移动构造函数和move
  10. 基于STM32的USB枚举过程学习笔记
  11. 网络安全实验7 防火墙 Iptables应用
  12. java项目实战达内代码_2018最新达内学子商城项目静态页面+sql+java代码
  13. 制作唐诗网页代码_有关于诗词的网页代码
  14. 学习PLC到底要不要买PLC?
  15. setex php,python redis setex可以设value为list或者其他数据结构吗?
  16. multisim变压器反馈式_基于Multisim的电压串联型负反馈电路的仿真与分析
  17. 安卓自定义View进阶-Canvas之图片文字
  18. ioc和aop全称是什么
  19. mysql数据库被勒索删库怎么办
  20. proguard学习

热门文章

  1. 如何给模型加入先验知识?
  2. 中国地质大学计算机学院保研率,2020年中国地质大学(北京)保研率是多少
  3. 华为怎么改输入法皮肤_华为输入法
  4. Mac下安装vim的插件YouCompleteMe及注意事项
  5. java计算机毕业设计网络游戏后台管理系统(附源码、数据库)
  6. 用raptor计算计算机课成绩,RAPTOR程序设计例题参考答案课案
  7. PBFT(拜占庭容错)
  8. 程序员需知的11个在线教程网站,建议收藏!
  9. 23个经过时间考验的应用程序,可以管理您的远程软件开发团队
  10. python学习-109-多个CSV文件的合并