1 常用linux驱动函数
//网络
// dma传输
//1申请一个DMA channel
dma_request_channel(mask, sata_dwc_dma_filter, hsdevp);
//2根据设备(slave)的特性,配置DMA channel的参数
int dmaengine_slave_config(struct dma_chan *chan, struct dma_slave_config *config)
//3 初始化一个DMA传输描述符
desc=dmaengine_prep_xxx()
//4 将本次传输(transaction)提交给dmaengine并启动传输
dmaengine_submit(desc);//
dma_async_issue_pending(dma_chan);//启动传输
//5 DMA传输完成,都会引发DMA传输描述符的完成回调函数被调用
dmaengine_pcm_dma_complete()
//pinctrl驱动(针对某些功能有多种配置,可以通过下面的函数选择选择配置)
struct pinctrl *devm_pinctrl_get(struct device *dev);
struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name);
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state);
&usdhc2 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc2_8bit>;
pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
bus-width = <8>;
non-removable;
status = "okay";
};
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog_1>;
imx6ul-evk {
pinctrl_usdhc2_8bit: usdhc2grp_8bit {
fsl,pins = <
MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10069
MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059
MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059
MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059
MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059
MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059
>;
};
pinctrl_usdhc2_8bit_100mhz: usdhc2grp_8bit_100mhz {
fsl,pins = <
MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100b9
MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9
MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9
MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9
MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9
MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9
MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170b9
MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170b9
MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170b9
MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170b9
>;
};
pinctrl_usdhc2_8bit_200mhz: usdhc2grp_8bit_200mhz {
fsl,pins = <
MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9
MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9
MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9
MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9
MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9
MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9
>;
};
}
}
//gpio相关操作
gpio = of_get_named_gpio(nd, "gpio_trigger", 0);
gpio_direction_input(gpio);
gpio_direction_output(gpio,0);
gpio_get_value(gpio);
gpio_set_value(gpio,0);
//自旋锁(通过关中断保证原子操作)
spinlock_t lock;
unsigned long flags;
spin_lock_init(&lock);
spin_lock_irqsave(&lock, flags);
spin_unlock_irqrestore(&lock, flags);
// 高精度定时器使用(100000为ns单位)
static enum hrtimer_restart timer_handler(struct hrtimer *timer)
{
hrtimer_start(&timer, ktime_set(0, 100000), HRTIMER_MODE_REL);
return HRTIMER_NORESTART;
}
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
timer.function = timer_handler;
hrtimer_start(&timer, ktime_set(0,1000000), HRTIMER_MODE_REL);
//linux内核获取当前时间(us)
do_gettimeofday(&start_time);
//字符串相关函数(其他与c语言一样)
#字符串转数字
char *end;
value = simple_strtol("123456", &end, 10);#10进制
//延时函数
udelay(10)//延时10us
mdelay(10)//延时10ms
//资源申请
devm_kzalloc(dev, sizeof(struct priv_data),
//寄存器操作相关函数
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
//读写寄存器
long val;
writel(value, base+GPIO1_DR);
val=readl(base+GPIO1_DR);
//申请中断
irq = platform_get_irq(pdev, 0);
irq = irq_of_parse_and_map(np, 0);
ret = devm_request_irq(&pdev->dev, irq, imx2_wdt_isr,0,dev_name(&pdev->dev), pdev);
devm_free_irq(&pdev->dev,irq,pdev);//释放irq
//使能禁止某个中断
void enable_irq(unsigned int irq);//使能某个中断
void disable_irq(unsigned int irq);//禁止某个中断
//使能禁止全局中断
void local_irq_save(unsigned long flags);//保存中断状态
void local_irq_disable(void )//禁止全局中断
//代码
void local_irq_restore(unsigned long flags); //恢复中断状态
void local_irq_enable(void )//使能全局中断
//时钟
wdev->clk = devm_clk_get(&pdev->dev, NULL);
clk_get_rate(wdev->clk);//获取时钟频率
clk_enable(wdev->clk);//使能时钟
clk_disable(wdev->clk);//禁止时钟
//获取of_device_id的data数据
static const struct of_device_id ak4642_of_match[] = {
{ .compatible = "asahi-kasei,ak4642", .data = &ak4642_drvdata},
{ .compatible = "asahi-kasei,ak4643", .data = &ak4643_drvdata},
{},
};
of_id = of_match_device(ak4642_of_match, &i2c->dev);
drvdata = of_id->data;
//根据指针获得整个结构体
struct device *dev = container_of(ptr, struct device, kobj);
//@ptr: the pointer to the member.
//@type: the type of the container struct this is embedded in.
//@member: the name of the member within the struct.
//设备树相关(查找设备节点 判断兼容性 映射 获取信息 )
(1)查找设备节点
//根据路径参数,在全局链表of_allnodes中,查找匹配的device_node
of_chosen = of_find_node_by_path("/chosen");
//则根据name在全局链表of_allnodes中查找匹配的device_node
gpiop = of_find_node_by_name(NULL, "gpio");
(2)判断兼容性以及映射
// 判断当前开发板是否兼容设备根节点下的compatible属性
ret = of_machine_is_compatible("fsl,imx6dl");
// 判断设备是否兼容compatible属性
of_device_is_compatible(pdev->dev.of_node, "ti,musb-dm816")
//映射node节点的interrupts属性中的中断
irq_of_parse_and_map(node, 0);
//映射node节点的第1个reg属性
void __iomem *regbase = of_iomap(np, 0);
(3) 从device_node中获取信息
//读取属性名为fsl,wakeup_irq的u32数据
ret=of_property_read_u32(np,"fsl,wakeup_irq",&val);
//读取属性名为reg的u32数组的第0个数值
ret=of_property_read_u32_index(np,"reg",0,&val);
//读取属性名为reg的u32数组
ret=of_property_read_u32_array(np,"reg",table,2);
//读取属性名为status的字符串数据
ret=of_property_read_string(np,"status",&name);
//读取属性名为compatible的字符串数组的第0个字符串
ret=of_property_read_string_index(np, "compatible",0,&name);
//读取属性名为compatible的字符串数组
ret=of_property_read_
int dmaengine_slave_config(struct dma_chan *chan, struct dma_slave_config *config)string_array(np, "compatible",str,2);
2 设备树属性读取例子
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
//设备节点信息
/*
/{
aips1: aips-bus@02000000 {
fec2: ethernet@020b4000 {
compatible = "fsl,imx6ul-fec", "fsl,imx6q-fec";
reg = <0x020b4000 0x4000>;
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_ENET>,
<&clks IMX6UL_CLK_ENET_AHB>,
<&clks IMX6UL_CLK_ENET2_REF_125M>;
clock-names = "ipg", "ahb", "ptp";
stop-mode = <&gpr 0x10 4>;
fsl,num-tx-queues=<1>;
fsl,magic-packet;
fsl,wakeup_irq = <0>;
status = "disabled";
};
};
}
*/
static int __init chardev_init(void)
{
int val=0;
int ret=0;
int i=0;
int table[5];
char *name;
char *str[5];
struct device_node *np;
printk("of_fun_test\r\n");
np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
if (!np)
{
printk("/soc/ethernet@020b4000 node is not find\n");
return -1;
}
ret=of_device_is_compatible(np,"fsl,imx6ul-fec");
if(ret==0)
{
printk("of_device_is_compatible is not compatible\n");
return -1;
}
ret=of_property_read_u32(np,"fsl,wakeup_irq",&val);
printk("of_property_read_u32 fsl,wakeup_irq=%d\n",val);
ret=of_property_read_u32_index(np,"reg",1,&val);
printk("of_property_read_u32_index reg=%d\n",val);
ret=of_property_read_u32_array(np,"reg",table,2);
printk("of_property_read_u32_array reg[0]=%d reg[1]=%d\n",table[0],table[1]);
ret=of_property_read_string(np,"status",&name);
printk("of_property_read_string status=%s\n",name);
ret=of_property_read_string_index(np, "compatible",0,&name);
printk("of_property_read_string_index compatible=%s\n",name);
ret=of_property_read_string_array(np, "compatible",str,2);
printk("of_property_read_string_array compatible=%s %s\n",str[0],str[1]);
return 0;
}
static void __exit chardev_exit(void)
{
printk("chardev device tree exit\r\n");
}
module_init(chardev_init);
module_exit(chardev_exit);
MODULE_AUTHOR("WXQ");
MODULE_LICENSE("GPL");
3 dvem相关函数
//CLOCK
devm_clk_get()
devm_clk_put()
//DMA
dmam_alloc_coherent()
dmam_alloc_noncoherent()
dmam_declare_coherent_memory()
dmam_free_coherent()
dmam_free_noncoherent()
dmam_pool_create()
dmam_pool_destroy()
//GPIO
devm_gpiod_get()
devm_gpiod_get_index()
devm_gpiod_get_index_optional()
devm_gpiod_get_optional()
devm_gpiod_put()
//IIO
devm_iio_device_alloc()
devm_iio_device_free()
devm_iio_device_register()
devm_iio_device_unregister()
devm_iio_kfifo_allocate()
devm_iio_kfifo_free()
devm_iio_trigger_alloc()
devm_iio_trigger_free()
IO region
devm_release_mem_region()
devm_release_region()
devm_release_resource()
devm_request_mem_region()
devm_request_region()
devm_request_resource()
//IOMAP
devm_ioport_map()
devm_ioport_unmap()
devm_ioremap()
devm_ioremap_nocache()
devm_ioremap_wc()
devm_ioremap_resource() : checks resource, requests memory region, ioremaps
devm_iounmap()
pcim_iomap()
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
pcim_iomap_table() : array of mapped addresses indexed by BAR
pcim_iounmap()
//IRQ
devm_free_irq()
devm_request_any_context_irq()
devm_request_irq()
devm_request_threaded_irq()
//LED
devm_led_classdev_register()
devm_led_classdev_unregister()
//MDIO
devm_mdiobus_alloc()
devm_mdiobus_alloc_size()
devm_mdiobus_free()
//MEM
devm_free_pages()
devm_get_free_pages()
devm_kasprintf()
devm_kcalloc()
devm_kfree()
devm_kmalloc()
devm_kmalloc_array()
devm_kmemdup()
devm_kstrdup()
devm_kvasprintf()
devm_kzalloc()
//PCI
pcim_enable_device() : after success, all PCI ops become managed
pcim_pin_device() : keep PCI device enabled after release
//PHY
devm_usb_get_phy()
devm_usb_put_phy()
//PINCTRL
devm_pinctrl_get()
devm_pinctrl_put()
//PWM
devm_pwm_get()
devm_pwm_put()
//REGULATOR
devm_regulator_bulk_get()
devm_regulator_get()
devm_regulator_put()
devm_regulator_register()
//SLAVE DMA ENGINE
devm_acpi_dma_controller_register()
//SPI
devm_spi_register_master()