C知识点
一. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)12#define a_year (365*24*60*60)UL//UL无符号整形
二. 写一个”标准”宏MIN ,这个宏输入两个参数并返回较小的一个1#define MIN( a, b) ((a<=b)?(a):(b))
三. 嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?123456while(1){}for(;;){}loop:...goto loop;
四. 用变量a给出下面的定义
a) 一个整型数(An integer)
b)一个指向整型数的指针( A pointer to an integer)
c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an intege)
d)一个有10个整型数的数组( An array of 10 integers)
e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to inte ...
研电赛
题目:超声接近感知系统(1)赛题主要考察接近感知系统的实现,可使用指示灯的亮灭来表征接近态和远离态
(2)以超声波技术为基础实现接近感知。可辅助使用加速度、陀螺仪或等其他传感器,来提高准确率(如提取接听电话动作中的距离、姿态、运动轨迹…等信息的变化)。
设计stm32pcb
设计姿态传感器pcb由磁力计IST8310和陀螺仪BMI088组成。
由于先设计的硬件,并没确定使用的IO口,所以分为了两个板子,为了符合题目要求,pcb上打上通孔,便于使用螺丝连接。
使用MCU是stm32f407VGT6的型号,在使用usart进行串口通信的时候发现会出现,乱码的问题,最后发现问题的原因出在了,晶振的频率源头上,
#define HSE_VALUE 25000000 把25改为8.
使用两个超声波模块,使用spi和iic通信来读取姿态传感器的数据。
关于SPI的通信使用为了节省CPU的占有率,使用了串口DMA的通信方式,DMA传输将数据从一个地址空间复制到另一个地址空间, 提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
关于这种pcb的贴片焊接,是建议用开一个钢网,之后刷锡膏,放 ...
linux异步通知
异步通知异步通知:一旦设备准备就绪,则主动通知应用程序,这样引用程序根本不需要查询设备状态,由此引入了信号的概念,信号是在软件层次上的对中断机制的一种模拟,驱动可以通过主动向应用程序发送信号的方式来报告自己可以访问了,应用程序获取到信号以后就可以从驱动设备中读取或者写入数据了。整个过程就相当于应用程序收到了驱动发送过来了的一个中断,然后应用程序去响应这个中断,。
信号Linux中用异步信号来实现进程通信(IPC)。
123456789101112131415161718192021222324252627282930313233343534 #define SIGHUP 1 /* 终端挂起或控制进程终止 */35 #define SIGINT 2 /* 终端中断(Ctrl+C 组合键) */36 #define SIGQUIT 3 /* 终端退出(Ctrl+\组合键) */37 #define SIGILL 4 /* 非法指令 */38 #define SIGTRAP 5 /* debug 使用,有断点指令产生 */39 #define SIGABRT 6 /* 由 abort(3) ...
linux阻塞与非阻塞
阻塞和非阻塞IO阻塞式
当应用程序对设备驱动进行操作的时候,如果不能获取到设备资源,那么阻塞式 IO 就会将应用程序对应的线程挂起,直到设备资源可以获取为止。
非阻塞式
对于非阻塞 IO,应用程序对应的线程不会挂起,它要么一直轮询等待,直到设备资源可以使用,要么就直接放弃。
等待队列等待队列头阻塞式的好处就是,当无法获取资源的时候进程进入休眠状态,让出cpu来干别的事情,可以操作的时候再进行唤醒(一般在中断里唤醒)。
Linux内核提供了等待队列来实现阻塞进程的唤醒工作,首先要创建并初始化一个等待队列头,等待队列头使用结构体wait_queue_head_t表示。
1234567struct __wait_queue_head{ spinlock_t lock; struct list_head task_list;}typedef struct __wait_queue_head wait_queue_head_t;//使用init_waitqueue_head初始化等待队列头void init_waitqueue_head(wait_queu ...
linux中断
linux中断中断是指CPU在执行程序执行中,出现了突发事件,CPU必须暂停当前程序的执行,处理突发事件,处理完后又返回程序到中断的位置继续进行。
根据中断入口跳转方法不同,分为向量中断和非向量中断,采用向量中断的CPU通常为不同的中断分配不同的中断号,当检测到某中断到来后,自动跳转到该中断号对应的地址执行。不同中断号的中断有不同的入口地址。非向量中断的多个中断共享一个入口地址,进入该入口地址后,再通过软件判断中断标志来标识,具体哪个中断。
申请和释放中断request_irq 函数用于申请中断, request_irq函数可能会导致睡眠,因此不能在中断上下文或者其他禁止睡眠的代码段中使用 request_irq 函数。 request_irq 函数会激活(使能)中断,所以不需要我们手动去使能中断。
12345int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)
irq:要申请中断的中断号。
每个中断都有一个中断号,通 ...
linux内核定时器
时间管理和内核定时器Linux 内核中有大量的函数需要时间管理,比如周期性的调度程序、延时程序、对于我们驱动编写者来说最常用的定时器。硬件定时器提供时钟源,时钟源的频率可以设置, 设置好以后就周期性的产生定时中断,系统使用定时中断来计时。中断周期性产生的频率就是系统频率,也叫做节拍率(tick rate)(有的资料也叫系统频率)。
可以在编译 Linux 内核的时候可以通过图形化界面设置系统节拍率,
12-> Kernel Features-> Timer frequency (<choice> [=y])
高节拍率和低节拍率的优缺点:
①、高节拍率会提高系统时间精度,如果采用 100Hz 的节拍率,时间精度就是 10ms,采用1000Hz 的话时间精度就是 1ms,精度提高了 10 倍。高精度时钟的好处有很多,对于那些对时间要求严格的函数来说,能够以更高的精度运行,时间测量也更加准确。②、高节拍率会导致中断的产生更加频繁,频繁的中断会加剧系统的负担, 1000Hz 和 100Hz的系统节拍率相比,系统要花费 10 倍的“精力”去处理中断。中断服务函数占 ...
globalmem设备驱动
globalmem驱动globalmem为“全局内存”的意思,在globalmem字符设备中会分配一片大小为GLOBALMEM_SIZE的内存空间,并在驱动中提供对这片内存的读写、控制和定位函数,供用户空间的进程能通过Linux系统调用获取和设置这片内存。
头文件、宏定义以及结构体1234567891011121314151617181920#include <linux/module.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/cdev.h>#include <linux/slab.h>#include <linux/uaccess.h>#define GLOBALMEM_SIZE 0x1000#define MEM_CLEAR 0x1#define GLOBALMEM_MAJOR 230static int globalmem_major = GLOBALMEM_MAJOR;module_param(globalmem_maj ...
linux并发与竞争
并发若我们谈及计算机系统中的并发,则是指同一个系统中,多个独立活动同时进行,而非依次进行。起初的计算机并发只是一种制造并发的假象,因为只有一个处理器,在同一时刻实质只能处理一个任务,不过是一秒钟内进行多个任务的切换。看起来是同时进行的,因此叫做任务交换。
多年来,配备了多处理器的计算机一直被用作服务器,它要承担高性能的计算任务;现今,基于一芯多核处理器(简称多核处理器)的计算机日渐普及,多核处理器也用在台式计算机上。
无论是装配多个处理器,还是单个多核处理器,或是多个多核处理器,这些计算机都能真正并行运作多个任务,我们称之为硬件并发(hardware concurrency)。
并发方式多进程并发在应用软件内部,一种并发方式是,将一个应用软件拆分成多个独立进程同时运行,它们都只含单一线程,非常类似于同时运行浏览器和文字处理软件。这些独立进程可以通过所有常规的进程间通信途径相互传递信息(信号、套接字、文件、管道等)。
多线程并发另一种并发方式是在单一进程内运行多线程。线程非常像轻量级进程,每个线程都独立运行,并能各自执行不同的指令序列。
不过,同一进程内的所有线程都共用相同的地址空间,且 ...
gpio子系统
GPIO子系统GPIO子系统API函数对于驱动开发人员,设置好设备树以后就可以使用 gpio 子系统提供的 API 函数来操作指定的 GPIO, gpio 子系统向驱动开发人员屏蔽了具体的读写寄存器过程。这就是驱动分层与分离的好处,大家各司其职,做好自己的本职工作即可。 gpio 子系统提供的常用的 API 函数有下面几个:
gpio_request函数,用于申请一个 GPIO 管脚
在使用一个 GPIO 之前一定要使用 gpio_request进行申请
1int gpio_request(unsigned gpio, const char *label)
gpio:要申请的gpio号,使用of_get_named_gpio函数从设备树获取指定gpio属性
label: gpio的名字
返回值:0申请成功,其他值失败
gpio_free函数, 释放gpio
1void gpio_free(unsigned gpio)
gpio: 释放的gpio
返回值无
gpio_direction_input函数 , 设置gpio为输入
1void gpio_direction_in ...
设备树上的驱动开发
设备树驱动编写框架
编写设备树节点首先是将节点编写在使用的开发板的dts文件中,比如编写led的节点。首先将节点编写在根节点下:
12345678910111213alphaled//节点名字{ #address-cells = <1>; #size-cells = <1>; compatible = "atkalpha-led"; status = "okay"; reg = { 0X020C406C 0X04 //CCM_CCGR1_BASE 0X020E0068 0X04 //SW_MUX_GPIO103_BASE 0X020E02F4 0X04 //SW_PAD_GPIO103_BASE 0X0209C000 0X04 //GPIO1_DR_BASE 0X0209C004 0X04 //GPIO1_GDIR_BASE };};
在节点中已经写入物理地址,所以驱动程序进行获取就行不用写了,设备树修改完 ...