仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2092|回复: 19
打印 上一主题 下一主题

[学习教程] IOS制作之offsetof,弄嵌进式必需会的杀手锏仓酷云

[复制链接]
简单生活 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:50:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
不管是学习Objective-C语言,还是学习ios,我都只是跟着书上的例子,在苹果机上,在Xcode和InterfaceBuilder开发环境中,按部就班的“抄”些应用程序。在嵌进式使用中,也许你对offsetof打仗未几乃至基本没见过。假如是如许,那末从这一刻起就好好地把握它,让它成为你的又一杀手锏吧。1.offsetof与EEPROM
我们很多人大概都利用过一些非挥发性的存储器,如罕见的EEPROM。我们常常利用它们在存储一些体系的设置参数和设备信息。在一切的EEPROM中,经由过程串口会见的占了年夜多半。一样平常来讲,对串口的会见都是按字节举行的,这使得我们不成制止会计划出上面的
接口往会见EEPROM的信息:/*从EEPROM偏移量offset处读取nBytes到RAM地点dest*/
ee_rd(uint16_toffset,uint16_tnBytes,uint8_t*dest);但是,这类接口必需要晓得偏移量offset和读取字节数nBytes。大概你会接纳上面的办法办理办法办理这个成绩:
界说一个数据布局和一个指向这个数据布局的指针,并初始化这个指针为EEPROM的肇端地点EEPROM_BASE.----------------------------<-EPPROM_BASE:0x0000000
|i|f|c||||...
----------------------------
|||||||...
----------------------------
|||||||...
----------------------------
...
----------------------------#defineEEPROM_BASE0x0000000/*设置信息的肇端地点*/typedefstruct
{
inti;
floatf;
charc;
}EEPROM;EEPROM*constpEE=EEPROM_BASEee_rd(&(pEE->f),sizeof(pEE->f),dest);没错,这类办法切实其实能够到达会见指定地点的信息。不外这类办法也存鄙人面的成绩:
a.简单使代码保护职员人误觉得在ee_rd接口外部也存在EEPROM的数据布局。
b.当你编写一些本人感到优秀编译器不报错的代码,好比pEE->f=3.2,你大概意想不到劫难将要光降。
c.这个接口没有很好地表现EEPROM所隐含的硬件特征。到这里,有人大概会想到offsetof(那些没用过头至没见过的伴侣别急,前面即刻会详解offsetof)来办理这个成绩:/*offsetof猎取数据成员在数据布局中的偏移量
好比成员f在EEPROM数据布局中的偏移量,这里为何
要强迫转化0,这是个有深度的成绩,在前面也会具体申明*/
#defineoffsetof(type,f)((size_t)
((char*)&((type*)0)->f-(char*)(type*)0))typedefstruct
{
inti;
floatf;
charc;
}EEPROM;ee_rd(offsetof(EEPROM,f),4,dest);假如你能想到这里申明你对offsetof有必定水平的了解,不外还能够改善。假如让编译器来盘算nBytes而不是我们本人给出4那就更好了。这时候,必定有人会即刻提到sizeof。是的。但是怎样利用呢,我们不克不及用sizeof(EEPROM.f)来盘算nBytes吧?!我想那些对offsetof有较深了解的同道必定会这么办:/*相似于offsetof的界说*/
#defineSIZEOF(s,m)((size_t)sizeof(((s*)0)->m))ee_rd(offsetof(EEPROM,f),SIZEOF(EEPROM,f),&dest);很不错!实在还能够精简为上面的终极情势:#defineEE_RD(M,D)ee_rd(offsetof(EEPROM,M),SIZEOF(EEPROM,M),D)EE_RD(f,&dest);哈哈,如许我们只用传送两个参数,不必再思索应当从那边读取数据和读取几的成绩。先打住,有人会说这类简化都是创建在EEPROM_BASE为0x0000000基本之上的,大概会反问,假如设置信息不是从0地点入手下手的呢?
Goodquestion.实在我们能够经由过程上面的办法办理。#defineEEPROM_BASE0x00000a10typedefstruct
{
charpad[EEPROM_BASE];/*使数据布局的前EEPROM_BASE个字节填"空"*/
inti;
floatf;
charc;
}EEPROM;
----------------------------0x00000000
|||||||...
----------------------------
...
----------------------------<-EPPROM_BASE:0x00000a10
|i|f|c||||...
----------------------------
|||||||...
----------------------------
...利用offsetof简化EEPROM的串口会见切实其实很妙。这里另有一个很好的例子。在嵌进式使用中,我们经常将一些I/O存放器映照到内存地点空间举行会见。
这类映照使底本庞大的存放器会见变得象会见一般的RAM地点一样便利。

在我们视频集会体系中,PowerPC8250会见内部的ROM把持器(ROMcontroller)的
存放器就是经由过程这类体例完成的。ROM把持器一切的存放器被映照到从I/O存放器空间基地点0x10000000(IO_BASE)偏移0x60000(ROMCONOffset)字节的一段内存。每一个存放器占用四个字节,并有一个数据布局与它们对应。好比把持ROM把持器事情形态的存放器对应数据布局ROMCON_ROM_CONTROL,设置PCI总线A的存放器对应数据布局ROMCON_CONFIG_A,上面先看看这些数据布局的界说:#defineIO_BASE0x10000000#defineROMCONOffset0x60000typedefunsignedintNW_UINT32;typedefstruct_ROMCON_CONFIG_A{
union{
struct{
UINT32pad4:21;/*unused*/
UINT32pad3:2;/*reserved*/
UINT32pad2:5;/*unused*/
UINT32EnablePCIA:1;
UINT32pad1:1;/*reserved*/
UINT32EnableBoot:1;
UINT32EnableCpu:1;/*bittoenablecpu*/
}nlstruct;struct{
UINT32ConfigA;
}nlstruct4;
}nlunion;
}ROMCON_CONFIG_A,*PROMCON_CONFIG_A;typedefstruct_ROMCON_ROM_CONTROL{
union{
struct{
UINT32TransferComplete:1;
UINT32pad3:1;/*unused*/
UINT32BondPad3To2:2;
UINT32Advance:3;
UINT32VersaPortDisable:1;
UINT32pad2:1;/*unused*/
UINT32FastClks:1;
UINT32pad1:7;/*unused*/
UINT32CsToFinClks:2;
UINT32OeToCsClks:2;
UINT32DataToOeClks:2;
UINT32OeToDataClks:3;
UINT32CsToOeClks:2;
UINT32AddrToCsClks:2;
UINT32AleWidth:2;
}nlstruct;struct{
UINT32RomControl;
}nlstruct4;
}nlunion;
}ROMCON_ROM_CONTROL,*PROMCON_ROM_CONTROL;typedefstruct
{
ROMCON_CONFIG_AConfigA;
ROMCON_CONFIG_BConfigB;
ROMCON_ROM_CONTROLRomControl;
...
}ROMCON,*PROMCON;----------------------------<-IO_BASE:0x10000000
|||||||...
----------------------------
|||||||...
...
----------------------------<-ROMCONOffset(ROMCON):0x60000
|||||||...
----------------------------<-ROMCON_ROM_CONTROL
...
----------------------------那末怎样会见ROMCON_ROM_CONTROL对应存放器呢,好比ROMCON_ROM_CONTROL对应存放器的VersaPortDisable位?
估量有人大概会如许做:
事前界说成员RomControl(ROMCON顶用ROMCON_ROM_CONTROL界说的实例)绝对与ROMCON的偏移量,#defineROMCONRomControlOffset0x8然后计划会见ROM的接口以下:/*读取ROM把持器位于src地位的存放器数据到dest*/typedefunsignedlongdword_t;
voidrom_read(dword_t*src,uint32_t*dest);
voidrom_write(dword_t*src,uint32_t*dest);最初使用这个偏移量做上面的操纵:ROMCON_ROM_CONTROLtRomCtrl={0};dword_t*pReg=(dword_t*)(IO_BASE+ROMCONOffset+ROMCONRomControlOffset);rom_read(pReg,(uint32_t)*(&tRomCtrl));/*检察存放器的VersaPortDisable位,假如该位没有启用就启用它*/
if(!tRomCtrl.nlunion.nlstruct.VersaPortDisable)
{
tRomCtrl.nlunion.nlstruct.VersaPortDisable=1;rom_write(pReg,(uint32_t)*(&tRomCtrl));
}

如许做的确能够到达会见响应存放器的目标。可是,假如和ROM相干的存放器良多,那末界说、影象和办理那末多偏移量不是很不便利吗?到这里,假如你对后面关于offsetof另有印象的话,我想你大概会作上面的优化:
#defineROMCON_ADDR(m)(((size_t)IO_BASE+
(size_t)ROMCONOffset+
(size_t)offsetof(ROMCON,m))ROMCON_ROM_CONTROLtRomCtrl={0};
dword_t*pReg=(dword_t*)ROMCON_ADDR(ConfigA);rom_read(pReg,(uint32_t)*(&tRomCtrl));/*检察存放器的VersaPortDisable位,假如没有启动就启动它*/
if(!tRomCtrl.nlunion.nlstruct.VersaPortDisable)
{
tRomCtrl.nlunion.nlstruct.VersaPortDisable=1;rom_write(pReg,(uint32_t)*(&tRomCtrl));
}
2.offsetof的前因后果
经由过程后面的举例,你大概对怎样利用offsetof已不生疏了吧。offsetof对那些弄
C++的人大概很熟习,由于offsetof相似于sizeof,也是一种体系操纵符,你不必思索它是怎样界说的。这个操纵符offsetof的界说能够在ANSIC编译器所带的stddef.h中找到。在嵌进式体系里,分歧开辟商,分歧架构处置器和编译器都有分歧的offsetof界说情势:/*Keil8051*/
#defineoffsetof(s,m)(size_t)&(((s*)0)->m)/*Microsoftx86*/
#defineoffsetof(s,m)(size_t)(unsignedlong)&(((s*)0)->m)/*Motorolacoldfire*/
#defineoffsetof(s,memb)((size_t)((char*)&((s*)0)->memb-(char*)0))/*GNUGCC4.0.2*/
#defineoffsetof(TYPE,MEMBER)__builtin_offsetof(TYPE,MEMBER)固然界说情势分歧,但功效都是前往成员在数据布局中的偏移量,都是为了进步代码的可移植性。上面拿KEIL8051的界说来作点注释:
((s*)0):强迫转化成数据布局指针,并使其指向地点0;
((s*)0)->m:使该指针指向成员m
&(((s*)0)->m):猎取该成员m的地点
(size_t)&(((s*)0)->m):转化这个地点为符合的范例你大概会利诱,如许强迫转换后的布局指针怎样能够用来会见布局体字段?呵呵,实在这个表达式基本没有也不盘算会见m字段。ANSIC尺度同意任何值为0的常量被强迫转换成任何一品种型的指针,而且转换了局是一个NULL指针,因而((s*)0)的了局就是一个范例为s*的NULL指针。假如使用这个NULL指针来会见s的成员固然长短法的,但&(((s*)0)->m)的企图并不是想存取s字段内容,而仅仅是盘算当布局体实例的首址为((s*)0)时m字段的地点。伶俐的编译器基本就不天生会见m的代码,而仅仅是依据s的内存结构和布局体实例首址在编译期盘算这个(常量)地点,如许就完整制止了经由过程NULL指针会见内存的成绩。又由于首址的值为0,以是这个地点的值就是字段相对布局体基址的偏移。这里有个中央必要注重:就是offsetof固然一样合用于union布局,但它不克不及用于盘算位域(bitfield)成员在数据布局中的偏移量。typedefstruct
{
unsignedinta:3;
unsignedintb:13;
unsignedintc:16;
}foo;利用offset(foo,a)盘算a在foo中的偏移量,编译器会报错;
有一些像NSCopying的接口(经@李禹龙提醒应该叫协议)不是特别用到开始不用了解NSObject创建对象的时候用+(id)alloc方法创建后需要init方法初始化
愤怒的大鸟 该用户已被删除
沙发
发表于 2015-1-21 16:06:20 来自手机 | 只看该作者
开始的时候甚至想放弃,不过想想自己的未来,只能咬牙坚持,课下就不停的缠着老师。放学就补基础,这些基础的东西没有速成的,只有刻苦努力。我是后来发现的,转变自己的心态,不要读书看资料当成一种痛苦
变相怪杰 该用户已被删除
板凳
发表于 2015-1-23 16:44:18 | 只看该作者
这个办法就是在WindowsXP或Win7的电脑上,使用vmware虚拟机来搭建一个真实的Mac OS X环境。
若天明 该用户已被删除
地板
发表于 2015-1-25 15:29:18 | 只看该作者
其实在培训的过程中,学习到最多的就是查资料的方式,当时感觉老师好坑,什么都不告诉我们,让我们自己去查,但是现在觉得还是要自己解决问题,这样才能理解的更加深入。
乐观 该用户已被删除
5#
发表于 2015-1-25 18:21:24 | 只看该作者
在百度搜索你想要了解的类名(苹果的cocoa和cocoatouch框架的类名很有特点很容易搜到,前缀都是NS or UI),看别人写的博客详解
小魔女 该用户已被删除
6#
发表于 2015-1-28 07:12:15 | 只看该作者
首先是基础,在汉昌的课程非常全面。从object—c到最后的毕业项目,基本上方方面面都涉及到了,我是一名非计算机专业的学生,起初学习还有点吃力,因为基础知识薄弱。经常像听天书
简单生活 该用户已被删除
7#
 楼主| 发表于 2015-2-5 12:36:40 | 只看该作者
要学会通过各种方法将面前的事情变成自己感兴趣的,那专研起来就不会是无聊和折磨了。
再见西城 该用户已被删除
8#
发表于 2015-2-10 23:25:19 | 只看该作者
在百度搜索你想要了解的类名(苹果的cocoa和cocoatouch框架的类名很有特点很容易搜到,前缀都是NS or UI),看别人写的博客详解
柔情似水 该用户已被删除
9#
发表于 2015-2-11 19:47:09 | 只看该作者
要学会通过各种方法将面前的事情变成自己感兴趣的,那专研起来就不会是无聊和折磨了。
10#
发表于 2015-2-27 08:47:59 | 只看该作者
中国如今已然发展成为一个软件大国,软件人才的数量跃居全球之首。当然,在苹果平台的开发领域,也保持了相当强劲的发展势头。然而,很多初入iOS开发门槛的开发者,
不帅 该用户已被删除
11#
发表于 2015-3-6 16:54:49 | 只看该作者
其实在培训的过程中,学习到最多的就是查资料的方式,当时感觉老师好坑,什么都不告诉我们,让我们自己去查,但是现在觉得还是要自己解决问题,这样才能理解的更加深入。
小妖女 该用户已被删除
12#
发表于 2015-3-6 21:12:52 | 只看该作者
以上可以同时进行,学习过程中尽量不要纠结细节和底层,要知道ios是封闭的、OC是高级语言,我们不可能过多地去了解它的原理,至少在新手阶段没有必要。用迭代的方式更新你的知识,而不是死抠一个知识点。
飘飘悠悠 该用户已被删除
13#
发表于 2015-3-6 22:38:56 | 只看该作者
同很多iOS开发者一样,我也是通过培训进入到iOS开发这个行业,开始没有打算培训,只准备自己学习一些计算机编程相关的知识,毕业时找一份编程相关工作(本人是信息与计算科学这个专业,是数学系)。
山那边是海 该用户已被删除
14#
发表于 2015-3-13 00:09:54 | 只看该作者
其实在培训的过程中,学习到最多的就是查资料的方式,当时感觉老师好坑,什么都不告诉我们,让我们自己去查,但是现在觉得还是要自己解决问题,这样才能理解的更加深入。
分手快乐 该用户已被删除
15#
发表于 2015-3-20 06:55:27 | 只看该作者
以上可以同时进行,学习过程中尽量不要纠结细节和底层,要知道ios是封闭的、OC是高级语言,我们不可能过多地去了解它的原理,至少在新手阶段没有必要。用迭代的方式更新你的知识,而不是死抠一个知识点。
透明 该用户已被删除
16#
发表于 2015-3-22 02:09:04 | 只看该作者
特别是在校的学生,都存在一个小小的尴尬——虽然学习iOS开发的热情高涨,但由于没有多余的银子购买昂贵的Mac电脑而踟蹰不前。其实,针对初学者,如果想进入iOS开发的天地
第二个灵魂 该用户已被删除
17#
发表于 2015-4-2 13:06:36 | 只看该作者
培训时可以选择安卓,iOS,Java,因为实习的时候我选了安卓,当时实习时间只有三周,学的晕头转向,而java我也没学过,iOS的基础是C语言,这个大学里还是学过的,于是选择了iOS。
老尸 该用户已被删除
18#
发表于 2015-4-6 21:40:32 | 只看该作者
因为我们老师也是自学的,给我们讲课说的最多的就是百度,谷歌,查文档。
灵魂腐蚀 该用户已被删除
19#
发表于 2015-4-9 04:38:23 | 只看该作者
好处就是运行速度会变快,ios6针对系统的优化进一步加强了,很多网友测试ios6,第一感觉就是速度快,而且ios69会有一些新功能,新浪微博,facetime支持3G网等等。。弊端就是,现在的ios6只能算是正式版本的第一个版本,bug很多,不少人刷完ios6都出现了很多毛病,开不开机,缺少图标等等。。最好现在不要升级,等官网放出下一个版本的时候,再选择升级。。。
深爱那片海 该用户已被删除
20#
发表于 2015-4-12 18:41:36 | 只看该作者
好处就是运行速度会变快,ios6针对系统的优化进一步加强了,很多网友测试ios6,第一感觉就是速度快,而且ios69会有一些新功能,新浪微博,facetime支持3G网等等。。弊端就是,现在的ios6只能算是正式版本的第一个版本,bug很多,不少人刷完ios6都出现了很多毛病,开不开机,缺少图标等等。。最好现在不要升级,等官网放出下一个版本的时候,再选择升级。。。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-5-13 21:09

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表