linux
初学者如何学习开发嵌入式Linux/Android设备的驱动?
一、初学者如何学习开发嵌入式Linux/Android设备的驱动?
书接上文,上文提到在获取内核device中可以参考本PWM实现。
PWM设备也是内核中一个标准的 平台设备,我们使用PWM来实现风扇控,本章在介绍pwm设备之前我们先介绍一下内核设备树中的aliases节点。
顾名思义,aliases 重命名,内核设备树提供给我们的driver设备驱动一个统一的管理方式,可以将我们的设备驱动全部挂载在aliases链表中,本人不才,未领会到其中的高深用法,我觉得这个aliases 设备节点最常见的用法就是 get id。
比较核心的两个函数如下:
extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
extern int of_alias_get_id(struct device_node *np, const char *stem);
一个是扫描全部的aliases节点,另一个是通过device_node和名称,获取aliases节点后面的序号。
具体代码有兴趣的朋友可以看:drivers/of/base.c中该函数的实现。
我们本次使用pwm,为什么要先介绍 aliases节点呢?
在驱动开发过程,阅读pwm内核源码,我们发现,pwm的控制接口pwm_apply_state所需要的句柄为:pwm_device,那么我们的核心目的是不是就是如何获取 pwm_device,如果我们拿到了 pwm_device,那么也就掌握了 内核中的pwm外设。
内核中获取 pwm_device的标准接口为:
struct pwm_device *pwm_request(int pwm_id, const char *label)
所需要的参数也很简单,一个id号,和一个 label, label就是设备名称。
能解决问题吗?当然可以,使用这个接口可以直接从内核中拿到pwm_device,但是这个id有一个问题,就是这个id会随着我们使能的pwm数量而改变。加入我们chip上目前又12路pwm,我们使能 8, 9, 10 三路,那么此时内核中会生成三个pwm节点,他们的编号是 0 ,1,2,对应的就是8, 9,10。
这样就会存在问题,我们传进去的id号,可能非我们真正使用的id,当有一天我又使能了pwm8,那么所有的号都需要依次加一,非常不人性化。
但是内核设备树中,所声明的pwm号,在驱动中request时却是真正的pwm号,那么这块是 怎么绑定且转换的呢?
可以发现,内核中使用的接口是,在dts中表示后,内核中使用的接口是:
static inline struct pwm_device *devm_of_pwm_get(struct device *dev,
struct device_node *np,
const char *con_id)
{
return ERR_PTR(-ENODEV);
}
通过查看源码可以发现,在dts中进行设备注册后会动态与device绑定在一起。
那么我们思路就来了,返回去找,根据id找到 device_node,再根据device_node 就可以在pwm中找到pwm_chip了,然后顺手取一下里面的id(内核中的id),再使用标准的pwm_request接口申请就好了。
代码如下:
typedef void* pwm_handle;
pwm_handle pwm_init(int pwm_channal, const char *label)
{
int ret = 0;
pwm_handle handle;
int kernel_idex;
struct pwm_device* pwm = NULL;
struct device_node* node = NULL;
/* 根据通道号在内核中查找当前注册的 device_node */
node = of_alias_get_device_node(pwm_channal, "pwm"); /* todo:不添加到内核 平台相关层添加一个 .h */
if (node == NULL) {
printk("%s Faild not get alias device node, Please check dts have pwm for alias\n");
return NULL;
}
/* 根据查找到根据查找到的device node 从pwm全局中查找注册的pwm_chip */
struct pwm_chip *node_pwm_chip = of_node_to_pwmchip(node); /* 使用 pwm->pwm 重新request一次 */
if (node_pwm_chip == NULL) {
printk("%s Faild not get pwm_chip, Please check enable pwm from dts\n");
return NULL;
}
/* 利用上步骤查找到的 pwm_chip 拿到可以使用的 pwm_device */
pwm = node_pwm_chip->pwms;
/* 通过pwm_device 中的 pwm参数,可以拿到当前device在kernel中的通道号 */
kernel_idex = pwm->pwm;
pwm = pwm_request(kernel_idex, label);
if (IS_ERR(pwm)) {
ret = PTR_ERR(pwm);
if (ret != -EPROBE_DEFER)
printk("Could not get PWM: %d\n", ret);
return NULL;
}
handle = pwm;
return handle;
}
有些同学看到代码就要问了,内核中没又这个接口啊?of_alias_get_device_node
没错,上面手的aliases节点,中并没有这个接口,我们可以模仿获取id的方法来获取device_node嘛
代码如下:
struct device_node *of_alias_get_device_node(int id, const char *stem)
{
struct alias_prop *app;
struct device_node *node;
mutex_lock(&of_mutex);
list_for_each_entry(app, &aliases_lookup, link) {
if (strcmp(app->stem, stem) != 0)
continue;
if (id == app->id) {
node = app->np;
break;
}
}
mutex_unlock(&of_mutex);
return node;
}
至此,我们就得到了 我们梦寐以求的 pwm_device.
直接上控制接口:
typedef struct
{
int pwm_id; //pwm通道号
int period; //pwm周期
int duty; //pwm占空比
int polity; //pwm极性
int enable; //使能状态
void *prsv; //保留
uint32_t rsv; //保留
}pwm_cfg;
int pwm_ctrl(pwm_handle handle, pwm_cfg* state)
{
int ret = 0;
struct pwm_device *pwm;
struct pwm_state ofstate;
if (handle == NULL) {
printk("%s: input handle is NULL\n", __FUNCTION__);
ret = -ENOMEM;
}
pwm = (struct pwm_device*)handle;
ofstate.duty_cycle = state->duty;
ofstate.period = state->period;
ofstate.polarity = state->polity;
if(state->enable)
ofstate.enabled = true;
else
ofstate.enabled = false;
ret = pwm_apply_state(pwm, &ofstate);
return ret;
}
二、嵌入式linux驱动涉及哪些芯片?
嵌入式Linux驱动可以涉及不同类型的芯片,包括处理器、存储器、网络和图形加速器等。常见的处理器包括ARM、x86、PowerPC等,存储器包括NAND、NOR、SDRAM等,网络芯片包括以太网控制器、Wi-Fi、蓝牙等。此外,还有一些需要加速的芯片,如图形处理器、视频编解码器等。嵌入式Linux驱动需要与这些芯片进行交互,并提供实现设备功能所需的接口,以支持应用程序的正常运行。
三、嵌入式linux驱动是青春饭吗?
当然不是,这个凭的是技术和经验。
四、嵌入式linux?
BSP(Board Support Package),板级支持包,也称为硬件抽象层HAL或者中间层。
它将系统上层软件和底层硬件分离开来,使系统上层软件开发人员无需关系底层硬件的具体情况,根据BSP层提供的接口开发即可。
BSP是相对于操作系统而言的,不同的操作系统有不同定义形式的BSP,要求BSP所实现的功能也有所不同。
在嵌入式Linux系统中,主要是初始化底层硬件并引导操作系统;同时,BSP又是和硬件相关的,还要考虑对硬件的初始化操作。这些初始化操作主要是对CPU、内存、中断等相关的寄存器及协处理器进行正确的配置。
在不同的开发阶段,因为核心和文件系统所处的位置不同,BSP所要完成的工 作也有所不同;在开发调试阶段,BSP要能够与主机通信并从主机下载核心;在目标产品中,BSP要能够从非易失存储设备中加载核心。
扩展资料
BSP有两个特点:硬件相关性和操作系统相关性。
设计一个完整的BSP需要完成两部分工作:
A、 嵌入式系统的硬件初始化和BSP功能。
片级初始化:纯硬件的初始化过程,把嵌入式微处理器从上电的默认状态逐步设置成系统所要求的工作状态。
板级初始化:包含软硬件两部分在内的初始化过程,为随后的系统初始化和应用程序建立硬件和软件的运行环境。
系统级初始化:以软件为主的初始化过程,进行操作系统的初始化。
B、 设计硬件相关的设备驱动。
五、嵌入式Linux驱动开发有什么推荐的公司吗?应届生?
感谢邀请。汇总了一份2023最全的嵌入式公司,建议收藏起来,以后投递的时候作为参考!
2023年最新国产半导体芯片行业细分企业名录: 囊括MCU、存储芯片、模拟芯片、电源IC、功率器件、IGBT、MOSFET、CMOS、液晶芯片、触控芯片、指纹识别芯片、时钟芯片、载波芯片、数字隔离器等领域。
01 移动CPU
02 计算机CPU/MPU
03 IP
04 GPU
05 ASIC
06 DSP
07 FPGA
08 EDA
09 MCU
10 存储芯片
11 模拟芯片
12 电源IC
13 功率器件
14 IGBT
15 MOSFET
16 CMOS
17 液晶芯片
18 触控芯片
19 指纹识别芯片
20 人脸识别/虹膜
21 射频芯片
22 WiFi芯片
23 蓝牙芯片
24 NB-loT芯片
25 RFID芯片
26 5G芯片
27 光芯片
28 光模块
29 GPS/北斗芯片
30 USB转接芯片
31 视频转换芯片
32 网络交换芯片
33 音频芯片
34 激光核心元件
35 激光雷达
36 毫米波雷达
37 MMIC
38 TPMS模组
39 LED芯片
40 时钟芯片
41 载波芯片
42 数字隔离器
43 航空航天领域嵌入式SOC
44 安全芯片
45 智能卡芯片
46 AI芯片
47 智能应用处理器SOC
48 OTT盒子主控CPU
49 无人机主控芯片
50 智能消防机器人芯片
51 VR主控芯片
52 智能音箱芯片
53 蓝牙音箱芯片
54 智能电视芯片
55 商显主控
56 行车记录仪主控芯片
57 投影仪主控芯片
58 打印机芯片
59 视频监控芯片
60 高端电容电阻
61 连接器
62 晶振
63 传感器
64 芯片代理分销
65 半导体生产设备
66 硅晶圆
67 晶圆代工
68 半导体封测
69 测试设备
70 操作系统
原文链接:https://www.zhihu.com/question/576122754/answer/2829273341?utm_campaign=shareopn&utm_medium=social&utm_oi=805166261268004864&utm_psn=1595350880659845120&utm_source=wechat_session推荐一个 github仓库,上面放了上百本经典的嵌入式,计算机书籍,可以star一下,下次找书直接在上面搜索就可以了: github 书籍宝藏仓库 github访问不了可以访问这个:gitee 书籍宝藏仓库
练手项目推荐这篇文章:
分享GitHub上一些嵌入式相关的高星开源项目笔试面试推荐这个专栏:
嵌入式软件工程师笔试面试指南学习路线:
仲一:【干货分享】嵌入式学习路线公开!(书籍推荐+视频推荐+练手项目)嵌入式经典书籍,免费下载,值得收藏:
仲一:嵌入式Linux必读经典书籍(含下载方式)码字不易,如果觉得本篇文章对你有帮助,可以点个免费的赞支持作者 @仲一
六、linux驱动设备名在哪个文件夹下?
设备驱动名一般都在/dev目录下。一般常用的设备的设备文件名如下:/dev/hd[a-t]:IDE设备/dev/sd[a-z]:SCSI设备 /dev/fd[0-7]:标准软驱 /dev/md[0-31]:软raid设备/dev/loop[0-7]:本地回环设备/dev/ram[0-15]:内存/dev/null:无限数据接收设备,相当于黑洞/dev/zero:无限零资源/dev/tty[0-63]:虚拟终端/dev/ttyS[0-3]:串口/dev/lp[0-3]:并口/dev/console:控制台/dev/fb[0-31]:framebuffer
七、嵌入式Linux的底层驱动开发主要从事什么工作?
都说了是底层驱动开发了,那主要工作就是开发驱动了,比如板卡上的PCIE设备,IIC设备,SPI设备等等
八、linux嵌入式开发环境用什么linux?
学习嵌入式开发,一般会面临3个阶段:
1:学习基本的编程语言C/C++,此时linux版本不重要,重要的是符合C99标准的编译器,建议使用ubuntu或者centos,免费并且都默认安装了标准g++编译器。
2:学习linux的基本环境,包括libc库等基本C库和一些标准的内核函数,建议使用ubuntu,不要使用centos,centos里面扩展了不少redhat的库,在实际嵌入式开发无法使用。
3:学习嵌入式的特定编译环境,交叉编译技巧等等,此时必须在实际的嵌入式开发板上学习,不能在发行版linux下学习,因为嵌入式开发板都是用裁剪和优化过的linux内核,编译环境也是嵌入式处理器自带的,和发行版linux有较大的不同。 总的来说,学习嵌入式开发,建议使用ubuntu
九、目前有几个嵌入式Linux应用开发的offer,但是本人想以后去干Linux驱动,下面这公司怎么选?
增加一个别人看法
做啥Linux应用开发?资深了,待遇上去了基本等于失业。如果要做,或者Linux驱动,或者单片机汽车,单片机医疗,单片机电机这些。其实现在单片机待遇很高,甚至比互联网还好,干嘛转坑爹Linux应用层?你去网上搜搜招聘看,基本找不到招聘公司,你转这个方向干嘛?一点前途没有。
单片机方向待遇
Linux驱动待遇
Linux应用待遇
十、在linux下人体学输入设备的驱动程序?
基本上大多数系统无法识别并安装驱动的USB设备插入电脑时,都回提示为“usb人体学输入设备”,所以仅凭名称是无法判断正确的驱动的。
如果该硬件自带有驱动程序光盘,可以插入USB设备后,将光盘放入光驱,运行其中的安装程序,就可以自动给硬件安装驱动了。
如果没有驱动程序,也不知道该安装什么驱动程序,那么去下载安装驱动精灵之类的自动驱动安装工具,运行后会自动扫描并安装相应的硬件。
热点信息
-
在Python中,要查看函数的用法,可以使用以下方法: 1. 使用内置函数help():在Python交互式环境中,可以直接输入help(函数名)来获取函数的帮助文档。例如,...
-
一、java 连接数据库 在当今信息时代,Java 是一种广泛应用的编程语言,尤其在与数据库进行交互的过程中发挥着重要作用。无论是在企业级应用开发还是...
-
一、idea连接mysql数据库 php connect_error) { die("连接失败: " . $conn->connect_error);}echo "成功连接到MySQL数据库!";// 关闭连接$conn->close();?> 二、idea连接mysql数据库连...
-
要在Python中安装modbus-tk库,您可以按照以下步骤进行操作: 1. 确保您已经安装了Python解释器。您可以从Python官方网站(https://www.python.org)下载和安装最新版本...