这一节中,我们重点分析一下驱动安装函数_io_dev_install_ext(xxx),看看驱动安装到底都做了些什么工作,又会遇到哪些新的东西!
文件:Io_instx.c (source\io)中
/*FUNCTION*------------------------------- * * Function Name : _io_dev_install_ext * Returned Value : _mqx_uint a task error code or MQX_OK * Comments : * Install a device dynamically, so tasks can fopen to it. Different from * _io_dev_install since this function also installs an unstall function. * *END*----------------------------------*/ _mqx_uint _io_dev_install_ext ( /* [IN] A string that identifies the device for fopen */ char_ptr identifier, /* [IN] The I/O open function */ _mqx_int (_CODE_PTR_ io_open)(MQX_FILE_PTR, char _PTR_, char _PTR_), /* [IN] The I/O close function */ _mqx_int (_CODE_PTR_ io_close)(MQX_FILE_PTR), /* [IN] The I/O read function */ _mqx_int (_CODE_PTR_ io_read)(MQX_FILE_PTR, char _PTR_, _mqx_int), /* [IN] The I/O write function */ _mqx_int (_CODE_PTR_ io_write)(MQX_FILE_PTR, char _PTR_, _mqx_int), /* [IN] The I/O ioctl function */ _mqx_int (_CODE_PTR_ io_ioctl)(MQX_FILE_PTR, _mqx_uint, pointer), /* [IN] The I/O un-install function */ _mqx_int (_CODE_PTR_ io_uninstall)(IO_DEVICE_STRUCT_PTR), /* [IN] The I/O initialization data */ pointer io_init_data_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; IO_DEVICE_STRUCT_PTR dev_ptr; #if MQX_CHECK_ERRORS _mqx_uint i; _mqx_uint found = 0; #endif _GET_KERNEL_DATA(kernel_data); #if MQX_CHECK_ERRORS if ((io_open == NULL) || (io_close == NULL)){ return(MQX_INVALID_PARAMETER); } /* Endif */ /* Search for delimiter */ for (i = 0; i < IO_MAXIMUM_NAME_LENGTH; i++) { if (identifier[i] == IO_DEV_DELIMITER) { found++; } else if (identifier[i] == '\0') { break; } /* Endif */ } /* Endfor */ /* ** Return an error if more than 1 delimiter found, no delimiter was found ** or the identifier was composed of a single delimiter only. */ if ((found != 1) || (i == 1)) { return(MQX_INVALID_PARAMETER); } /* Endif */ /* START CR-169 */ #endif /* Check to see if device already installed */ _lwsem_wait((LWSEM_STRUCT_PTR)&kernel_data->IO_LWSEM); if (kernel_data->IO_DEVICES.NEXT == NULL) { /* Set up the device driver queue */ _QUEUE_INIT(&kernel_data->IO_DEVICES, 0); } /* Endif */ #if MQX_CHECK_ERRORS dev_ptr = (IO_DEVICE_STRUCT_PTR)((pointer)kernel_data->IO_DEVICES.NEXT); while (dev_ptr != (pointer)&kernel_data->IO_DEVICES.NEXT) { if (!strncmp(identifier, dev_ptr->IDENTIFIER, IO_MAXIMUM_NAME_LENGTH)) { _lwsem_post((LWSEM_STRUCT_PTR)&kernel_data->IO_LWSEM); return(IO_DEVICE_EXISTS); } /* Endif */ dev_ptr = (IO_DEVICE_STRUCT_PTR)((pointer)dev_ptr->QUEUE_ELEMENT.NEXT); } /* Endwhile */ #endif _lwsem_post((LWSEM_STRUCT_PTR)&kernel_data->IO_LWSEM); /* END CR-169 */ dev_ptr = (IO_DEVICE_STRUCT_PTR)_mem_alloc_system_zero((_mem_size) sizeof(IO_DEVICE_STRUCT)); #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if (dev_ptr == NULL) { return(MQX_OUT_OF_MEMORY); }/* Endif */ #endif _mem_set_type(dev_ptr, MEM_TYPE_IO_DEVICE); dev_ptr->IDENTIFIER = identifier; dev_ptr->IO_OPEN = io_open; dev_ptr->IO_CLOSE = io_close; dev_ptr->IO_READ = io_read; dev_ptr->IO_WRITE = io_write; dev_ptr->IO_IOCTL = io_ioctl; dev_ptr->IO_UNINSTALL = io_uninstall; dev_ptr->DRIVER_INIT_PTR = io_init_data_ptr; _lwsem_wait((LWSEM_STRUCT_PTR)&kernel_data->IO_LWSEM); _QUEUE_ENQUEUE(&kernel_data->IO_DEVICES, dev_ptr); _lwsem_post((LWSEM_STRUCT_PTR)&kernel_data->IO_LWSEM); return MQX_OK; } /* Endbody */
分析:
首先传递参数有gpio的驱动标示符identifier,一般是“gpio:”,还有驱动操作函数指针,这个上次已经讲过了,剩下的那个就是初始化数据的指针,一般是传递一些特殊数据,这里设为NULL。
然后定义了两个变量:内核数据kernel_data和io设备指针dev_ptr,内核数据指针指向的数据主要包含系统内核状态信息,是一个全局变量,供各个模块使用。设备指针主要包含我们马上就要初始化的一些数据信息,下面会看到初始化的过程就是初始化这个dev_ptr指针,然后把这个指针链接进kernel_data的过程,这样系统就获得了GPIO的操作函数,完成初始化。
紧接着是宏定义MQX_CHECK_ERRORS,用户可以打开这个宏,进行参数的有效性校验,对不符合的参数进行错误处理,一般这个宏都是打开的,这才符合高质量编程的规范嘛!
下一步,获得信号量来保证初始化操作的互斥性,进一步检测kernel_data中的io设备结构体队列是否初始化,如果没有初始化(IO_DEVICES.NEXT = NULL),则先进行io设备队列的初始化。下面这个while循环,主要是判断在IO列表上是否已经存在初始化好的的io设备结构体,判断的根据就是传递过来的identifier标示符“GPIO:”。如果存在,就返回错误信息。
信号量使用完成后一定要释放,这是特别要注意的。当入口校验完毕,下一步就是进行dev_ptr结构体的初始化了,首先以初始化为0的方式分配内存空间,空间IO设备结构体大小。注意,一般在分配内存空间时,都需要进行空间分配是否成功的判断,因为分配内存会有分配失败的可能存在。但是我记得在学习linux时,linux也需要判断,而且linux返回的值也都是几乎都正确,因为linux在分配时,分配的并不是实际地址,而是一个逻辑地址,当对该空间操作时,才进行逻辑地址向屋里地址的映射。这里不是mqx是不是这样,不管是不是都需要判断,这是少不了的。
最后,进行dev_ptr结构体的初始化,给里边的各个变量赋值,把相关的io操作函数进行绑定。绑定完成后,再把设备结构体链接到内核数据结构上,这样内核数据结构就可以根据一个io结构体,找到对应的io操作函数,这样就完成了GPIO驱动函数与MQX内核之间的数据映射,下一步要做的工作就是根据GPIO硬件属性,完成对应驱动函数的功能实现了。
至于MQX内核是怎样进行相关函数调用,组合内部逻辑的,这个我们暂时还看不到迹象,或许以后可以看到!另:该函数里边用到了许多队列相关知识,而且大概看了一下,队列的使用中有好多技巧值得我们学习,故下一步要详细分析一下啦!
转载请注明出处 谢谢!http://blog.csdn.net/metalseed/article/details/8197798
多Activity 需要建立多个java的class及相对应的xml
建立完成之后必须在manifest中注册
<activity android:name=".activity2" android:label="@string/MSSSS" > </activity>
普通String的传入:
主调程序中:
(将名为将"Seed"以名为Name的String丢给被调用程序)
Button1.setOnClickListener(new View.OnClickListener(){ public void onClick(View V){ Intent intent = new Intent(MainActivity.this, activity2.class); String name = "Seed"; intent.putExtra("Name", name); satrtActivity(intent); } });
被调程序:
(获取名为Name的String)
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity2); Intent intent = this.getIntent(); String message = intent.getStringExtra("Name"); }
传递对象类型
Button1.setOnClickListener(new View.OnClickListener(){ public void onClick(View V){ Intent intent = new Intent(MainActivity.this, activity2.class); String name = "Seed"; intent.putExtra("Name", name); startActivityForResult(intent, 1); } });2:在被调Activity中重写finish来设置返回信息
@Override public void finish(){ Intent intent = new Intent(); Bundle b = new Bundle(); b.putString("rtString","~~~~"); intent.putExtras(b); setResult(activity2Return, intent); super.finish(); }3:在主调程序中重载onActivityResult,获得回传的message
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ switch(resultCode){ case activity2Return: Bundle b = data.getExtras(); String returnMessage = b.getString("ac2"); } }
1. 什么是open street map(osm)?
2. 开发者应该知道哪些概念?包括地图的内容、格式等
3. OSM开发有哪些环境?
4. libosmscout环境的搭建
5. libosmscout的使用示例、配置文件
1. 什么是OSM?
Open Street Map 维基世界地图,一个开源的在线地图项目,包括软件和地图数据。
官网介绍
http://wiki.openstreetmap.org/wiki/Zh-hans:Main_Page
中文网页
http://wiki.openstreetmap.org/wiki/Main_Page
OSM与其他地图 如google地图的区别在哪里?
正如官网所说,它提供了一种方式,让任何人能编辑地图,能为OSM增加地图数据(当然如果是错误的,别人是有权修改的)。而且,其他地图大部分都不是免费的,或者需要授权使用, google地图是免费的,但它也是被别人授权的,无法随意编辑或在自己的软件中使用的。
所以,人们也可以免费地使用OSM数据,包括开发等。
对OSM的常见问题,可以浏览
http://wiki.openstreetmap.org/wiki/FAQ
对于大部分人而言,为OSM绘图是比较有趣的事。
有关为地图增加数据(绘图)的详细介绍如下:
http://wiki.openstreetmap.org/wiki/Zh-hans:Map_Making_Overview
而对于开发者而言,更关心如何使用OSM数据,用于开发,一个必要的开发介绍和资源入口:
http://wiki.openstreetmap.org/wiki/Develop
里面介绍了 OSM的API, 如何下载map data,map data的数据格式和数据结构,常用的开发工具(已经开发好的小工具),地图要素(有哪些数据),与OSM相关的支持的框架(库和组件)。
OSM自身的框架描述:
http://wiki.openstreetmap.org/wiki/Component_overview
下面先介绍一些与开发相关的概念和环境。
2. OSM相关的一些概念
地图数据的存储方式是xml结构,后缀名可以是xml或osm。
地图的数据结构,即地图要素包括1 Node, 2 Way, 3 Relation,4 Tag,5 Common attributes
这些地图要素,与普通的地图或导航要素概念相同
Node是空间点,包括经纬坐标,或高度信息。其他一些可选信息,如name等,在tag子数据中表示。类似于shape point 或attribution point
way表示线或区域,能包含2-2000个node点信息。它道路与区域描述的主要形式。类似于link、edge的概念
relation表示不同的元素间的关系,将不同元素间的关系描述出来。类似于connection的概念
tag表示一个元素中包含的一个特征,或者说是包含的一小块数据,如highway=residential,住宅区内的道路。类似于attribution的概念,不过tag的作用远不止attribution的描述。
Common attributes就是node、way、relation的共同属性,包括id, usr, version, timestamp等meta的信息。
更详细的描述参见:
http://wiki.openstreetmap.org/wiki/Data_Primitives
及每个元素的子链接。
有关tag类型的详细介绍和分类在这里有介绍:
http://wiki.openstreetmap.org/wiki/Map_Features
3. 开发框架
OSM目前提供了API 0.6版本的开发接口,xapi是extended api扩展的接口。而这些接口是用于web或java应用开发的。如下介绍
http://wiki.openstreetmap.org/wiki/Databases_and_data_access_APIs
如果是使用其他语言开发,就必须使用其他的库或组件,这里列举了各种语言支持的库和组件。
http://wiki.openstreetmap.org/wiki/Develop/Frameworks
对于我而言,我采用的c++开发语言,目的是读取OSM数据,并解析,选取一些数据,我就选用libosmscout库。
所以,下面我就介绍libosmscout的开发环境设置。
4. libosmscout环境的搭建
我使用JOSM用于查看和下载地图数据,JOSM只能查看较小的地图数据,其内存支持400多MB,对于更大的数据不支持。OSMOSIS用于数据转换或分割等。
地图数据下载,以下链接里包括各个地区或整个地图的下载路径:
http://wiki.openstreetmap.org/wiki/Planet.osm
libosmscout各个模块的介绍:
http://wiki.openstreetmap.org/wiki/Libosmscout
闲话少说,环境搭建(非qt版部分):
a. 使用git从sourceforge上把源码都下载下来
http://sourceforge.net/projects/libosmscout/
b. libosmscout支持windows版本,我使用的是vs2008,所以首先查看README.VisualStudio.txt,里面包含了详细的build windows版本的步骤。
c. 依据readme,将zlib、libxml2、google protocol buffers、protoc.exe下载下来,并配置好。其中zlib、libxml2的版本要匹配,否则会有很因为版本不匹配的链接错误。
d. 依据readme,设置环境变量EXTRALIBS_HEADERS、EXTRALIBS_DEBUGLIBS。
e. 然后编译,这时,若有与DECLARE_COEFFS(SINECOEFF_SSE)相关的编译错误,就查看SSEMath.cpp中,有关math的一系列代码是否是有效的,若无效,加入#define OSMSCOUT_HAVE_SSE2。这个是我遇到的其vs工程中自带的问题,可能是个小bug吧。
f. 此时libosmscout工程、libosmscout-import工程、import工程、demo_AddressLookup工程都能编译通过。有关qt部分的工程我没编译,这里就不写了。
订阅邮件列表,用于知晓它的修改变换,及咨询问题:
https://lists.sourceforge.net/lists/listinfo/libosmscout-development
5. libosmscout使用示例与配置
在使用demo_AddressLookup之前,要获取OSM地图数据及将osm地图数据转换为libosmscout需要的binary数据。
如果手上拿的的有xml格式的数据,可以使用osmosis工具将xml格式的数据转换为osm格式。转换命令示例:
osmosis --read-xml file="planetin.xml" --write-xml file="planetout.osm"更丰富的,强大的示例在
http://wiki.openstreetmap.org/wiki/Osmosis#Example_Usage
或使用JOSM工具从服务器上下载地图数据,并保存为osm格式,这种方法能直接打开地图数据并查看。
然后,使用编译好的import.exe,将osm格式的数据转换为binary数据。在运行程序之前,将libosmscout\map.ost复制到程序当前目录下,因为import需要默认的map.ost参数文件。建立一个用于输出结果的文件夹(libosmscout的binary地图作为输入或输出都是文件夹的形式),如转换planet.xml,运行命令Import.exe planetout.osm --destinationDirectory planet
更详尽的命令参数,请参看源码或import的命令提示。
import的输出会包含很多dat和idx文件,dat是数据文件,idx是dat的索引文件,更详细的说明在libosmscout\libosmscout\ProcessResult.txt中,libosmscout\libosmscout\Resource.txt是一些算法和程序所占资源的说明。
并且map.ost是可以编辑的,可以增加或删除一些选项,如以下一些必要类型保留,其他我都删除,并添加了highway_crossing类型。这样能减少自己不需要的生成的binary数据,当然就会提高效率。
OST TYPES TYPE "highway_crossing" = NODE ("highway"=="crossing") // Do not delete the following type, they are required by the GenCityStreet import step TYPE "boundary_administrative" = WAY AREA ("boundary"=="administrative") OR RELATION ("type"=="boundary" AND "boundary"=="administrative") OPTIONS MULTIPOLYGON IGNORESEALAND // Do not delete the following types, they are required by the GenCityStreet import step TYPE "place_city" = NODE AREA ("place"=="city") TYPE "place_town" = NODE AREA ("place"=="town") TYPE "place_village" = NODE AREA ("place"=="village") TYPE "place_hamlet" = NODE AREA ("place"=="hamlet") TYPE "place_suburb" = NODE AREA ("place"=="suburb") END
自己的一个小的demo,打印地图中highway_crossing的node(前提:自己生成的输入地图中有highway_crossing的数据)。
#include <iostream> #include <iomanip> #include <vector> #include <osmscout/Database.h> #include <osmscout/TypeConfigLoader.h> using namespace std; const static size_t RESULT_SET_MAX_SIZE = 1000; int main(int argc, char* argv[]) { std::string map; map=argv[1]; osmscout::DatabaseParameter databaseParameter; //databaseParameter.SetDebugPerformance(true); osmscout::Database database(databaseParameter); if (!database.Open(map.c_str())) { std::cerr << "Cannot open database" << std::endl; return 1; } double minlat = 0.f; double minlon = 0.f; double maxlat = 0.f; double maxlon = 0.f; database.GetBoundingBox(minlat, minlon, maxlat, maxlon); std::cout << " " << minlat << " " << minlon << " " << maxlat << " " << maxlon << std::endl; std::vector<osmscout::NodeRef> nodes; std::vector<osmscout::WayRef> ways; std::vector<osmscout::WayRef> areas; std::vector<osmscout::RelationRef> relationWays; std::vector<osmscout::RelationRef> relationAreas; osmscout::TypeConfig typeConfig; clock_t startTime = clock(); if (!osmscout::LoadTypeData(map,typeConfig)) { std::cerr << "Cannot load 'types.dat'!" << std::endl; return false; } std::cout << "typeID:" << typeConfig.GetTypeId("highway_crossing") << endl; osmscout::TypeSet types; types.SetType(typeConfig.GetTypeId("highway_crossing")); std::cout << types.HasTypes() << std::endl; database.GetObjects(minlon, minlat, maxlon, maxlat,types, nodes, ways, areas, relationWays, relationAreas); clock_t endTime = clock(); std::cout << "Time:" << (endTime - startTime) << std::endl; std::cout << "nodes: " << nodes.size() << " ways:" << ways.size() << " areas:" << areas.size() << std::endl << "relationWays:" << relationWays.size() << " relationAreas:" << relationAreas.size() << std::endl; for (unsigned int i=0; i<nodes.size(); ++i) { std::cout << i << "GetLat:" << nodes[i].Get()->GetLat() << std::endl; std::cout << i << "GetLon:" << nodes[i].Get()->GetLon() << std::endl; std::cout << i << "GetId: " << nodes[i].Get()->GetId() << std::endl; if (nodes[i].Get()->GetTagCount() > 0) { std::cout << i << "GetTagCount:" << nodes[i].Get()->GetTagCount() << std::endl; std::cout << i << "GetTagKey:" << nodes[i].Get()->GetTagKey(0) << std::endl; std::cout << i << "GetTagValue:" << nodes[i].Get()->GetTagValue(0) << std::endl; } std::cout << i << "GetType:" << nodes[i].Get()->GetType() << std::endl; } database.Close(); std::cout << "database close ..." << std::endl; return 0; }