raw_os扩展接口函数
- 格式:doc
- 大小:28.50 KB
- 文档页数:1
RAW ASSERT 篇把assert 单独放一篇文章,可见是多么的重要。
Raw os 提供了RAW_ASSERT 的接口。
强烈建议在产品研发阶段打开assert 功能/*enable assert for raw os*/#define CONFIG_RAW_ASSERT 1RAW_ASSERT 是一个宏,移植的时候放在raw_cpu.h 里面,比如VC 上的移植如下。
#define RAW_ASSERT(CON) if (!(CON)) {printf("file is %s\nLine is %d\n", __FILE__, __LINE__); \printf("aborted task name is %s\n", raw_task_active->task_name); \ while (1); }需要打开串口的功能,但是有的时候串口打开比较麻烦,怎么办呢。
最简单的移植是:#define RAW_ASSERT(CON) if (!(CON)) {volatile RAW_U8 dummy = 0; while (dummy==0);}但是这样的话就看不到有效debug信息,资源紧缺的话建议这样的移植#define RAW_ASSERT(CON) if (!(CON)) {volatile RAW_U8 dummy = 0; led1_on();while (dummy==0);}led1_on() 操作寄存器使能一个小灯,用来告诉用户系统出错了。
RAW_ASSERT 的时候可以串口打印任何全局变量,最常用的是打印raw_task_active 的信息告诉你是哪个任务跑的有问题,告诉你哪一行,哪一个文件,甚至哪一个函数有问题。
raw_idle_task 里面assert的话说明哪个任务栈空间不够了,那个时候不够栈空间的任务被保存到raw_task_active 然后assertraw_task_active = task_ptr;RAW_ASSERT(0);。
1、引言为了实现嵌入式系统终端连入互联网,而有必要为其引入了网络功能。
μC/OS II 是一个源代码开放的实时操作系统,但是它只是一个实时的任务调度及通信内核,并没有集成TCP/IP 通信协议,为了实现网络功能,需要在μC/OS II 移植一个轻量级的TCP/IP 通信协议LwIP。
本文主要论述μC/OS II 下通信协议LwIP 的移植以及测试。
2、LwIP 简介LwIP ( light weight IP)是瑞士计算机科学院的Adam Dunkels 等开发的一套开放TCP/IP 协议栈源代码。
LwIP 既可以移植到操作系统上,又可以在无操作系统的情况下独立运行。
LwIP 实现的重点是在保持TCP/IP 协议主要功能的基础上减少对RAM 的占用,这使LwIP 适合在低端嵌入式系统中使用。
其主要特点如下:(1)支持多网络接口下IP 转发;(2)支持ICMP 协议;(3)包括试验性扩展的UDP;(4)包括简单的拥塞控制,RTT 估算和快速恢复和快速转发的TCP;(5)提供专门的内部回调接口(Raw API)用于提高应用程序性能;(6)可选择的Berkeley 接口API;3、LwIP 协议栈移植到μC/OS II 操作系统的具体实现3.1 嵌入式系统结构和LwIP 接口整个嵌入式系统的结构如图 1 所示,由ARM 微处理器、网卡、网络设备驱动、μC/OSII 操作系统、LwIP 协议栈和应用程序组成。
图 1 嵌入式系统结构图LwIP 在设计时为了适应不同的操作系统,并没有在代码中使用和某个特定的操作系统相关的系统调用和数据结构,而是在LwIP 和操作系统之间提供了一个接口层(sys_arch interface),该接口主要实现的功能包括数据类型的定义、存储模式的选择、任务间的同步、时间和内存的管理等。
因此,完成LwIP 在μC/OS II 移植,我们就是要通过修改这个接口层来实现。
同时,还要根据自己所要实现的具体目的,可以对LwIP 协议栈进行一定的裁减。
浙江大学嵌入式ARM+LINUX高端培训课程简章课程目录卷首语 (1)嵌入式OS--Linux (1)嵌入式LINUX应用高级班 (1)嵌入式LINUX系统架构师培训班 (6)嵌入式LINUX内核实验班 (11)嵌入式OS--3G手机操作系统 (15)Android应用开发培训班(FSAD1002) (15)Android系统开发培训班(FSAD1001) (20)嵌入式OS--VxWorks (23)VxWorks应用开发培训班 (23)VxWorks BSP开发高级班 (28)嵌入式协处理器--DSP (30)TMS320C6000 DSP系统开发培训班 (30)嵌入式OS--Linux嵌入式LINUX应用高级班招生简章●课程描述详细介绍嵌入式开发流程、交叉编译环境搭建与开发工具的使用、Bootloader的原理与配置、嵌入式Linux内核的移植与根文件系统构建、高级应用编程开发技巧、嵌入式数据库系统构建与应用编程、嵌入式图形系统构建与应用编程,并通过大量实例演示使学员快速掌握嵌入式Linux开发流程及与应用相关的编程方法和技巧。
●质量保证〃所有课程内容均可免费重听,直到学员完全掌握为止。
〃凡是培训班学员,在以后工作中遇到课程相关问题,可得到免费技术支持。
〃雄厚的师资力量、经典的课程体系、丰富的教学经验确保教学质量。
●培养对象有志从事嵌入式Linux开发的工程技术人员、有兴趣深入了解嵌入式Linux 开发的技术爱好者、以及从事ARM相关工作的技术人员。
●行业需求工业控制,军工企事业,电信/网络/通讯,航空航天,汽车电子行业,医疗仪器,仪器仪表与电子。
●基础要求熟练掌握C语言编程。
具备一定的英文技术文档阅读能力对ARM(或其他嵌入式)体系结构和ARM芯片有一定的了解●教师简介浙江大学徐新民(副教授)工作研究领域嵌入式系统的应用,微机测控,智能仪器仪表,集成电路设计方法,FPGA动态重构理论与技术研究浙江大学章专(副教授)工作研究领域嵌入式系统设计与应用.现代数字集成电路设计理论研究.可编程器件应用浙江大学董利达(副教授)工作研究领域Petri网理论及其离散事件系统,嵌入式系统设计与应用浙江大学金文光(副教授)工作研究领域无线通信与嵌入式系统设计汇文教育王老师汇文教育特级讲师,浙大计算机学院资深专家,国际著名嵌入式公司资深技术骨干,曾担任某公司技术总监,擅长硬件设备(子系统)Linux驱动程序开发、硬件子系统相应SDK的研发、嵌入式芯片相关固件的研发等工作,深入理解计算机系统底层结构及各种嵌入式技术:包括以太网,PCI,TCP/IP,USB等,熟悉Linux 内核编程及驱动程序开发,多年教学经验。
python基础题1、请⾄少列举5个 PEP8 规范1、缩进:每⼀级4个缩进。
连续跨⾏应该使⽤圆括号或⼤括号或者使⽤悬挂缩进。
2、代码长度约束⼀⾏列数:PEP8 规定最⼤为79列,如果拼接url很容易超限⼀个函数:不可以超过30⾏;直观来讲就是完整显⽰⼀个函数⼀个屏幕就够了,不需要上下拖动⼀个类:不要超过200⾏代码,不要超过10个⽅法⼀个模块:不要超过500⾏3、import不要在⼀句import中引⽤多个库4、命名规范:数字字母下划线组成、不能⽤数字开头,更不能是纯数字、区分⼤⼩写、不要⽤中⽂、不能⽤关键字、推荐使⽤驼峰、不要太长5、注释 # """总体原则,错误的注释不如没有注释。
所以当⼀段代码发⽣变化时,第⼀件事就是要修改注释!2、各种进制之间的转换:答案:⼆进制转换成⼗进制:v = “0b1111011”print(int('0b1111011',2))⼗进制转换成⼆进制:v = 18print(bin(18))⼋进制转换成⼗进制:v = “011”print(int('011',8))⼗进制转换成⼋进制:v = 30print(oct(30))⼗六进制转换成⼗进制:v = “0x12”print(int('0x12',16))⼗进制转换成⼗六进制:v = 87print(hex(87))3、请编写⼀个函数实现将IP地址转换成⼀个整数如 10.3.9.12 转换规则为:10 000010103 000000119 0000100112 00001100再将以上⼆进制拼接起来计算⼗进制结果:00001010 00000011 00001001 00001100 = ?答案:def func(x): lis = x.strip().split('.') li = [bin(int(i)) for i in lis] li2 = [i.replace('0b',(10-len(i))*'0') for i in li] return int(''.join(li2),2)ret = func('10.3.9.12')print(ret)4、python递归的最⼤层数?⼀般计算机默认的最⼤递归深度在1000左右,python最⼤递归深度⼀般在4000左右,跟计算机的性能有关系,这个数不是⼀个定数,可通过⼀下⽅式测试import sysprint(sys.getrecursionlimit())print(sys.setrecursionlimit(10000))5、not、and、or求结果:v1 = 1 or 3 -------------->1v2 = 1 and 3-------------->3v3 = 0 and 2 and 1-------->0v4 = 0 and 2 or 1--------->1v5 = 0 and 2 or 1 or 4---->1v6 = 0 or Flase and 1----->False6、ascii、unicode、utf-8、gbk 区别?ASCII码:使⽤⼀个字节编码,所以它的范围基本是只有英⽂字母、数字和⼀些特殊符号,只有256个字符。
本科生毕业论文(设计)题目 A Functionalist Approach to Translation ofTourism Texts姓名商广浩学号**********院系物理工程学院专业电子信息工程指导教师王艳娜职称讲师2012年5月15日曲阜师范大学杏坛学院教务处制目录摘要 (3)关键词 (3)A BSTRACT (3)keyword (4)引言 (4)1 QT (6)1.1 QT的概念 (6)1.2 QT的发展史和前景 (7)1.3 QT的主要功能 (8)2 WINDOWS SOCKETS 网络编程的研究............ 错误!未定义书签。
2.1 TCP/IP体系结构 (5)2.2.1 TCP/IP简介 (5)2.2.2TCP/IP的特点 (5)2.2基本套接字 (5)2.3客户机/服务器模式 (7)2.4 SOCKETS程序设计 (8)2.4.1 SOCKETS API简介 (8)2.4.2WINDOWS SOCKETS机制 (9)3网络通信模块分析.......................... 错误!未定义书签。
3.1 网络通信程序设计过程 (11)3.2 网络通信程序设计核心 (13)3.2.1通信设计代码分析 (13)3.2.2数据传输代码分析 (17)3.2.3出错处理 (19)4界面模块分析 (20)4.1 服务器端界面模块分析 (20)4.2 客户端界面模块分析 (21)4.2.1用户登陆界面分析 (21)4.2.2用户聊天界面分析...................... 错误!未定义书签。
5数据库模块分析........................... 错误!未定义书签。
5.1数据库的选择 (27)5.2数据库访问方法....................... 错误!未定义书签。
5.3 ADO数据库编程....................... 错误!未定义书签。
1网络游戏开发—DirectX函数归纳总结23003李翔李森2DirectX目录1.D3D 基本框架 (1)创建D3D 对象 (2)获取显卡显示模式 (2)创建D3D 设备接口 (2)开始渲染和结束渲染 (2)清空图形绘制区 (2)屏幕反转 (2)2.绘制基本图形 (1)绘制基本图形 (4)灵活定点格式(FVF) (2)基本图元的绘制 (2)创建顶点缓冲区 (2)基本图元的绘制 (2)保存顶点 (2)设置渲染状态 (2)图形绘制 (2)索引缓冲 (4)顶点设置 (2)创建索引缓冲区 (2)保存顶点索引值 (2)索引图形绘制 (2)D3D 中的图形学 (4)D3D 中的向量 (2)D3D 中的矩阵 (2)D3D 中的平面 (2)3D3D 中的射线 (2)D3D 中的图形变换 (2)3.纹理 (4)从磁盘文件获取纹理 (2)设置当前要渲染的纹理 (2)设置纹理的渲染状态 (2)设置纹理采样属性 (2)从一张纹理图形中生成多级纹理 (2)包装纹理寻址 (2)镜像纹理寻址 (2)夹取纹理寻址 (2)边框颜色纹理寻址 (2)一次镜像纹理寻址 (2)纹理包装 (2)4.光照 (4)D3D 光照的基本实现 (4)顶点格式 (2)设置物体材质 (2)添加光源 (2)激活光照运算 (2)5.摄像机 (4)生成视图变换矩阵 (2)生成投影变换矩阵 (2)6.模型基础 (4)ID3DXMesh 接口基础 (2)ID3DXMesh 接口相关 (2)应用.X 文件 (2)7.游戏中的基本特效 (4)4检查硬件支持的深度缓冲区格式 (2)激活深度测试 (2)设置深度缓冲区更新 (2)设置深度测试函数 (2)激活Alpha 混合 (2)设置Alpha 混合计算方式 (2)设置Alpha 混合系数 (2)激活Alpha 测试 (2)设置Alpha 测试参考值 (2)设置Alpha 测试函数 (2)多边形填充模式 (2)查询设备是否支持多重采样 (2)启用多重采样的全景图形反锯齿 (2)设置多纹理混合方式 (2)激活雾化 (2)设置雾化计算方式 (2)设置雾的颜色 (2)设置雾的起始范围 (2)指数雾化浓度 (2)基于发散的雾化 (2)创建2D 字体 (2)绘制字体 (2)5创建3D 文字网格 (2)8.游戏控制................ . . . . . . . . . . . . . . . . . . . .4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ....DirectInput 实现键盘控制 (2)...........................................DirectInput 实现鼠标控制 (2)..........................................................鼠标键选 (2)9.游戏音乐音效 (4)6D3D基本框架创建D3D对象:Direct3DCreate9(D3D_SDK_VERSION)===============================================================================DirectX===============================================================================获取显卡显示模式:HRESULT GetAdapterDisplayMode(UINT Adapter, //指定显示卡序列号D3DDISPLAYMODE *pMode //存储显示模式的指针===============================================================================DirectX===============================================================================创建D3D设备接口:HRESULT CreateDevice(UINT Adapter, //显卡序列号D3DDEVTYPE DeviceType, //D3D 设备类型HWND hFocusWindow, //所属窗口句柄DWORD BehaviorFlags, //设备进行3D 运算方式D3DPRESENT_PARAMETERS *pPresentationParameters, //用于存储D3D 设备相关信息的指针IDirect3DDevice9 ** ppReturnedDeviceInterface //返回D3D 设备接口指针的地址);第二个参数DeviceType 取值:D3DDEVTYPE_HAL //硬件抽象层,通过显示硬件来完成图形渲染工作D3DDEVTYPE_REF //参考光栅器,一般用于测试显卡不支持的D3D 功能D3DDEVTYPE_SW //用于支持第三方软件第四个参数BehaviorFlags 取值:D3DCREATE_SOFTWARE_VERTEXPROCESSING //由D3D 软件进行顶点运算(常用)D3DCREATE_FPU_PRESERVE //激活双精度浮点运算或浮点运算异常检测,设置该项会降低系统性能D3DCREATE_MULTITHREADED //保___________d+_证D3D 是多线程安全的,设置该项会降低系统性能7D3DCREATE_MIXED_VERTEXPROCESSING //由混合方式进行顶点运算D3DCREATE_HARDWARE_VERTEXPROCESSING //由D3D 硬件进行顶点运算D3DCREATE_PUREDEVICE //禁用D3D 的Get*()函数,禁止D3D使用虚拟设备模拟顶点运算===============================================================================DirectX===============================================================================开始渲染和结束渲染:BeginScene(); //开始渲染……实际的渲染工作……EndScene(); //结束渲染注意:这两个函数必须成对出现,不允许交错和嵌套的发生,实际的渲染工作在这两个函数的中间进行。
ucos+lwip应用心得ucos+lwip应用心得ucos+lwip应用心得经过几天调试除掉几个bug以后,ucos+lwip在我的44b0+8019开发板上终于跑得比较稳定了.一只觉得lwip是一个不错的开放源码的tcp/ip 协议栈,想把自己对lwip的移植和理解写出来.但是由于最近比较忙,lwip的移植也是利用业余时间做的,今天写好了第一部分(lwip的process model)先贴上来,如果大家有兴趣我再接着往下写.另外我的移植参看了skyeye扬晔大侠的代码,大家可以去看看扬晔大侠的lwip在ucos上移植的文章和代码.lwip应用心得lwIP是瑞士计算机科学院(Swedish Institute of Computer Science)的Adam Dunkels等开发的一套用于嵌入式系统的开放源代码TCP/IP协议栈。
Lwip既可以移植到操作系统上,又可以在无操作系统的情况下独立运行.LwIP的特性如下:(1)支持多网络接口下的IP转发(2)支持ICMP协议(3)包括实验性扩展的的UDP(用户数据报协议)(4)包括阻塞控制,RTT估算和快速恢复和快速转发的TCP(传输控制协议)(5)提供专门的内部回调接口(Raw API)用于提高应用程序性能(6)可选择的Berkeley接口API(多线程情况下)(7)在最新的版本中支持ppp(8)新版本中增加了的IP fragment的支持.(9)支持DHCP协议,动态分配ip地址.现在网上最新的版本是V0.6.41.lwip的进程模型(process model)tcp/ip协议栈的process model一般有几种方式.1.tcp/ip协议的每一层是一个单独进程.链路层是一个进程,ip层是一个进程,tcp层是一个进程.这样的好处是网络协议的每一层都非常清晰,代码的调试和理解都非常容易.但是最大的坏处数据跨层传递时会引起上下文切换(context switch).对于接收一个TCP segment要引起3次context switch(从网卡驱动程序到链路层进程,从链路层进程到ip层进程,从ip层进程到TCP 进程).通常对于操作系统来说,任务切换是要浪费时间的.过频的context swich是不可取的.2.另外一种方式是TCP/IP协议栈在操作系统内核当中.应用程序通过操作系统的系统调用(system call)和协议栈来进行通讯.这样TCP/IP 的协议栈就限定于特定的操作系统内核了.如windows就是这种方式.3.lwip的process model:所有tcp/ip协议栈都在一个进程当中,这样tcp/ip协议栈就和操作系统内核分开了.而应用层程序既可以是单独的进程也可以驻留在tcp/ip进程中.如果应用程序是单独的进程可以通过操作系统的邮箱,消息队列等和tcp/ip进程进行通讯.如果应用层程序驻留tcp/ip进程中,那应用层程序就利用内部回调函数口(Raw API)和tcp/ip协议栈通讯.对于ucos来说进程就是一个系统任务.lwip的process model请参看下图.在图中可以看到整个tcp/ip 协议栈都在同一个任务(tcpip_thread)中.应用层程序既可以是独立的任务(如图中的tftp_thread,tcpecho_thread),也可以在tcpip_thread 中(如图左上角)中利用内部回调函数口(Raw API)和tcp/ip协议栈通讯2 Port Lwip to uCos在这个项目中我用的硬件平台是s3c44b0x+rtl8019.ucos在44b0上的移植在网上有很多大侠非常详尽的讲解和移植代码.我就不敢罗嗦了.需要说明的一点是lwip会为每个网络连接动态分配一些信号量(semaphone)和消息队列(Message Queue),当连接断开时会删掉这些semaphone和Queue.而Ucos-2.0不支持semaphone和Queue的删除,所以要选择一些较高版本的ucos.我用的是ucos-2.51.2.1 Lwip的操作系统封装层(operating system.emulation layer)Lwip为了适应不同的操作系统,在代码中没有使用和某一个操作系统相关的系统调用和数据结构.而是在lwip和操作系统之间增加了一个操作系统封装层.操作系统封装层为操作系统服务(定时,进程同步,消息传递)提供了一个统一的接口.在lwip中进程同步使用semaphone和消息传递采用”mbox”(其实在ucos的实现中我们使用的是Message Queue来实现lwip中的”mbox”,下面大家可以看到这一点)Operating system emulation layer的原代码在…/lwip/src/core/sys.c中.而和具体的操作系统相关的代码在../lwip/src/arch/sys_arch.c中.操作系统封装层的主要函数如下:void sys_init(void)//系统初始化sys_thread_t sys_thread_new(void (* function)(void *arg), void *arg,int prio)//创建一个新进程sys_mbox_t sys_mbox_new(void)//创建一个邮箱voidsys_mbox_free(sys_mbox_t mbox)//释放并删除一个邮箱voidsys_mbox_post(sys_mbox_t mbox, void *data) //发送一个消息到邮箱void sys_mbox_fetch(sys_mbox_t mbox, void **msg)//等待邮箱中的消息sys_sem_t sys_sem_new(u8_t count)//创建一个信号量void sys_sem_free(sys_sem_t sem)//释放并删除一个信号量void sys_sem_signal(sys_sem_t sem)//发送一个信号量void sys_sem_wait(sys_sem_t sem)//等待一个信号量void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)//设置一个超时事件void sys_untimeout(sys_timeout_handler h, void *arg)//删除一个超时事件…关于操作系统封装层的信息可以阅读lwip的doc目录下面的sys_arch.txt.文件.2.2 Lwip在ucos上的移植.2.2.1 系统初始化sys_int必须在tcpip协议栈任务tcpip_thread创建前被调用.#define MAX_QUEUES20#define MAX_QUEUE_ENTRIES20typedef struct {OS_EVENT*pQ;//ucos中指向事件控制块的指针void*pvQEntries;//消息队列//MAX_QUEUE_ENTRIES消息队列中最多消息数} TQ_DESCR, *PQ_DESCR;typedef PQ_DESCRsys_mbox_t;//可见lwip中的mbox其实是ucos的消息队列static char pcQueueMemoryPool CR) ];void sys_init(void){u8_t i;s8_tucErr;pQueueMem = OSMemCreate( (void*)pcQueueMemoryPool, MAX_QUEUES, sizeof(TQ_DESCR), &ucErr );//为消息队列创建内存分区//init lwip task prio offsetcurr_prio_offset = 0;//init lwip_timeouts for every lwip task//初始化lwip定时事件表,具体实现参考下面章节for(i=0;i<LWIP_TASK_MAX;i++){lwip_timeouts.next = NULL;}}2.2.2 创建一个和tcp/ip相关新进程:lwip中的进程就是ucos中的任务,创建一个新进程的代码如下:#define LWIP_STK_SIZE10*1024//和tcp/ip相关任务的堆栈大小.可以根据情况自//己设置,44b0开发板上有8M的sdram,所以设大//一点也没有关系:)//max number of lwip tasks#define LWIP_TASK_MAX5 //和tcp/ip相关的任务最多数目//first prio of lwip tasks#define LWIP_START_PRIO5 //和tcp/ip相关任务的起始优先级,在本例中优先级可//以从(5-9).注意tcpip_thread在所有tcp/ip相关进程中//应该是优先级最高的.在本例中就是优先级5//如果用户需要创建和tcp/ip无关任务,如uart任务等,//不要使用5-9的优先级OS_STK LWIP_TASK_STK;//和tcp/ip相关进程//的堆栈区u8_t curr_prio_offset ;sys_thread_t sys_thread_new(void (* function)(void *arg), void *arg,int prio){if(curr_prio_offset < LWIP_TASK_MAX){OSTaskCreate(function,(void*)0x1111, &LWIP_TASK_STK,LWIP_START_PRIO+curr_prio_offset );curr_prio_offset++;return 1;} else {// PRINT(" lwip task prio out of range ! error! ");}}从代码中可以看出tcpip_thread应该是最先创建的.2.2.3 Lwip中的定时事件在tcp/ip协议中很多时候都要用到定时,定时的实现也是tcp/ip协议栈中一个重要的部分.lwip中定时事件的数据结构如下.struct sys_timeout {struct sys_timeout *next;//指向下一个定时结构u32_t time;//定时时间sys_timeout_handler h;//定时时间到后执行的函数void *arg;//定时时间到后执行函数的参数.};struct sys_timeouts {struct sys_timeout *next;};struct sys_timeouts lwip_timeouts;Lwip中的定时事件表的结构如下图,每个和tcp/ip相关的任务的一系列定时事件组成一个单向链表.每个链表的起始指针存在lwip_timeouts的对应表项中.函数sys_arch_timeouts返回对应于当前任务的指向定时事件链表的起始指针.该指针存在lwip_timeouts中.struct sys_timeouts null_timeouts;struct sys_timeouts * sys_arch_timeouts(void){u8_t curr_prio;s16_t err,offset;OS_TCB curr_task_pcb;null_timeouts.next = NULL;//获取当前任务的优先级err = OSTaskQuery(OS_PRIO_SELF,&curr_task_pcb);curr_prio = curr_task_pcb.OSTCBPrio;offset = curr_prio - LWIP_START_PRIO;//判断当前任务优先级是不是tcp/ip相关任务,优先级5-9if(offset < 0 || offset >= LWIP_TASK_MAX){return &null_timeouts;}return &lwip_timeouts;}注意:杨晔大侠移植的代码在本函数有一个bug.杨晔大侠的.移植把上面函数中的OS_TCB curr_task_tcb定义成了全局变量,使本函数成为了一个不可重入函数.我也是在进行如下测试时发现了这个bug.我的开发板上设置的ip地址是192.168.1.95.我在windows的dos窗口内运行ping 192.168.1.95 –l 2000 –t,不间断用长度为2000的数据报进行ping测试,同时使用tftp客户端软件给192.168.1.95下载一个十几兆程序,同时再使用telnet连192.168.1.95端口7(echo端口),往该端口写数测试echo功能.在运行一段时间以后,开发板进入不再响应.我当时也是经过长时间的分析才发现是因为在低优先级任务运行ys_arch_timeouts()时被高优先级任务打断改写了curr_task_tcb的值,从而使sys_arch_timeouts 返回的指针错误,进而导致系统死锁.函数sys_timeout给当前任务增加一个定时事件:void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg){struct sys_timeouts *timeouts;struct sys_timeout *timeout, *t;timeout = memp_malloc(MEMP_SYS_TIMEOUT);//为定时事件分配内存if (timeout == NULL) {return;}timeout->next = NULL;timeout->h = h;timeout->arg = arg;timeout->time = msecs;timeouts = sys_arch_timeouts();//返回当前任务定时事件链表起始指针if (timeouts->next == NULL) {//如果链表为空直接增加该定时事件timeouts->next = timeout;return;}//如果链表不为空,对定时事件进行排序.注意定时事件中的time存储的是本事件//时间相对于前一事件的时间的差值if (timeouts->next->time > msecs) {timeouts->next->time -= msecs;timeout->next = timeouts->next;timeouts->next = timeout;} else {for(t = timeouts->next; t != NULL; t = t->next) {timeout->time -= t->time;if (t->next == NULL ||t->next->time > timeout->time) {if (t->next != NULL) {t->next->time -= timeout->time;}timeout->next = t->next;t->next = timeout;break;}}}}函数sys_untimeout从当前任务定时事件链表中删除一个定时事件void sys_untimeout(sys_timeout_handler h, void *arg){struct sys_timeouts *timeouts;struct sys_timeout *prev_t, *t;timeouts = sys_arch_timeouts();//返回当前任务定时事件链表起始指针if (timeouts->next == NULL)//如果链表为空直接返回{return;}//查找对应定时事件并从链表中删除.for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next){if ((t->h == h) && (t->arg == arg)){/* We have a match *//* Unlink from previous in list */if (prev_t == NULL)timeouts->next = t->next;&nbselse rev_t->next = t->next;/* If not the last one, add time of this one back to next */ if (t->next != NULL)t->next->time += t->time;memp_free(MEMP_SYS_TIMEOUT, t);return;}}return;}2.2.3“mbox”的实现:(1)mbox的创建sys_mbox_t sys_mbox_new(void){u8_tucErr;PQ_DESCRpQDesc;//从消息队列内存分区中得到一个内存块pQDesc = OSMemGet( pQueueMem, &ucErr );if( ucErr == OS_NO_ERR ) {//创建一个消息队列pQDesc->pQ=OSQCreate(&(pQDesc->pvQEntries), MAX_QUEUE_ENTRIES );if( pQDesc->pQ != NULL ) {return pQDesc;}}return SYS_MBOX_NULL;}(2)发一条消息给”mbox”const void * const pvNullPointer = 0xffffffff;void sys_mbox_post(sys_mbox_t mbox, void *data){INT8U err;if( !data )data = (void*)&pvNullPointer;err= OSQPost( mbox->pQ, data);}在ucos中,如果OSQPost (OS_EVENT *pevent, void *msg)中的msg==NULL 会返回一条OS_ERR_POST_NULL_PTR错误.而在lwip 中会调用sys_mbox_post(mbox,NULL)发送一条空消息,我们在本函数中把NULL变成一个常量指针0xffffffff.(3)从”mbox”中读取一条消息#define SYS_ARCH_TIMEOUT 0xffffffffvoid sys_mbox_fetch(sys_mbox_t mbox, void **msg){u32_t time;struct sys_timeouts *timeouts;struct sys_timeout *tmptimeout;sys_timeout_handler h;void *arg;again:timeouts = sys_arch_timeouts();////返回当前任务定时事件链表起始指针if (!timeouts || !timeouts->next) {//如果定时事件链表为空 sys_arch_mbox_fetch(mbox, msg, 0);//无超时等待消息} else {if (timeouts->next->time > 0) {//如果超时事件链表不为空,而且第一个超时事件的time !=0//带超时等待消息队列,超时时间等于超时事件链表中第一个超时事件的time,time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);//在后面分析中可以看到sys_arch_mbox_fetch调用了ucos中的OSQPend系统调//用从消息队列中读取消息.//如果”mbox”消息队列不为空,任务立刻返回,否则任务进入阻塞态.//需要重点说明的是sys_arch_mbox_fetch的返回值time:如果sys_arch_mbox_fetch//因为超时返回,time=SYS_ARCH_TIMEOUT,//如果sys_arch_mbox_fetch因为收到消息而返回,//time = 收到消息时刻的时间-执行sys_arch_mbox_fetch时刻的时间,单位是毫秒//由于在ucos中任务调用OSQPend系统调用进入阻塞态,到收到消息重新开始执行//这段时间没有记录下来,所以我们要简单修改ucos的源代码.(后面我们会看到).} else {//如果定时事件链表不为空,而且第一个定时事件的time ==0,表示该事件的定时//时间到time = SYS_ARCH_TIMEOUT;}if (time == SYS_ARCH_TIMEOUT) {//一个定时事件的定时时间到tmptimeout = timeouts->next;timeouts->next = tmptimeout->next;h = tmptimeout->h;arg = tmptimeout->arg;memp_free(MEMP_SYS_TIMEOUT, tmptimeout);//从内存中释放该定时事件,并执行该定时事件中的函数if (h != NULL) {h(arg);}//因为定时事件中的定时时间到或者是因为sys_arch_mbo_fetch 超时到而执行到//这里,返回本函数开头重新等待mbox的消息goto again;} else {//如果sys_arch_mbox_fetch无超时收到消息返回//则刷新定时事件链表中定时事件的time值.if (time <= timeouts-="">next->time) {timeouts->next->time -= time;} else {timeouts->next->time = 0;}}}}u32_tsys_arch_mbox_fetch(sys_mbox_t mbox, void **data, u32_t timeout){u32_tucErr;u16_t ucos_timeout;//在 lwip中 ,timeout的单位是ms// 在ucosII ,timeout 的单位是timer tickucos_timeout = 0;if(timeout != 0){ucos_timeout = (timeout )*( OS_TICKS_PER_SEC/1000);if(ucos_timeout < 1)ucos_timeout = 1;else if(ucos_timeout > 65535)ucos_timeout = 65535;}&nbs//如果data!=NULL就返回消息指针,if(data != NULL){*data = OSQPend( mbox->pQ, (u16_t)ucos_timeout, &ucErr );}else{OSQPend(mbox->pQ,(u16_t)ucos_timeout,&ucErr);}//这里修改了ucos中的OSQPend系统调用,//原来的void*OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)// err的返回值只有两种:收到消息就返回OS_NO_ERR,超时则返回OS_TIMEOUT//这里先将err从8位数据改变成了16位数据OSQPend(*pevent,timeout, INT16U *err)//重新定义了OS_TIMEOUT//在ucos中原有#define OS_TIMEOUT 20//改为 #defineOS_TIMEOUT-1//err返回值的意义也改变了,如果超时返回OS_TIMEOUT// 如果收到消息,则返回OSTCBCur->OSTCBDly修改部分代码如下//if (msg != (void *)0) { /* Did we get a message?*/// OSTCBCur->OSTCBMsg = (void *)0;// OSTCBCur->OSTCBStat= OS_STAT_RDY;// OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;//*err=OSTCBCur->OSTCBDly;//***************.12//OS_EXIT_CRITICAL();// return (msg);/* Return message received */// }//关于ucos的OSTBCur->OSTCBDly的含义请查阅ucos的书籍if( ucErr == OS_TIMEOUT ) {timeout = SYS_ARCH_TIMEOUT;} else {if(*data == (void*)&pvNullPointer )*data = NULL;//单位转换,从ucos tick->mstimeout = (ucos_timeout -ucErr)*(1000/ OS_TICKS_PER_SEC); }return timeout;}semaphone的实现和mbox类似,这里就不再重复了.。
os复制文件函数-回复OS复制文件函数是操作系统提供的一种功能,用于将一个文件的内容从源文件复制到目标文件中。
这样的函数通常具有一些参数,例如源文件路径、目标文件路径和复制选项等。
通过调用这个函数,我们可以实现文件的快速复制,从而满足不同的应用需求。
在本文中,我们将详细介绍OS 复制文件函数的原理和使用方法,以及一些常见问题的解答。
首先,我们需要了解复制文件的原理。
在操作系统中,文件是以字节流的形式存储的。
因此,复制文件的本质就是将源文件的字节流读取出来,并写入到目标文件中。
这个过程可以通过以下几个步骤来实现:1. 打开源文件和目标文件:在调用OS复制文件函数之前,我们需要先打开源文件和目标文件。
这可以通过调用操作系统提供的文件打开函数来完成。
在打开文件时,需要指定文件的路径和一些权限选项。
2. 读取源文件的字节流:一旦源文件打开成功,我们可以通过调用操作系统提供的文件读取函数来逐个字节地读取源文件的内容。
通常,读取的字节数会保存在一个缓冲区中,以便后续的处理。
3. 写入目标文件的字节流:读取源文件的字节流后,我们需要将其逐个字节地写入到目标文件中。
这可以通过调用操作系统提供的文件写入函数来完成。
与读取函数类似,写入函数也需要指定写入的字节流和缓冲区的大小等参数。
4. 关闭文件:在复制完成后,我们需要关闭源文件和目标文件。
这可以通过调用操作系统提供的文件关闭函数来实现。
关闭文件可以释放系统资源,并确保文件的正确关闭。
有了上述的原理介绍之后,我们可以开始使用OS复制文件函数了。
首先,我们需要确定源文件路径和目标文件路径。
这些路径可以是绝对路径,也可以是相对路径。
对于绝对路径,我们需要指定完整的文件路径,例如"C:\Documents\source.txt"。
而对于相对路径,我们可以使用当前目录和文件名的组合来指定路径,例如"source.txt"。
在调用OS复制文件函数之前,我们还需要检查源文件和目标文件是否存在。
open core使用方法OpenCore是一款开源的macOS引导工具,它可以帮助您在非苹果电脑上安装和运行macOS系统。
以下是使用OpenCore的基本步骤:1. 首先,您需要下载和安装OpenCore。
可以在GitHub上找到OpenCore的最新版本。
2. 下载完成后,解压压缩文件,并将OpenCore安装到您的启动盘上。
3. 制作启动盘时,您需要使用一个空的USB闪存驱动器。
确保它至少有8GB的容量,并将其连接到您的计算机上。
4. 打开终端应用程序,并使用以下命令格式化USB闪存驱动器:```bashdiskutil eraseDisk JHFS+ /dev/disk2s1```这将格式化USB闪存驱动器为macOS扩展(JHFS+)格式。
5. 接下来,使用以下命令将OpenCore安装到USB闪存驱动器上:```bash./createinstallmedia --volume /Volumes/YourVolumeName --nointeraction```其中“YourVolumeName”是您要安装OpenCore的USB闪存驱动器的卷名。
6. 等待安装完成,然后断开USB闪存驱动器,将其插入您的目标计算机。
7. 重启计算机,并在启动时按下相应的键(通常是F12或ESC),以选择从哪个介质启动。
选择您的USB闪存驱动器,然后按Enter键。
8. 在macOS安装界面中,选择“重新安装macOS”选项,并按照屏幕上的指示进行操作。
这将开始安装macOS的过程。
9. 安装完成后,您的计算机将自动重启,并进入macOS系统。
这些是使用OpenCore的基本步骤。
需要注意的是,在使用OpenCore之前,您需要了解macOS系统的基本知识和计算机硬件的要求。
如果您不确定如何进行操作,建议先咨询专业人士或专家。
iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数iwpriv是处理下面的wlan_private_args的所有扩展命令,iwpriv的实现上,是这样的, =>main=>set_private=>iw_get_priv_info获取wireless网卡所能处理的所有wlan_private_args类型. dev_ioctl=>wext_handle_ioctl=>wireless_process_ioctlif(cmd == SIOCGIWPRIV && dev->wireless_handlers)return ioctl_standard_call(dev, ifr, cmd,&iw_handler_get_private);static int ioctl_standard_call(struct net_device *dev,struct ifreq *ifr,unsigned int cmd,iw_handler handler){.../* Call the handler */ret = handler(dev,&info,&(iwr->u), extra);if(user_length < iwr->u.data.length){kfree(extra);return-E2BIG;//通知iwpriv,本wifi网卡对应的private命令还没有完,还有,这样iwpriv将会继续//maxpriv默认为16,即将以16个为一组,一组一组的从wifi网卡驱动读取该网卡所能支持的所有private_args参数//newpriv = realloc(priv, maxpriv * sizeof(priv[0]));继续申请,继续拷贝,知道将wifi 网卡自定义的wlan_private_args参数全部//传出到iwpriv为止.}...}/* New driver API : try to find the handler */handler = get_handler(dev, cmd);//获取if(handler){/* Standard and private are not the same */if(cmd < SIOCIWFIRSTPRIV)return ioctl_standard_call(dev, ifr, cmd, handler);else//如果有对应的handler,那么处理iwpriv的命令,可以我们的iwpriv都是由dev->do_ioctl完成的.return ioctl_private_call(dev, ifr, cmd, handler);}/* Old driver API : call driver ioctl handler */if(dev->do_ioctl)//如果dev->wireless_handlers->standard和dev->wireless_handlers->private[index都不对该cmd作处理,那么由//dev->do_ioctl = wlan_do_ioctl;我们驱动的最后处理函数wlan_do_ioctl处理.return dev->do_ioctl(dev, ifr, cmd);static iw_handler get_handler(struct net_device *dev,unsigned int cmd){/* Don't "optimise" the following variable, it will crash */unsigned int index;/* *MUST* be unsigned *//* Check if we have some wireless handlers defined */if(dev->wireless_handlers ==NULL)return NULL;/* Try as a standard command */index = cmd - SIOCIWFIRST;if(index < dev->wireless_handlers->num_standard)return dev->wireless_handlers->standard[index];/* Try as a private command */index = cmd - SIOCIWFIRSTPRIV;//if(index < dev->wireless_handlers->num_private)return dev->wireless_handlers->private[index];//该private命令的handler./* Not found */return NULL;}下面wlan_private_args为本wifi网卡驱动的所能支持的所有命令,也就是iwpriv命令所能支持的所有命令struct iw_handler_def wlan_handler_def ={num_standard:sizeof(wlan_handler)/sizeof(iw_handler),num_private:sizeof(wlan_private_handler)/sizeof(iw_handler),num_private_args:sizeof(wlan_private_args)/sizeof(struct iw_priv_args), standard:(iw_handler *) wlan_handler,private:(iw_handler *) wlan_private_handler,private_args:(struct iw_priv_args *) wlan_private_args,#if WIRELESS_EXT > 20get_wireless_stats:wlan_get_wireless_stats,#endif};以下为示意代码,我们的wifi网卡驱动支持如下iwpriv命令. static const struct iw_priv_args wlan_private_args[] = { "extscan""hostcmd""arpfilter""regrdwr""sdcmd52rw""sdcmd53rw""setgetconf""getcis""scantype""deauth""getNF""getRSSI""bgscan""enable11d""adhocgrate""sdioclock""wmm""uapsdnullgen""setcoalescing""adhocgprot""setpowercons""wmm_qosinfo""lolisteninter""fwwakeupmethod""psnullinterval""bcnmisto""adhocawakepd""moduletype""autodeepsleep""enhanceps""wakeupmt""setrxant""settxant""authalgs""encryptionmode""setregioncode""setlisteninter""setmultipledtim""setbcnavg""setdataavg"associate""getregioncode" "getlisteninter" "getmultipledtim" "gettxrate" "getbcnavg" "getdataavg" "getrxant" "gettxant" "gettsf" "wpssession" "deepsleep" "adhocstop" "radioon" "radiooff" "rmaeskey" "crypto_test" "reasso-on" "reasso-off" "wlanidle-on" "wlanidle-off" "sleepparams" "requesttpc" "powercap" "measreq""bca-ts" "scanmode" "getadhocstatus" "setgenie" "getgenie" "qstatus""ts_status" "setaeskey" "getaeskey" "version" "verext" "setwpaie" "setband" "setadhocch" "chanswann" "getband" "getadhocch" "getlog" "tpccfg" "scanprobes""ledgpio""sleeppd""rateadapt""getSNR""getrate""getrxinfo""atimwindow""bcninterval""sdiopullctrl""scantime""sysclock""txcontrol""hscfg""hssetpara""inactoext""dbgscfg""drvdbg""drvdelaymax""intfctrl""setquietie""""setuserscan""getscantable""setmrvltlv""getassocrsp""addts""delts""qconfig""qstats""txpktstats""getcfptable""mefcfg""getmem"};浅析ethx网卡控制函数ioctl实现具体流程====================1.应用层程序iwprivwireless tools网络配置应用程序iwpriv命令格式: iwpriv ethX private-command [parameters] iwpriv部分实现源码如下:int main(int argc, char *argv[]){...sockfd = socket(AF_INET, SOCK_STREAM, 0);...ioctl(sockfd, ioctl_val, &iwr);//将控制命令通过ioctl发送到无线网卡...}====================2.系统调用sys_ioctl应用层通过ioctl(sockfd, ioctl_val, &iwr);触发sys_ioctl系统调用,实际流程:sys_ioctl=>vfs_ioctl=>do_ioctl=最后调用filp->f_op->unlocked_ioctl执行具体的ioctl操作,该操作就是sock_ioctl,至于为什么是sock_ioctl,后边作了进一步分析sock_ioctl=>{...#ifdef CONFIG_WIRELESS_EXTif (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {err = dev_ioctl(net, cmd, argp);//} else#endif...}dev_ioctl=>wext_handle_ioctl{.../* T ake care of Wireless Extensions */if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)return wext_handle_ioctl(net, &ifr, cmd, arg);...}wext_handle_ioctl=>wireless_process_ioctl=>然后通过if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL)函数, 从系统管理的net链表中,把ioctl指定的ethX对应的struct net_device摘出来,最后调用ioctl_private_call(handler)或者调用dev->do_ioctl(dev, ifr, cmd)来处理该ioctl,这两个函数分别指向wlan_handler_def和wlan_do_ioctl====================3.wifi网卡是怎么登记到kernel上的wlan_probe()=>wlan_add_card()=>alloc_etherdev()=>之后将操作方法添加到struct net_device *dev=alloc_etherdev()申请的dev上去,其中包括:.../* Setup the OS Interface to our functions */dev->open = wlan_open;dev->hard_start_xmit = wlan_hard_start_xmit;dev->stop = wlan_close;dev->do_ioctl = wlan_do_ioctl;dev->set_mac_address = wlan_set_mac_address;dev->tx_timeout = wlan_tx_timeout;dev->get_stats = wlan_get_stats;dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;dev->wireless_handlers = (struct iw_handler_def *) &wlan_handler_def;dev->set_multicast_list = wlan_set_multicast_list;...4.socket系统调用如何关联上ioctl和ethX设备asmlinkage long sys_socket(int family, int type, int protocol);sys_socket=>sock_create=>__sock_create=>sock = sock_alloc();通过sock_mnt->mnt_sb从socket文件系统的超级块上申请一个inode节点,这样也就同时获得了由该inode描述的一个sock结构体单元,所以sokcet和dentry目录项等效,接下来从net_families全局管理结构体中找到当前family对应的ops操作集,net_proto_family *pf=net_families[family];pf->create(net, sock, protocol);//核心调用,对于ipv4,就是inet_create以ipv4为例static struct net_proto_family inet_family_ops = {.family = PF_INET,.create = inet_create,.owner = THIS_MODULE,};还记得上面应用层创建sokcet的函数吧,sockfd = socket(AF_INET, SOCK_STREAM, 0);//AF_INET虽然等于PF_INET,但是因为种种原因我们提倡使用PF_INET可见family等于AF_INET,type等于SOCK_STREAM,协议protocol为0,也就是采用IP 协议,inet_create=>inetsw[sock->type]也就是inetsw[SOCK_STREAM],从inetsw[sock->type]中找到已经登记的protocol网络协议处理函数,inetsw[]是怎么填充的呢?inet_init()=>inet_register_protosw(inetsw_array)=>这样inetsw_array中的所有protocol处理模块都将登记到inetsw中了,static struct inet_protosw inetsw_array[] ={{.type = SOCK_STREAM,.protocol = IPPROTO_TCP,.prot = &tcp_prot,.ops = &inet_stream_ops,.capability = -1,.no_check = 0,.flags = INET_PROTOSW_PERMANENT | INET_PROTOSW_ICSK, },{.type = SOCK_DGRAM,.protocol = IPPROTO_UDP,.prot = &udp_prot,.ops = &inet_dgram_ops,.capability = -1,.no_check = UDP_CSUM_DEFAULT,.flags = INET_PROTOSW_PERMANENT,},{.type = SOCK_RAW,.protocol = IPPROTO_IP, /* wild card */.prot = &raw_prot,.ops = &inet_sockraw_ops,.capability = CAP_NET_RAW,.no_check = UDP_CSUM_DEFAULT,.flags = INET_PROTOSW_REUSE,}};至于inet_init,则是以fs_initcall(inet_init)方式,以5号优先级被build in到了内核中,当kernel启动时会在start_kernel=>rest_init=>kernel_init=>do_basic_setup=>do_initcalls中依据优先级号优先于其他module驱动被调用.这样sock->ops = answer->ops;对于ipv4也就等于inet_stream_ops,接下来就是将ops填充到file操作指针中了,sys_socket=>sock_map_fd=>sock_attach_fd=>dentry->d_op = &sockfs_dentry_operations;init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE,&socket_file_ops);file->private_data = sock;其中init_file=>file->f_op = fop;也就是file->f_op = socket_file_ops;所以read(),wirte(),poll()和ioctl()应用程序调用的file->f_op就是socket_file_ops 了,比如:read()对应sock_aio_read网络异步读write()对应sock_aio_write网络异步写ioctl()对应sock_ioctlsocket_file_ops结构体具体实现如下:static const struct file_operations socket_file_ops = {.owner = THIS_MODULE,.llseek = no_llseek,.aio_read = sock_aio_read,.aio_write = sock_aio_write,.poll = sock_poll,.unlocked_ioctl = sock_ioctl,#ifdef CONFIG_COMPAT.compat_ioctl = compat_sock_ioctl,#endif.mmap = sock_mmap,.open = sock_no_open, /* special open code to disallow open via /proc */.release = sock_close,.fasync = sock_fasync,.sendpage = sock_sendpage,.splice_write = generic_splice_sendpage,};网卡控制因为涉及到的知识点比较多,上面只是从宏观上对数据流程做了一个简单的介绍,深入到其中的每个知识点,都会牵扯出一系列文章,读者需要自己去一个个的慢慢深入,希望本文能够对刚刚接触网络驱动的读者有所帮助和启发【gliethttp.Leith】wireless extention扩展接口Blog作者的回复:wlan_add_card=>wlan_create_thread(wlan_service_main_thread, &priv->MainThread,"wlan_main_service");=>wlan_service_main_thread=>wlan_exec_next_cmd=>将调用wlan_enter_ps和wlan_exit_pssbi_interrupt=>从sdio口上传来的中断数据,sdio_irq_thread=>process_sdio_pending_irqs=>调用func->irq_handler(func);即本.在mmc_signal_sdio_irq=>将调用wake_up_process(host->sdio_irq_thread);来唤醒该irq处理线程,可能还有其他命令需要处理wlan_exec_next_cmd这个pxamci_irq就是mmc的物理irq中断了,pxamci_irq=>mmc_signal_sdio_irq(host->mmc);wlan_exec_next_cmd=>只要cmd链表上CmdNode还存在,那么就会执行wlan_dnld_cmd_to_fw(wlan_private * priv, CmdCtrlNode * CmdNode)将CmdNode中的数据下发下去,然后重新触发wlan_mod_timer(&Adapter->MrvDrvCommandTimer,MRVDRV_TIMER_5S);也就是wlan_cmd_timeout_func命令超时处理函数,在cmd已经有了恢复之后,在主线程中调用wlan_process_cmdresp,立即调用wlan_cancel_timer(&Adapter->MrvDrvCommandTimer);来删除定时器wlan_service_main_thread=>每次唤醒都会检查====/* Execute the next command */if (!priv->wlan_dev.cmd_sent && !Adapter->CurCmd)wlan_exec_next_cmd(priv);====wlan_prepare_cmd=>wlan_hostcmd_ioctl=>获取一个空闲的CmdNode节点wlan_get_cmd_node,当完成赋值之后,执行如下语句,将CmdNode节点添加到处理队列中:wlan_insert_cmd_to_pending_q(Adapter, CmdNode, TRUE);wake_up_interruptible(&priv->MainThread.waitQ);另外在数组中/** iwconfig settable callbacks*/static const iw_handler wlan_handler[]这个数组中全部是回调函数,/** wlan_handler_def */struct iw_handler_def wlan_handler_def = {num_standard:sizeof(wlan_handler) / sizeof(iw_handler),num_private:sizeof(wlan_private_handler) / sizeof(iw_handler),num_private_args:sizeof(wlan_private_args) / sizeof(struct iw_priv_args), standard:(iw_handler *) wlan_handler,private:(iw_handler *) wlan_private_handler,private_args:(struct iw_priv_args *) wlan_private_args,#if WIRELESS_EXT > 20get_wireless_stats:wlan_get_wireless_stats,#endif};在wlan_add_card函数中dev->wireless_handlers = (struct iw_handler_def *) &wlan_handler_def;===============在kernel的net中使用wireless extention扩展接口static iw_handler get_handler(struct net_device *dev, unsigned int cmd) {/* Don't "optimise" the following variable, it will crash */unsigned int index; /* *MUST* be unsigned *//* Check if we have some wireless handlers defined */if (dev->wireless_handlers == NULL)return NULL;/* Try as a standard command */index = cmd - SIOCIWFIRST;if (index < dev->wireless_handlers->num_standard)return dev->wireless_handlers->standard[index];/* Try as a private command */index = cmd - SIOCIWFIRSTPRIV;if (index < dev->wireless_handlers->num_private)return dev->wireless_handlers->private[index];/* Not found */return NULL;}=>sock_ioctl=>dev_ioctl+++/* T ake care of Wireless Extensions */+++if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)+++return wext_handle_ioctl(net, &ifr, cmd, arg);=>wext_handle_ioctl=>wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd) =>get_handler(dev, cmd);如果没有实现该cmd,那么将调用dev->do_ioctl来处理, wlan_reassoc_timer_func=>wmm_start_queue=>wlan_tx_packet=>wlan_tx_timeout=>wlan_remove_card=>wlan_hostcmd_ioctl=>wlan_auto_deep_sleep=>wlan_set_deep_sleep=>wlan_prepare_cmd=>wlan_cmd_timeout_func=>将调用wake_up_interruptible(&priv->MainThread.waitQ);唤醒wlan_service_main_thread主处理线程.wlan_hard_start_xmit=>wlan_tx_packet发送数据包dev->tx_timeout = wlan_tx_timeout;wlan_initialize_timer(&Adapter->MrvDrvCommandTimer,wlan_cmd_timeout_func, priv);int wlan_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd){...case WLAN_WAKEUP_MT:if (wrq->u.data.length > 0)Adapter->IntCounter++;wake_up_interruptible(&priv->MainThread.waitQ);break;...}在wlan_process_cmdresp()处理完该cmd之后,调用wlan_insert_cmd_to_free_q=>wlan_clean_cmd_noder,从命令链表上删除已经处理完成的cmd_node,wlan_clean_cmd_noder然后pTempNode->CmdWaitQWoken = TRUE;同时如果该cmd_node是一个被阻塞等待的,那么唤醒等待的程序. wake_up_interruptible(&pTempNode->cmdwait_q);。
MounRiver Studio 帮助手册1MounRiver Studio 帮助手册V1.40目录一、概述............................................................................ 2二、计算机配置要求.................................................................. 22.1 最低配置.................................................................... 22.2 推荐配置.................................................................... 2三、MounRiver Studio安装 ........................................................... 2四、MounRiver Studio 环境........................................................... 44.1 菜单栏...................................................................... 44.2 快捷工具栏.................................................................. 94.3 工程目录窗口.............................................................. 104.4 其他显示窗口.............................................................. 11五、MounRiver Studio 工程......................................................... 115.1 新建工程.................................................................. 115.2 打开工程.................................................................. 125.3 导入KEIL工程............................................................. 125.4 编译...................................................................... 145.5 调试...................................................................... 235.6下载...................................................................... 255.7工程导出为模板............................................................ 285.8 工程模板管理.............................................................. 28六、快速问答...................................................................... 29七、更新......................................................................... 327.1在线更新.................................................................. 327.2离线更新.................................................................. 32八、联系我们...................................................................... 33注:WCH-LINK使用方法详见WCH-Link使用说明-V1.1.Pdf(文件位置:MRS安装路径\MounRiver\MounRiver_Studio\ExTool)MounRiver Studio 帮助手册2一、概述MounRiver Studio是一款针对嵌入式开发的集成开发环境。
pyusb常用函数及基础用法-回复PyUSB是一个用于Python的USB库,它提供了一个简单而强大的接口,用于与USB设备进行通信。
在本文中,我们将介绍PyUSB的常用函数和基础用法,以帮助你快速开始使用这个库。
首先,我们需要安装PyUSB库。
你可以使用pip命令来安装它。
在命令行中运行以下命令:pip install pyusb安装完成后,我们就可以开始使用PyUSB了。
PyUSB库提供了许多函数来管理USB设备和进行通信。
让我们逐个介绍这些函数。
1. `usb.core.find(idVendor=None, idProduct=None)`:这个函数用于查找与指定的idVendor和idProduct匹配的USB设备。
idVendor和idProduct是USB设备的厂商ID和产品ID。
如果不指定这两个参数,该函数将返回找到的第一个USB设备。
返回一个`usb.core.Device`对象。
2. `usb.core.find_all(idVendor=None, idProduct=None)`:这个函数与上一个函数相似,但它返回所有匹配的USB设备对象列表。
3. `usb.core.Device.set_configuration()`:这个函数用于设置USB设备的配置。
每个USB设备都有一个或多个配置,每个配置又包含一个或多个接口。
在与USB设备进行通信之前,我们需要先设置设备的配置。
这个函数接受一个可选的配置索引参数,默认为0,用于指定设置哪个配置。
4. `usb.core.Device.write(endpoint, data, timeout=1000)`:这个函数用于向设备的指定端点写入数据。
endpoint是一个元组,包含了端点的地址和方向(IN或OUT)。
data是要写入的数据。
timeout是超时时间,单位为毫秒。
这个函数将返回写入的字节数。
5. `usb.core.Device.read(endpoint, size, timeout=1000)`:这个函数用于从设备的指定端点读取数据。
网络游戏开发—DirectX函数归纳总结23003 李翔李森DirectX目录1.D3D基本框架 (1)创建D3D对象 (2)获取显卡显示模式 (2)创建D3D设备接口 (2)开始渲染和结束渲染 (2)清空图形绘制区 (2)屏幕反转 (2)2.绘制基本图形 (1)绘制基本图形 (4)灵活定点格式(FVF) (2)基本图元的绘制 (2)创建顶点缓冲区 (2)基本图元的绘制 (2)保存顶点 (2)设置渲染状态 (2)图形绘制 (2)索引缓冲 (4)顶点设置 (2)创建索引缓冲区 (2)保存顶点索引值 (2)索引图形绘制 (2)D3D中的图形学 (4)D3D中的向量 (2)D3D中的矩阵 (2)D3D中的平面 (2)D3D中的射线 (2)D3D中的图形变换 (2)3.纹理 (4)从磁盘文件获取纹理 (2)设置当前要渲染的纹理 (2)设置纹理的渲染状态 (2)设置纹理采样属性 (2)从一张纹理图形中生成多级纹理 (2)包装纹理寻址 (2)镜像纹理寻址 (2)夹取纹理寻址 (2)边框颜色纹理寻址 (2)一次镜像纹理寻址 (2)纹理包装 (2)4.光照 (4)D3D光照的基本实现 (4)顶点格式 (2)设置物体材质 (2)添加光源 (2)激活光照运算 (2)5.摄像机 (4)生成视图变换矩阵 (2)生成投影变换矩阵 (2)6.模型基础 (4)ID3DXMesh接口基础 (2)ID3DXMesh接口相关 (2)应用.X文件 (2)7.游戏中的基本特效 (4)检查硬件支持的深度缓冲区格式 (2)激活深度测试 (2)设置深度缓冲区更新 (2)设置深度测试函数 (2)激活Alpha混合 (2)设置Alpha混合计算方式 (2)设置Alpha混合系数 (2)激活Alpha测试 (2)设置Alpha测试参考值 (2)设置Alpha测试函数 (2)多边形填充模式 (2)查询设备是否支持多重采样 (2)启用多重采样的全景图形反锯齿 (2)设置多纹理混合方式 (2)激活雾化 (2)设置雾化计算方式 (2)设置雾的颜色 (2)设置雾的起始范围 (2)指数雾化浓度 (2)基于发散的雾化 (2)创建2D字体 (2)绘制字体 (2)创建3D文字网格 (2)8.游戏控制 (4)DirectInput实现键盘控制 (2)DirectInput实现鼠标控制 (2)鼠标键选 (2)9.游戏音乐音效 (4)D3D基本框架创建D3D对象:Direct3DCreate9(D3D_SDK_VERSION)===============================================================================DirectX=============================================================================== 获取显卡显示模式:HRESULT GetAdapterDisplayMode(UINT Adapter, //指定显示卡序列号D3DDISPLAYMODE *pMode //存储显示模式的指针);===============================================================================DirectX=============================================================================== 创建D3D 设备接口:HRESULT CreateDevice(UINT Adapter, //显卡序列号D3DDEVTYPE DeviceType, //D3D设备类型HWND hFocusWindow, //所属窗口句柄DWORD BehaviorFlags, //设备进行3D运算方式D3DPRESENT_PARAMETERS *pPresentationParameters, //用于存储D3D设备相关信息的指针IDirect3DDevice9 ** ppReturnedDeviceInterface //返回D3D设备接口指针的地址);第二个参数DeviceType取值:D3DDEVTYPE_HAL //硬件抽象层,通过显示硬件来完成图形渲染工作D3DDEVTYPE_REF //参考光栅器,一般用于测试显卡不支持的D3D功能D3DDEVTYPE_SW //用于支持第三方软件第四个参数BehaviorFlags取值:D3DCREATE_SOFTWARE_VERTEXPROCESSING //由D3D软件进行顶点运算(常用)D3DCREATE_FPU_PRESERVE //激活双精度浮点运算或浮点运算异常检测,设置该项会降低系统性能D3DCREATE_MULTITHREADED //保证D3D是多线程安全的,设置该项会降低系统性能D3DCREATE_MIXED_VERTEXPROCESSING //由混合方式进行顶点运算D3DCREATE_HARDWARE_VERTEXPROCESSING //由D3D硬件进行顶点运算D3DCREATE_PUREDEVICE //禁用D3D的Get*()函数,禁止D3D使用虚拟设备模拟顶点运算===============================================================================DirectX===============================================================================开始渲染和结束渲染:BeginScene(); //开始渲染……实际的渲染工作……EndScene(); //结束渲染注意:这两个函数必须成对出现,不允许交错和嵌套的发生,实际的渲染工作在这两个函数的中间进行。
VxWorks为块设备(磁盘)的实时使用提供了两种本地文件系统:一种与MS-DOS文件系统相兼容,另一种与RT-11文件系统相兼容。
这些文件系统的支持库分别为do sF sLib和rt11FsLib。
VxW orks还提供了一种简单的raw文件系统,这个文件系统把整个磁盘作为一个单独的大文件。
这个文件系统的支持库是r awFsL ib。
VxWork s还为不使用标准文件或目录结构的磁带设备提供了一个文件系统。
磁带卷被看作一个ra w设备,整个卷就是一个大文件。
这个文件系统的支持库是t ape FsLib。
另外,V xWork s提供了一个文件系统支持库cd rom FsLib,它允许应用程序从依照IS O9660标准文件系统格式化的CD-R OMs中读取数据。
在VxWorks中,文件系统不受块设备种类型或它的驱动程序的约束。
Vx Works块设备都使用一个标准接口,以便文件系统可以与设备驱动程序自由的混合。
做为选择,你可以写自己的能被驱动程序以相同方式使用的文件系统,只要在文件系统、驱动程序和I/O系统间遵循同样的标准接口。
V xWork s的I/O体系结构使得在一个VxWork s系统中可以有多样的文件系统,甚至其类型也可以不同。
块设备界面在3.9.4块设备中讨论。
1 与MS-DOS兼容的文件系统:dosF s使用dosFs文件系统格式化的磁盘与MS-D OS(直至6.2版本)磁盘是相兼容的。
由两个文件系统初始化的硬盘之间在格式上有细微区别。
然而,数据自身是兼容的,而且do sFs可被配置成使用MS-DOS格式化的磁盘。
D osFs文件系统向不同要求的实时应用程序提供了良好的适应性。
一个人学习的能力有限,分享无限,分享让所有人平等的学习科技。
本文适合有一定的z_stack基础,做过基本的zigbee实验,为大家提供一个速查的文本,根据易难可以自由取舍章节。
文章是本人应2台电脑对照逐字逐句敲打,固有错误之处,但不会影响阅读。
编写中本人尽量做到细心。
by syemour_GuangDong2014_11OASL API (operation system abstraction layer操作系统抽象层,aplication programming interface应用程序接口)为以下在一种规范内的功能函数提供一个独立的编程环境。
1.task registration,initialization,starting任务注册,初始化,启动2.message exchange between tasks任务间的信息传递3.task synchronization任务同步4.interrupt handling中断处理5.timers时钟节拍,延时等6.memory allocation内存分配(一)message management API(1)uint8 *osal_msg_allocate(uint16 len);被任务调用建立一个消息缓存区,填满后用osal_msg_send();传递给另外一个任务,如果buffer没有被分配,msg_ptr=NULL;len为消息长度。
the return value is a pointer to the buffer allocated for the message,a NULL return indicates the massage allocation operation failed.返回一个指向被分配消息的缓冲区的指针。
(2)uint8 osal_msg_deallocate(uint8 *msg_ptr);接收消息程序完成后,清空存储区,返回操作结果指示。