0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

学习笔记分享|使用C库函数控制ELF 1开发板的LED

ElfBoard 2024-01-19 11:12 次阅读
wKgaomWp5vyAZCKwAAUeBr-5VoU338.png(ELF1/ELF1S开发板及显示屏)

嵌入式Linux系统开发中,通过编程控制硬件资源是至关重要的技能之一,今天跟各位小伙伴分享一篇专注于介绍如何使用C库函数控制ELF 1开发板LED的学习笔记。

希望通过这篇学习笔记,让屏幕前的小伙伴能深入理解Linux内核对于底层硬件资源管理的抽象机制,为进行复杂的嵌入式系统开发奠定基础。

一、系统调用与库函数

(一)系统调用

系统调用(System Call)是操作系统内核提供的函数,在内核态运行(Kernel Mode),是操作系统为用户提供的一些接口。它通过软中断向内核态发出一个明确的请求。有一些任务需要进程跑在内核态才能执行,比如和硬件打交道。所以进程调用系统调用就能让自己运行在内核态从而执行这些类似的任务。系统调用实现了用户态进程和硬件设备之间的大部分接口。

常见系统调用

Open, Close, Read, Write, Ioctl,Fork,Clone,Exit,Getpid,Access,Chdir,Chmod,Stat,Brk,Mmap等,需要包含Unistd.h等头文件。

(二)库函数

库函数位于系统调用的上层,扮演着封装和抽象的角色,运行在用户态(User Mode),旨在为程序员提供一种更为便捷的方式来调用真正实现底层功能的系统调用。这些库函数充当了用户态服务的供给者,其功能实现机制各异:有的库函数可能整合并包装了一个或多个不同的系统调用,而有的库函数则能够直接在用户态提供所需服务,无需进一步调用任何系统调用。

(三)区别

系统调用通常不可替换,而库函数通常可替换
普通的库函数调用由函数库或用户自己提供,因此库函数是可以替换的。例如,对于存储空间分配函数malloc,如果不习惯它的操作方式,我们完全可以定义自己的malloc函数。

系统调用通常提供最小接口,而库函数通常提供较复杂功能

例如sbrk系统调用分配一块空间给进程,而malloc则在用户层次对这以空间进行管理。

系统调用运行在内核空间,而库函数运行在用户空间

因为系统调用属于内核,和库函数不属于内核。因此,如果当用户态进程调用一个系统调用时,CPU需要将其切换到内核态,并执行一个内核函数。

内核调用都返回一个整数值,而库函数并非一定如此

在内核中,整数或0表示系统调用成功结束,而负数表示一个出错条件。而出错时,内核不会将其设置在errno,而是由库函数从系统调用返回后对其进行设置或使用。

POSIX 标准针对库函数而不是系统调用

判断一个系统是否与POSIX需要看它是否提供一组合适的应用程序接口,而不管其对应的函数是如何实现的。因此从移值性来讲,使用库函数的移植性较系统调用更好。

系统调用运行时间属于系统时间,库函数运行时间属于用户时间

调用系统调用开销相对库函数来说更大

很多库函数本身都调用了系统调用,这得益于双缓冲的实现,在用户态和内核态,都应用了缓冲技术,对于文件读写来说,调用库函数,可以大大减少调用系统调用的次数。而用户进程调用系统调用需要在用户空间和内核空间进行上下文切换,开销较大。如此以来,库函数的开销也就会比直接调用系统调用小了。另外一方面,库函数同样会对系统调用的性能进行优化。

二、使用C库函数控制LED

(一)实验代码

参考3.2.1.2 文件 I/O 的方式控制 LED的例程将使用系统调用的部分改为使用库函数来实现。代码如下:

#include #include #include #define LED1_BRIGHTNESS "/sys/class/leds/led1/brightness" #define LED2_BRIGHTNESS "/sys/class/leds/led2/brightness" #define LED3_BRIGHTNESS "/sys/class/leds/led3/brightness" int main() { FILE *fd1, *fd2, *fd3; fd1 = fopen(LED1_BRIGHTNESS, "w"); if(fd1 < 0) { printf("Fail to Open %s device\n", LED1_BRIGHTNESS); exit(1); } fd2 = fopen(LED2_BRIGHTNESS, "w"); if(fd2 < 0) { printf("Fail to Open %s device\n", LED2_BRIGHTNESS); exit(1); } fd3 = fopen(LED3_BRIGHTNESS, "w"); if(fd3 < 0) { printf("Fail to Open %s device\n", LED3_BRIGHTNESS); exit(1); } while(1) { fwrite("1",3,1,fd1); fflush(fd1); sleep(1); fwrite("0",1,1,fd1); fflush(fd1); fwrite("1",3,1,fd2); fflush(fd2); sleep(1); fwrite("0",1,1,fd2); fflush(fd2); fwrite("1",3,1,fd3); fflush(fd3); sleep(1); fwrite("0",1,1,fd3); fflush(fd3); } fclose(fd1); fclose(fd2); fclose(fd3); return 0; }

(二)编译、测试将代码编译后拷贝到ELF 1开发板进行测试。

wKgaomWp55GAfbdzAAA14UYzuQc929.png

执行LED2,查看结果

wKgaomWp55iARvKJAAAaYzoNUjQ024.png

可以看到LED按照预期循环点亮

wKgaomWp56SAAybXAA45QUwgv9E021.png

三、总结

本次实验使用C库函数实现了对LED的控制,通过一个简单的示例来感受系统调用与库函数的区别。但是代码中还有需要注意的地方。

代码中调用fwrite函数写入内容时,它可能只是把内容保存到了C库的缓冲区,并没有执行真正的系统调用write函数把内容写入到设备文件,这种情况下LED灯的状态是不会被改变的,代码中在fwrite函数后调用了fflush要求立刻把缓冲区的内容写入到文件,确保 执行了相应的操作。在实验时可以尝试把代码中的fflush都注释掉,这种情况下有极大的几率是无法正常改变LED灯状态的。

如果不考虑操作的时间开销,其实控制硬件更推荐的做法是,每次控制LED灯都使用fopen—fwrite—fclose的流程,这样就不需要考虑flseek、fflush的问题了,但最推荐的还是直接通过系统调用来控制硬件的方式。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5082

    文章

    19115

    浏览量

    304935
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136746
  • 开发板
    +关注

    关注

    25

    文章

    5038

    浏览量

    97404
收藏 人收藏

    评论

    相关推荐

    学习笔记分享|ElfBoard开发板初识

    大家分享一篇共创官学习笔记,共同见证携手进步的真实写照: 最近很荣幸能够参加保定飞凌嵌入式公司举办的Elfboard\"自创一派\" 共创社活动。下图是本次活动采用的ElF 1
    发表于 01-04 10:22

    嵌入式学习-ElfBoard ELF 1板卡-使用C库函数控制ELF1开发板LED

    来自共创官的学习笔记分享|使用C库函数控制ELF1开发板L
    发表于 01-19 10:07

    I.MX6ULL-ElfBoard ELF1板卡- 使用C库函数控制开发板LED

    来自共创官的学习笔记分享|使用C库函数控制ELF1开发板L
    发表于 01-19 10:12

    嵌入式学习-ElfBoard ELF 1开发板-共创官学习笔记分享|将Go程序编译到ELF 1开发板

    编译并运行在ELF 1开发板上的。 一、在GoLand中配置(一) 配置SSH连接Ubuntu虚拟机以及ELF 1
    发表于 02-21 10:22

    4412开发板学习笔记分

    4412开发板学习笔记
    发表于 02-05 07:40

    STM32F103学习笔记分

    蓝桥杯嵌入式学习笔记|STM32F103学习笔记–写在前沿:从准备蓝桥杯嵌入式开始,一步一个脚印认真学习STM32
    发表于 12-24 07:08

    ELF 1开发板试用】+ RGB LED及按键的控制

    1开发板上,自然也不会少了它,其在开发板上的位置如图1所示,共有3个,其颜色分别为红、绿、黄3个色彩。 图1LED灯 3个
    发表于 11-21 11:11

    ELF 1开发板试用】板载资源测试1:点亮LED

    位置?如上图打在左边位置。2、USB Type-C线的另一端插入PC机/笔记本电脑USB口。在PC机/笔记本电脑设备管理器中查看端口号为COM3。3、将上图开关拨到右边,启动开发板。此
    发表于 12-13 23:01

    ALIENTEK MiniSTM32开发板例程-库函数版本

    ALIENTEK MiniSTM32开发板例程-库函数版本—1-27个实验例程。
    发表于 07-25 17:45 0次下载

    ALIENTEK MiniSTM32开发板例程(库函数版本)

    ALIENTEK MiniSTM32开发板例程(库函数版本)_标准例程+扩展例程。
    发表于 07-25 17:45 0次下载

    STM32F107开发板学习笔记

    STM32F107开发板学习笔记
    发表于 10-27 09:16 52次下载
    STM32F107<b class='flag-5'>开发板</b>的<b class='flag-5'>学习</b><b class='flag-5'>笔记</b>

    Alientek MiniSTM32开发板例程库函数版本资料合集免费下载

    本文档的主要内容详细介绍的是Alientek Ministm32开发板例程库函数版本资料合集免费下载包括了:
    发表于 05-09 08:00 0次下载
    Alientek MiniSTM32<b class='flag-5'>开发板</b>例程<b class='flag-5'>库函数</b>版本资料合集免费下载

    STM32库函数开发-GPIO

    2021-01-11 学习日志STM32f1库函数开发学习实战一 · I/O口1. 文件夹结构2
    发表于 01-13 16:17 14次下载
    STM32<b class='flag-5'>库函数</b><b class='flag-5'>开发</b>-GPIO

    关于ELF1/ELF1S开发板的音频接口,你需要知道的都在这!

    音乐可以将平凡的画面赋予深厚的意义,那么音频接口就是这个支点;今天就来给大家详细介绍一下ELF1/ELF1S开发板的音频接口。ELF1/ELF1
    的头像 发表于 10-31 14:10 705次阅读
    关于<b class='flag-5'>ELF1</b>/<b class='flag-5'>ELF1</b>S<b class='flag-5'>开发板</b>的音频接口,你需要知道的都在这!

    ELF 1技术贴|在NXP源码基础上适配ELF 1开发板LED功能

    LED适配为例,详细说明整个适配过程。01准备工作NXP源码路径ELF1开发板资料包\07-NXP原厂资料\07-1NXP官方源码\linux-imx-imx_4.1
    的头像 发表于 12-29 10:04 854次阅读
    <b class='flag-5'>ELF</b> <b class='flag-5'>1</b>技术贴|在NXP源码基础上适配<b class='flag-5'>ELF</b> <b class='flag-5'>1</b><b class='flag-5'>开发板</b>的<b class='flag-5'>LED</b>功能