BLACKfin的VDK学习

本文原创,未完待续

 

 

1、VDK的使用

A:线程和优先级

      Blackfin处理器有 31个优先级,任何线程都能够在这些优先级上运行。

      在任意时刻,系统上能够运行任意多个线程(可以多于 31个),实际上在很多时候,应用程序在某个优先级上都会有不止一个线程在运行 。对不同优先级的调度十分简单,完全由优先权决定,并且强制操作系统执行。也就是说,能够运行且具有最高优先级的线程将一直完全占据处理器,直到发生一些情况迫使这一线程被搁置。

      当多个线程运行于同一个优先级上时,有协同式多任务和时间片两种模式

 

      协同式多任务:

      两个线程之间是协同或合作的关系。处理器的控制权在两个线程之间来回传递,使得处理器工作在两个不同的线程之间

    

      时间片模式:

      操作系统或 VDK会自动地将操作系统的控制权以轮转调度或时间片的方式在所有线程之间进行传递。每个线程所得到的处理器控制时间的长度由程序员定义。优先级可以被静态地分配,也可以被动态地分配。静态分配意味着应用程序在创建时就已经被指定好了优先级。动态分配则意味着程序的优先级在其运行时仍能被改变,也就是说在线程实体化时或运行时,其优先级都能被改变。

 

      线程

      线程能够在系统被引导时进行实体化,也能在随后需要运行时再实体化。实际上在系统被引导时,必须有一个线程被实体化来使得系统能够运行,否则系统将无事可做。VisualDSP会强制创建至少一个引导线程,之后你可以随意地创建任意多个线程。当然,实际
上你所能创建的线程数量会受到你的系统所能提供的内存容量的限制,但 VDK本身对其没有任何限制。

      每个线程都有自己的堆栈,用来供C编译器放置本地变量和调用堆栈。因此,你不必担心会出现两个线程意外地共享了同一个本地变量或类似的情况。它们都会有自己的堆栈拷贝,它们自己的堆栈。从最简单的层次上来看,每个线程就是实现了四个函数 — 创建函数、消除函数、运行函数和错误函数。如果大家精通C++,可以把创建和消除函数分别理解为 C++中的构造器和解构器。也就是说,它们通常是一些小函数,在创建线程时完成一些静态初始化工作。类似地,消除函数或解构器用来完成一些消除线程所必须的少量清除工作。大部分时间花费在执行运行函数上。实际上运行函数通常是不会返回的,它由“while(1) ”循环或一些其它类型的无限循环来实现,这样的循环是永远无法跳出的。如果运行函数一旦退出,线程就会被自动消除。

      线程相关API

 B:关键域/禁止调度域
     关键域和禁止调度域能被用来完成一些少量的工作,这些工作非常重要,并且不能被中断。使用过RTOS的人一定遇到过这样的情况,你需要完成一些小操作,它们非常关键以至于在执行期间操作系统必须被隔离。也就是说在关键时期内,操作系统不能再响应其它的任务。VDK提供了关键域和禁止调度域来完成这些操作。
 
      关键域所采取的行动十分极端,它们简单地关闭调度程序和所有的中断,从而让当前进程取得处理器全部的控制权,而不管其具有什么样的优先级,也不管系统当时正在做什么。当你需要完成一些非常小并且不能被中断的工作时,采用这一方法十分方便。但是这一方法在使用时必须十分小心,因为如果让处理器在关键域停留太长的时间,将无法执行中断。其它一些副作用,像中断延时,会随着在关键域停留时间的增加而等量增加。通常,此功能被用于测试和设置或读取—修改—写入操作,例如你的应用程序正在查询一个全局变量值,根据它来做出判断,然后再改变这个全局变量值。如果这一操作十分重要,并且在这段时间内系统不能被中断,那么关键域可能是你可以使用的一个好方法。
 
      禁止调度域所采取的行动就不那么极端,但它们之间是相互联系的。它所做的仅仅是禁止线程切换,因此本质上 VDK将做出让步,不允许进行时序调度,但中断还能够被执行。在右边能看到一组用于关键域和禁止调度域的 API,它们十分简单。注意它们使用的是堆栈形式的操作,你需要将关键域推入堆栈,并将其从堆栈中取出。使用堆栈形式的操作是因为,如果你正在编写一段需要进入关键域的代码,则这段代码不必去关心它自己是否已经处于一个关键域。你只需简单地让关键域出栈、压栈。完成时让关键区出栈,而不必关心当前这个函数的调用者自己是否也处于一个关键域中。 
 
C:信号量
      信号量:信号量可能是在线程之间进行同步的最简单方法。本质上,它是线程之间或一个线程的ISR之间的一种协同同步的方法。信号量通常被用来控制对一些共享资源的访问。经典的例子是我可能有一个音频信号的缓存,一个线程正在对它写入,而另一个线程同时在对它进行读取,我要确保下一个音频缓存不会覆盖这个正在被另一个线程读出的缓存。因此,我需要一个信号量来控制对缓存的访问。正在读取音频信号缓存的线程会提示,“在这段时间内请不要进行写操作。”接着要对缓存进行写操作的线程会遵守这个提示,一直等待直到信号量被清除。这样的话,两个不同的进程之间就不会出现争着访问同一块缓存或外设或其它资源的情况。
 
      大多数信号量是布尔类型的,只能表示是或否这两种情况。在我给的缓存的例子中,它只需表示能被访问或不能被访问这两种情况。但可能会出现这样的情况,一个共享资源能同时被不止一个线程访问,可能是两个或三个,或更多。在这种情况下就需要使用计数信号量,它的实现方式在本质上与一个布尔信号量相同,只是共享计数的值比1大。最后,值得注意的是信号量可以被设置成周期性的。那样操作系统就会在由应用程序定义的一段时间内,自动发布一个信号量。如果你有一个背景动画,希望在一秒钟内对其更新24次,或进行其它诸如此类的操作,你就可以使用一个周期信号量来实现。可以每隔 1/24秒发布一个信号量来更新动画,而不必通过像让一个线程休眠这样不恰当的方法来实现这一功能。在右边是一组用于信号量的 API,像我说的那样,它们的创建和消除都十分简单。你也可以静态地创建信号量,也就是在创建应用程序的过程中创建信号量,稍后我们将关注一下这个问题。

 

D:消息
      消息是在线程之间进行协作的一种更复杂的方法。消息是从一个线程到另一个线程有目标的信息传送。因此,本质上会有一个发送线程和一个接收线程。发送线程将消息按某种格式进行封装,然后传递给接收线程,接着接收线程会将消息解封,并按照应用程序的要求来进行操作。这一过程是通过空指针来实现的。如果你熟悉C语言,会发现其类似于C语言中的后门。你能够将空指针指向任意类型任意长度的数据,这样就能在系统中随意地传递数据。还有一个非常方便的地方  — 本质上你能够在线程间传递任何东西。这一切都是假设接收端的接收者已经对消息的内容有所了解,因此接收者必须能够将数据再映射回到正确的数据类型上。

 

2、VDK与 System Services互补使用

通过标准的System Services来实现硬件驱动的标准接口。

 

3、调试VDK的工具

A、Project Window Kernel Page

通过 Kernel page 可以简单的控制系统的资源,.VDK  VDK.cpp  VDK.h由系统自行生成 ,不必自己看这些代码。

B、VDK Status Window

可以用来看VDK内部线程状态

C、VDK state history

右键点选Data cursor 来显示任务转换顺序 legend来显示图例。选择区间可以扩大原来的视图

而Target Load显示CPU使用率,0%表示CPU空闲

 

4、建立VDK工程

和建立普通工程一样,区别是在工程类型选择上选择 VDK工程或者 LwIP Ethernet application(带轻量级IP协议的VDK工程)

 

修改内核资源

当修改内核资源时,记得要使用Updating the Kernel Source来修改对应的VDK.c和VDK.h文件

 

1、Clock  Frequency (MHz)   系统时钟

2、Tick Period (ms)               默认是0.1 是什么意思还不明白

3、History Buffer Size          历史窗大小

4、Instrumentation Level    使用调试等级  Full Instrumentation  全调试模式

                                                                Error Checking           只报告实时错误

                                                                None                           生成最快 最小的代码

5、Timer interrupt                使用系统的中断,可以通过下拉线选择

 

6、Maximum Running Threads  修改运行线程的最大数目

7、增加一个新的线程:Thread Types 上点右键,选择New Thread Type,给新线程命名,

 

 

8、Thread Type Properties 修改线程属性

     Priority                                Default is 5. The highest priority is 1.  1~31

     Message Enabled               Specifies whether the thread type can use VDK messaging.Default is false.

     其他属性基本不用修改

9、删除线程   在对应线程上点 delete 按照提示点选是否保留源文件在工程里

10、Boot 线程

    增加boot线程 、

    重命名boot线程和上面的类似

 

修改boot线程顺序、用于决定boot线程的先后,直接用鼠标拖,由上往下容易些。

Modifying a Boot Thread's Properties  

Thread type            修改对应的线程

Initializer                给相同的线程不同的初始值来区别

 

11、Round-Robin Priority

设定采用时间片运行的优先级   Period 是设定的时间片的大小

12、Idle Thread

这里有些不明白,准备写个信问问,

  

 

13、Semaphore

旗语最大数目

旗语堆

增加 重命名 删除一个旗语

旗语属性  初始值 最大值 旗语周期(初始延时、周期)

14、Event Bit

事件位 0 或1 ,属性是初始值

15、Event

这个Event 目前添加是灰的,不知道是什么原因

16、Interrupt

增加 Interrupt  ,选择Interrupt 级别、处理代码

删除 Interrupt

修改 Interrupt 属性

Enabled at Boot            在boot时是否使能,默认是不使能,当不使能时, 在运行时,就要根据需要打开

Entry Point                    中断接口

Source File                    源代码

 

17、IOInterface

add a device driver             添加设备驱动

Adding a Boot I/O Object    添加IO对象  这里是灰色,不知道为什么

18、Device Flag

不知道有什么用处

19、Memory Pool

好像是关于内存方面的控制

 

默认是0.1 是什么意思还不明白 

20、导出调试窗口

在History view上 选择export 选择存为剪贴板中,还是文件还是图片

 

系统会根据你选择的语言自动添加源文件

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值