学习总结2015.6.24

《6.24》
mdev在/etc/init.d/rcS中的内容与作用
/bin/mount -t sysfs sysfs /sys
/bin/mount -t tmpfs tmpfs /dev
echo /sbin/mdev > /proc/sys/kernel/hotplug   //热拔插下检测到时,进行调


//用/sbin/mdev来查看/sys下的                    


//目录变化,从而决定是否创建


//设备节点。
mdev -s                 //扫描/sys目录下是否有dev文件,然后有的话,则在/dev


   //目录下创建文件节点




/etc/init.d/rcS中的mdev的作用不难看出:mdev的动作都是与/sys目录相关,
原因在于mdev与udev相关,而udev是用户态下,基于sysfs所产生的设备文件
系统,并且有sysfs挂载在/sys目录下!!!!




《6.25》
一、定时器的PWM的通道个数问题:
STM32中的定时器TIM6和TIM7为基本定时器,不能产生PWM。
         定时器TIM1和TIM8为高级定时器,能产生高达7路的PWM。
定时器TIM2-TIM5/TIM9-TIM14为通用定时器有多达4路的PWM。
注意:从CCMRx(1/2)和CCRx(1/2/3/4)寄存器可以看出其输入和输出有多少通道!!!!
      TIM6和TIM7没有这两种寄存器,不能进行输入和捕获功能。


对于通用的寄存器,像TIM9/TIM12是具有两路独立的输入输出通道。
   TIM10/TIM11/TIM13/TIM14只具有一路独立的输入输出通道。


二、寄存器的预装载问题:
使能自动预装载功能,针对的对象是TIMx_CCRx(1、2、3、4)寄存器。如果使能了自动预装载功能,对其


写入的数值将不会立即传入到CCRx中去,而是要等到发生了更新事件。
然后要设置自动预装载功能要进行两步操作:
1.将TIMx_CCMR1中的OC1PE位选择相应的使能预装载功能,即CCRx。
2.在TIMx_CR1寄存器中设置ARPE位,使能自动重装载的预装载寄存器。(注意:只能向上计数或中心对


称模式中)
由于开始时,CCRx预装载值不会传入到影子寄存器中,原因在于它必须是产生了更新事件,
那么为了程序开始时,能够使其进行初次赋值,必须人为的进行更新事件产生。所以我们
必须将TIMx_EGR(事件产生寄存器)的UG位置1,产生更新事件来初始化所有寄存器。


小结:由上可知,预装载寄存器与影子寄存器的传入,是随时发生都可以,或者产生事件才可以,在PWM


模式下取决与CCMR中的OCxPE位的预装功能使能和CR1的ARPE位设置,但同时,要明白更新事件才进行装


载,会面临一个初始化的问题:怎样在程序开始时进行一次装载,此时我们就要认为产生一个更新事件





三、PWM的输出频率计算:
由TIM14_PWM_Init(arr,psc);其中有Tout=(arr+1)*(psc+1)/F; F=84Mhz. 即APB1的频率。
程序中的arr=500-1,psc=84-1,那么计数器的频率为1Mhz,定时器溢出的频率为1Mhz/500=2Khz.




刘魏_裸机/PWM输出实验 实现的功能:1、LED0实现TIM14定时器的PWM功能
 2、LED1实现TIM3定时器的中断功能




四、定时器捕获原理:由于按键连接着高电平,同时






《6.26》
第五章linux文件系统和设备文件


一、关于file和inode的作用和来源:
    1、file结构体代表着一个打开的文件(设备就对应设备文件),系统中每个打开的文件在内核空间


中都会有一个相关联的struc file,它又内核打开文件时创建,并传递给在文件上进行操作的任何函数。


(即哪个函数要用哪个文件,内核就它的file文件给哪个函数,内核->file(文件)->函数操作)。
    同时,文件的所有实例关闭后,即函数不需要操作文件了。内核释放这个数据结构。
    内核中都将struct file的指针命名为file或filp。
    2、inode结构体是属于VFS的,它包含文件的访问权限、属主、组、大小、生成/访问修改时间信息


。它是LINUX管理文件系统的基本单位,也是文件系统连接子目录、文件的桥梁。(即linux管理文件-


>inode->file) 
       inode结构体中含有cdev设备或block_dev设备结构体。
   延伸: 对于devfs设备文件系统和udev设备文件系统,前者从内核态即进行操作,在驱动          


程序中加入devfs_register()创建设备文件。同时从devfs使用范例中          


ret=register_chrdev()内核中注册设备,可以看出创建设备文件和注册设备是          两个分开的


过程。
 之后,我们将理解总线、设备驱动device_driver、设备device的区别:
          (1) 总线类型(bus_type)具有驱动(device_driver)与设备(device)的属性
          (2) device包含device_driver和bus_type的类型
          (3)device_driver包含bus_type的类型
         device_driver和device分别表示驱动和设备,而这两者是必须依附于一种总线,因此包含


struct bus_type指针。在内核中,设备和驱动是分开注册的,注册1个设备的时候,并不需要驱动已经


存在,而一个驱动被注册的时候,也不需要对应的设备已经被注册。设备与驱动各自涌向内核,而每个


设备和驱动都会寻找彼此,其中bus_type的match()成员将两者绑在一起。即设备与驱动是通过bus_type


中的match()牵的红线!!!
         device、bus_type、device_driver都包含了kobject类,其分别通过直接kobject kobj成员、


间接的bus_type_private和driver_private间接包含。而kobject对应于sysfs的1个目录。
         device_driver和device都包含bus_type类型,而bus_type包含了device_attibute和


driver_attibute,而attibute具有show()和store()函数完成对应的sysfs的读和写。(即device和


device都对相应sysfs文件节点(inode)进行读写,sysfs即内核文件系统目录视图)


二、字符设备文件和块设备文件的区别:
  1.字符设备没有上层的磁盘文件系统,因此file_operation成员函数直接由驱动直接提供,所以


file_operation是字符设备的核心。
  2、而块设备中的ext2、fats、jffas等文件系统实现了针对VFS(虚拟文件系统)的file_operation成员


函数,设备层将看不到file_operation的存在。
  2.1磁盘文件系统和设备驱动将会把对磁盘上文件的访问转换成对磁盘上柱面和扇区的访问。
三、设备文件系统mdev的来源和作用、延伸:
  由目录可知,涉及到了文件系统,同时还涉及设备文件系统udev和基于udevs的mdev,
其中的sysfs是安装在/sys目录下内核可视的硬件层文件系统,udev即是基于从它其中的
打印信息进行设备文件的创建,删除。udev是从用户态进行创建,而不是内核态。
  mdev分为几个部分namedev、libdev、mdev三个部分,其中的namedev根据内核打印信息对文件以一定


的规则命名,然后创建设备文件节点。同时对于可热插拔的设备进行识别。
  mdev是轻量级的devfs,可由busybox进行创建。
  


tips:
  linux 中的系统调用和C库函数都能在用户空间中进行编程.


四、cdev与file_operation:
    cdev为字符设备结构体,其中包含的成员决定了它的属性。
    cdev->ops   (stuct file_operation *ops)
    cdev->dev_t (dev_t为设备号 dev_t dev[31:20]为主设备号,dev_t dev[19:0]为此设备号)
    cdev->kobject(对应着sysfs的一个目录)
    cdev->module (struct module *owner所属模块)
    cdev->list_head_list;






五、(1)对定时器捕获实验(刘魏_裸机.PWM实验)的理解分析:
       在TIM5的中断函数中,引起中断的原因有两个:1.定时器溢出的更新事件
        2.捕获发生引起
    这两个中断在TIM5->DIER的UIE/CC1IE位进行设置,使其都可以产生中断。
    
    为什么更新事件会引起中断?
    (2)更新事件:
      对于更新事件,不是定时器溢出、UG置1就会产生更新事件,更新事件的使能在TIM5->CR1的UDIS
    中位,决定了更新事件是否使能。
      更新事件的使能的作用:更新事件发生ARR、PSC、CCRx的值将从预装载寄存器中重新送值,达到重
    新初始化的目的。(预装载的作用在之前解释!!!!!)
      另一方面,更新事件产生中断也必须使能,在TIM5->CR1的URS中设置。这样遇到更新事件,也会
    进入响应定时器的中断服务程序中去。
      更新事件和捕获时间引起的中断标志在TIM5->SR,对应着UIF和CC1IF位。可以通过这两个标志位  


    来查看是否中断发生,或者是哪个事件引起的中断的发生。 


   (3)定时器捕获实验中断的脉冲计时方法:
        第一次低变高的过程,TIM5->CNT的值被TIM5->CCR1所捕获,但是这个值无意义。有两种方式处 


     理:1.记录该值,然后让定时器继续计数,最后在第二次捕获其值。最后计算总共的时间。


          2.不要改值,定时器清0后,时间以此为起点,开始计时,经过n个定时器溢出时间,加上一  


          次捕获的值即可计算得到脉冲持续时间。
       对比以上两种方法,明显第二种方法更加优异,降低了计算的难度,同时程序的书写更加简单。 


 
  (4)关于TIM5_CAPTURE_STA中各位的作用:
        TIM5_CAPTURE_STA[7]位用来完成脉冲持续时间的捕获。
        TIM5_CAPTURE_STA[6]位,主要用来判断是第一次上升沿还是第二次的下降沿。通过&0x40,可  


      以判断出来,从而针对不同情况,进行处理。大概的处理都包括对将TIM5_CAPTURE_STA[6]重置
、计数器零、读取捕获值、进行触发方式改变。


struct cdev{
      struct kobject kobj;
      struct module *owner;
      struct file_operation *ops;
      struct list_head list;
      dev_t dev;
      unsigned int count;
}


cdev结构体中的file_operation定义了字符设备驱动提供给虚拟文件系统的接口函数。


void cdev_init(struct cdev *cdev,struct file_operation *ops)
{
memset(cdev, 0 ,sizeof *cdev);
        INIT_LIST_HEAD(&cdev->list);
  kobject_init(&cdev->kobj, &ktype_cdev_default);
        cdev->ops = fops;   //将传入的文件操作结构体指针赋值给cdev的ops;
}
struct cdev  *cdevalloc(void)
{
struct cdev *p = kzalloc(sizeof(struct cdev),GFP_KERNEL);
        if(p)
      {
INIT_LIST_HEAD(&p->list);
kobject_init(&p->kobj,&ktype_cdev_dynamic);
}
return p;
}


《6.27》
     关于ATK-RM04 WIFI模块的作用:
     1.串口-以太网模式: 电脑串口助手->(网线连接到)路由器->(网线连接到)ATK WIFI模块
       为什么上面的例程中,电脑可以直接用网线连接到ATK-RM04 WIFI模块??????
       解释:
     2.串口-无线网卡模式:电脑串口助手->(网线或无线)路由器(开启WIFI_DHCP功能)->ATK WIFI     


 (WIFI STA模式) (WIFI连接到)路由器
       注:此时模块WIFI STA模式,路由器开启WIFI_DHCP功能。
       WIFI连接和无线网卡有什么区别?
     3.串口-无线接入点模式:ATK-RM04模块(WIFI AP(开启DHCP功能))<-->智能手机(WIFI STA)
     总结:2、3例子中,第三个模式中ATK-RM04的作用充当了路由器功能,而智能手机则变成了开启

         WIFI功能的第二模式中的ATK-RM04模块作用。  

《6.28》
    MY_NVIC_Init(3,2,IRQn,2)的函数设置意义:
      其中最后一个参数2代表分组,即[7:5]为抢占优先级,[4:0]为亚优先级
    ,上述设置的寄存器为《AIRCR》.
      而前两个参数3、2分别设置的是《中断优先级寄存器》,每个占8位,根据优先
    级分组PRI_GROUP,对不同位段送数据。


    UCOSII中的重要几个与cpu相关文件分析:
    UCOSII与处理器有关的代码:oc_cpu.h os_cpu_a.asm os_cpu_c.c
    UCOSII的移植,我们只需要修改以上三个文件即可,其中os_cpu.h,
    进行了数据类型的定义,以及处理器的相关代码和几个函数原型。


os_cpu.h
    #define    OS_CRITICAL_METHOD 3   //设置访问临界区的方法
    #if   OS_CRITICAL_METHOD==3 
    #DEFINE  OS_ENTER_CRITICAL()      {cpu_sr=OS_CPU_SR_Save();}
    #DEFINE  OS_EXIT_CRITICAL()       {OS_CPU_SR_Restore();}
    #endif
os_cpu_a.a    
OS_CPU_SR_Save     
    MRS  R0,PRIMASK            //PRIMASK的值读到R0,R0为返回值
                               //
to mask all(except faults)      
    CPSID I
    BX    LR    


OS_CPU_SR_Restore
    MSR   PRIMASK,R0
    BX    LR
     
    
    回顾思考,(1).LR(r14)在调试中的作用:
                               1. 当使用bx或blx跳转到子程序时,
              2. 
     (2).PC(r15)在调试中的作用: 程序计数器,当程序运行到哪里就指向哪里,同时也可以
通过改变PC来实现程序的跳转。  
     (3).CP(r16)在调试中的作用:在任何模式下对它能进行访问,包括条件标志位、中断   
                                         禁止位、当前处理器模式标志位,以及其他控制标志位。
     (4).SP在调试中的作用:其含义为Saved Program Status Register. 当出现异常时,保
                    存CP中的值,异常退出时,回复CP的值。用户和系统模式下没 有SP寄存器,访问它是未知的。
           常见程序:                   
     跳转的bl 标号和ldr pc,=标号的区别:
              ldr   pc,=MAIN   


              bl    MAIN          //bl会自动将当前pc传至lr,bl为跳转带链接的作用
              MAIN:
...
...
mov pc,lr
以下假设:
芯片 FLASH起始于0x100000,共64kB,片上RAM起始于0x200000,共16kB.
芯片 复位之后,程序会从0开始执行,此时FLASH被映射到0地址,因此,芯片可以取得指令并执行.显然,此
时还是驻留在0x100000地址.如果使用remap命令,将会把RAM映射到0地址,同样的这时0地址的内容也只是


RAM的镜像.
假定有如下程序:
       RESET
                   B       INIT        或者   LDR      PC,=INIT
                   …


       INIT
                   …
    其中RESET为起始时的代码,也就是这条代码的偏移为0,设INIT的偏移量为offset.如果将这段程序按
照RO=0x100000编译, 那么B INIT可理解为ADD   PC, PC, #offset,而LDR     PC,=INIT可被理解为 MOV 
PC,#(RO+offset) .显然当系统复位时,程序从0开始运行,而0地址有FLASH的副本,执行B     INIT将把PC
指向位于0地址处的镜像代码位置,也即INIT(应该是offset,by imjacob);如果执行LDR    PC,=INIT
将会将PC直接指向位于FLASH中的原始代码.(应该是 0x100000 + offset,by imjacob)因此以上两者都能


正确运行.
   下面将RO设置为0x200000,编译后生成代码,还是得 烧写到FLASH中,也就是还是0x100000,系统复位后
从0地址执行,还是FLASH的副本,此时执行B     INIT,将跳到副本中的INIT位置执行(此时是
0x100000+offset 还是 offset?,by imjacob),此处有对应的代码;但是如果执行LDR     PC,=INIT,
将向PC加载0x200000+offset,这将使得PC跳到RAM中,而此时由于代码没有复制,RAM中的指定位置并没有
代码,程 序无法运行(应该是 0x200000 + offset,by imjacob).
      


       (2)
              ldr   r0,=0x56000000
              mov   r1,#0
              str   [r0],r0
              
              mov和ldr/str的区别:
              对于ldr r0,0x12345678的作用是将0x12345678地址上的值传递给r0寄存器。
              ldr伪指令:
 ldr r0,=0x12345678的作用是将0x12345678传递给r0寄存器。
              该指令与mov的作用是相似的,但由于mov只能操作8位的立即数,就是不能超过512.而
 ldr则没有这个限制。
              总结:ldr与ldr伪指令意义不同,ldr伪指令和mov意义相似, 
                    即ldr .,=xxx   中ldr可看成mov  ,而xxx标号看成立即数。  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值