打印
[菜农群课笔记]

《ARM不是单片机,结构为何先出墙?》

[复制链接]
6924|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tear086|  楼主 | 2010-12-15 20:24 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
沙发
tear086|  楼主 | 2010-12-15 20:30 | 只看该作者
本帖最后由 tear086 于 2010-12-15 22:56 编辑

20:14:40
在2005年俺玩LPC213x时,就推出了红杏系列的LPC213xdef.h后升级为LPC213xcfg.h

20:16:06
俺2003年在DSP中也推出了红杏级的C5402def.h后升级为c5402cfg.h/c5402cfg.c

20:17:32
俺的红杏就是要让菜农将DSP/ARM等高档的单片机普及化,书写的就像单片机一样简单,而且想错都难

20:18:05
哈哈~~~在菜农眼里没有牛人,只有苦命的人

20:18:44
这次俺决定出手M0,实际是从LPC11xx开始的

20:20:12
可是开发环境只能是他们自己做的,俺高喊了开放改革

20:20:21
不听俺的

20:21:01
无奈,俺又一次红杏出墙,推出了LPC11xxcfg.h

20:22:18
晕!他的环境就是命令行调用keil的核

20:22:49
俺在北京打电话问他,说是自己开发的

20:23:24
俺对他反汇编了,是调用keil的核

20:23:45
这种技术对俺是小菜

20:24:23
这种技术俺已用了10数年

20:25:11
等等俺上传nxp的红杏全部工程包

20:25:35
里面的就是这种命令行调用技术

20:26:42
声明,群内发布

20:27:18
TinyM0CPP1.rar

20:28:52
这个就是命令行控制台不回显调用技术

20:29:37
可以在keil内直接烧写flash而不出keil的界面

20:30:57
在nxp的M0发布后,俺感觉它的头文件lpc11xx.h几乎和菜农2005年前的框架一样,但没学彻底

20:32:05
本不想再红杏出墙了,太累,想想几千行,而且是不准错一位的,有多难

20:33:14
当看见周公的头文件后,俺晕了!
又回到了旧社会----寄存器方式

20:34:00
所以,菜农在此红杏出墙,推出了刚才包内的lpc11xxcfg.h

20:34:18
俺抽颗烟去

20:35:58
本来俺不想玩芯唐的M0

20:36:14
抽了三口

20:37:10
Mr.Wrong(44500789)  20:36:00
寄存器方式确实方便,我第一次见识到是STM32的库。

今天俺就用事实讲为什么它不可取,而红杏可取

20:38:00
对,120,有西工大二个研究所协助验证

20:39:37
本来是有在ST上红杏出墙的,可是俺当时走火入魔,搞HotComm

20:40:30
为向香水城交代,俺让自己的研究生用HotCOMM搞了个“STM32ISP”

20:40:58
俺也发布了STM32的C++裸奔

20:41:11
可是就是没时间红杏一把

20:41:38
现在都没脸见香主

20:42:10
等ST上M0吧,俺直接还债,倒塌ST未来的M0

过眼云烟(106821270) 20:42:12
STM32的C++裸奔用哪个编译器啊

20:42:27
IAR

20:43:10
这次玩芯唐的M0确实是无意的

20:43:22
无心插柳柳成荫

20:46:32
哈哈~~~俺想要一套完整的开发板都要银两,这里的代理可以作证

20:47:04
俺红杏这么多就是要证明,农民不是好欺负的

20:48:10
昨天俺说过:nxp和ti都趴下了,芯唐能蹲着就算厉害,群友可以证明

20:49:09
俺一直不宣布做芯唐M0菜鸟,因为俺知道这意味着什么

20:50:15
真的开始看芯唐的资料后(在拿到研讨会开发套件前)

20:50:52
觉得太晕!!!这是俺当菜鸟最晕的一次

20:51:10
不知大家感受如何?

20:51:30
再抽三口烟去

20:53:42
在运动中学习汇编.gif

20:54:10
这是今天讲课的图

20:54:54
在汇编中理解结构比寄存器都有点

20:55:33
大家都知道在C语言的结构体吧

20:56:18
它很庞大,在单片机人的眼里,远不如寄存器操作方便

20:58:48
首先,今天演讲的标题是《ARM不是单片机,结构为何先出墙?》

20:59:32
首先,“ARM不是单片机”,为何?

20:59:58
海_塔机监控(176254851)  20:59:20
那是。。寄存器几百个,晕

这个是一点

21:00:23
ARM不是单片机”,为何?

21:00:27
回答

21:02:13
首先ARM公司不生产单片机

21:03:11
所以,ARM的寄存器就不会有何硬件相关

21:04:18
而单片机的专业厂家指令集中就有访问具体特殊寄存器的指令

21:04:58
也就意味着ARM指令集中就不会包含特殊寄存器

21:06:36
PIC单片机就是一个例证,随着档次的提高,它的指令长度从13位开始增长

21:06:51
为何????

21:07:27
可以看到PIC的指令是变长的

21:08:04
不知指令多了,而是寄存器多了

过眼云烟(106821270) 21:07:44
是指令多了不够用吗

21:08:35
PIC低档的清一色的33/35条指令

21:08:56
听晕了否???

21:09:55
pic12c508好像就20个左右的寄存器,所以指令长为13位。

21:10:51
那么档次高后,寄存器多了,13位就不够了,就变成了14位、15/。。。

21:11:23
指令集条数没变

21:12:01
ARM不是单片机”,对否?

21:12:17
抽三口去

21:14:08
不讲结构,那是教授的作为

过眼云烟(106821270)  21:14:02
外设是各家自己加的
过眼云烟(106821270)  21:14:11
然后重映射

21:14:22


21:15:55
因为ARM指令集内不包含特殊寄存器,而且特殊寄存器都是统一编址在2G即32位的空间内

21:17:00
这就意味着一条指令(32/16位长)不可能容纳32位的特殊寄存器地址或数据

21:18:23
所以,ARM访问特殊寄存器必须通过寄存器间接寻址得到32位的地址值

21:19:36
由于指令长度和编码长度的问题,0x00000000不可能访问到0xffffffff的位置

21:20:46
所以必须在程序的附近即上下偏移处藏匿这些需要的地址或数据

21:21:13
俺记得好像是上下2K还是4K

21:21:46
当超越了这个范围就不能访问到了

21:22:25
这就是所谓的“文字池”,即存放数据或地址的地方


21:24:24
单片机访问寄存器绝对是指向了同一位置,而ARM必须先从能访问到的“池子”里取出要访问的地址值,再得到特殊寄存器的值

21:24:58
继续讲解为何结构要出墙

21:26:17
只要明白了,真谛自然找到,也可抢在菜农前面红杏出墙~~~

21:26:50
俺抽三口烟,大家讨论

21:31:00
前些天有人说俺dsp5402红墙的好,想把5509做成红杏,问俺侵犯红杏专利否,俺说晕,随便

21:31:48
今天课要是讲完了,俺看红杏专利就不是俺的了~~~

21:32:35
为什么寄存器方式在ARM上不太合理???

21:34:00
寄存器方式首先太晕,太多,太乱

21:34:27
例如I2C

21:36:43
结构体将它们都封装在其结构体中,每个寄存器都是结构成员

21:36:55
晕,断线了

21:37:54
单片机特殊寄存器最重要的是“位”,这是我们操作的重点之重点

21:38:48
所以,红杏系列和它们都不一样在于可以控制到所有的“位”

21:39:30
但是可以告诉大家,ARM就不可能直接控制到“位”

21:40:12
M051都研究过了吧

21:41:12
ARM的“位”实际是靠C语言结构体的“位域”实现的,实际是骗人的~~~

21:41:39
依心爱婷(122607939)  21:41:06
像STM32,有块BITAND的区域,操作起来很快

21:42:05
俺给大家用硬件描述,就会理解的

21:43:04
        I2Cs.CON.Bits.STA = 0;//此位必须清除,否则读不出数据
        I2Cs.CON.Regs |= (1 << I2C_CON_SI) | (1 << I2C_CON_AA);

21:43:11
切记

红杏的风格是:(保留原厂定义)
->原厂的结构指针
x->菜农的结构指针
s.菜农的结构


21:45:33
Bits后是位域访问,右值为“位”

21:46:11
Regs说明右值是32位值

21:46:38
这样很方便,维护方便

21:48:15
大家知道74hc573吧

21:48:52
依心爱婷(122607939)  21:47:57
有啥,这是STM32的位操作
依心爱婷(122607939)  21:48:02
方便

可以下课了

21:48:56
俺晕

21:50:42
抽三口

21:53:34
假若用8个片选信号访问8个位呢?

21:53:57
芯唐的快速GPIO就是这样做的

21:55:06
普通GPIO就如同片选信号加位控,而快速GPIO宁可浪费空间也要换取速度

21:55:27
硬件是没有区别的

21:56:12
//DrvGPIO_SetBit()传递参数(E_PORT3, E_PIN6):(总共13条指令28个字节)
//0x00000CB4~0x00000CBB 3条指令8个字节
//0x00000420~0x00000433        10条指令20个字节
        DrvGPIO_SetBit(E_PORT3, E_PIN6);
        __NOP();
//DrvGPIO_ClrBit()传递参数(E_PORT3, E_PIN6):(总共15条指令32个字节)
//0x00000CBE~0x00000CC5 3条指令8个字节
//0x00000408~0x00000419        12条指令24个字节
        DrvGPIO_ClrBit(E_PORT3, E_PIN6);
        __NOP();
//0x00000CC8~0x00000CCD        3条指令6个字节(推荐语句)
        PBitx(E_PORT3, E_PIN6)->Regs = 0;
        __NOP();
//0x00000CD0~0x00000CD3        2条指令4个字节(推荐语句)
        PBitx(E_PORT3, E_PIN6)->Regs = 1;
        __NOP();
//0x00000CD6~0x00000CDF        5条指令10个字节(不推荐语句)
        PBitx(E_PORT3, E_PIN6)->Bits.DOUT = 0;
        __NOP();
//0x00000CE2~0x00000CED        6条指令12个字节(不推荐语句)
        PBitx(E_PORT3, E_PIN6)->Bits.DOUT = 1;
        __NOP();
//DrvGPIO_ClrBit()传递参数(E_PORT3, E_PIN6):(总共15条指令32个字节)
//0x00000CF0~0x00000CF7 3条指令8个字节
//0x00000408~0x00000419        12条指令24个字节
        DrvGPIO_ClrBit(E_PORT3, E_PIN6);
        __NOP();
//DrvGPIO_SetBit()传递参数(E_PORT3, E_PIN6):(总共13条指令28个字节)
//0x00000CFA~0x00000D01 3条指令8个字节
//0x00000420~0x00000433        10条指令20个字节
        DrvGPIO_SetBit(E_PORT3, E_PIN6);
        __NOP();
//0x00000D04~0x00000D0B        3条指令6个字节(推荐语句)
        PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Regs = 0;
        __NOP();
//0x00000D0E~0x00000D11        2条指令4个字节(推荐语句)
        PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Regs = 1;
        __NOP();
//0x00000D14~0x00000D1F        6条指令12个字节(不推荐语句)
        PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Bits.DOUT = 0;
        __NOP();
//0x00000D22~0x00000D2E        7条指令14个字节(不推荐语句)
        PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Bits.DOUT = 1;
        __NOP();
//0x00000D32~0x00000D35        2条指令4个字节(极力推荐语句)
        PORTs.PBit3.Pin6.Regs = 0;
        __NOP();
//0x00000D38~0x00000D3B        2条指令4个字节(极力推荐语句)
        PORTs.PBit3.Pin6.Regs = 1;
        __NOP();
*/
        while(1)
        {
                if (SystemTick.Timer.Bits.T500mS)//0.5S到
                {
//普通GPIO书写方式
//0x00000C8E~0x00000CAD        16条指令32个字节(M05x不推荐语句)
//                        P3s.DOUT.Bits.Pin6 ^= 1;//LED闪烁
//                        PORTs.P3.DOUT.Bits.Pin6 ^= 1;//LED闪烁
                        PORTs.P3.DOUT.Bits.Pin6 = 1;//LED闪烁
                        __NOP();
                        PORTs.P3.DOUT.Bits.Pin6 = 0;//LED闪烁
                        __NOP();
//快速GPIO书写方式
//0x00000CAE~0x00000CB9        6条指令12个字节(M05x极力推荐语句)
                        PORTs.PBit3.Pin6.Regs ^= 1;//LED闪烁
                        SystemTick.Timer.Bits.T500mS = 0;
//快速GPIO书写方式
//0x00000CC6~0x00000CD1        6条指令12个字节(M05x极力推荐语句)
                        PORTs.PBit3.Pin6.Regs ^= 1;//LED闪烁
//普通GPIO书写方式
//0x00000CD2~0x00000CF1        16条指令32个字节(M05x不推荐语句)
                        P3s.DOUT.Bits.Pin6 ^= 1;//LED闪烁

21:56:32
这是俺今天做的实验

21:58:19
NUC1xxM051Seriescfg.h 发生未知错误

21:58:26
上传不了

21:58:34
新版本

21:58:47
继续

21:59:07
芯唐的FTP在俺手上

.COM 菜农弟子?<yuphone@qq.com>  21:59:10
怎么没有版本号

21:59:34
V1.11

22:00:17
以后再说

22:01:08
访问结构成员就如同我们访问文件夹,层次鲜明

22:01:45
不要认为一大串的字符效率就低

22:03:39
俺是学自动化的,程序要机器累死也不要人累,这是原则

22:04:04
所以俺的程序都是傻瓜型的

22:04:59
//        __NOP();
//DrvGPIO_SetBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000D9E~0x00000DA7 4条指令10个字节
//0x00000454~0x00000463        8条指令16个字节
        DrvGPIO_SetBit(E_GPB, GPB_0);
        __NOP();
//0x00000DAA~0x00000DB7        7条指令14个字节
        PBs.DOUT.Bits.Pin0 = 1;
        __NOP();

        __NOP();
//DrvGPIO_ClrBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000DBC~0x00000DC5 4条指令10个字节
//0x00000428~0x00000437        8条指令16个字节
        DrvGPIO_ClrBit(E_GPB, GPB_0);
        __NOP();
//0x00000DC8~0x00000DD3        7条指令14个字节
        PBs.DOUT.Bits.Pin0 = 0;
        __NOP();
//0x00000DD6~0x00000DE1        6条指令12个字节
        PBs.DOUT.Regs |= (1 << Pin0);
        __NOP();
//0x00000DE4~0x00000DEC        5条指令10个字节
        PBs.DOUT.Regs &= ~(1 << Pin0);
        __NOP();
        __NOP();
//0x00000DF2~0x00000DFD        6条指令12个字节
        PBs.DOUT.Bits.Pin0 = 1;
        __NOP();
//0x00000E00~0x00000E09        5条指令10个字节
        PBs.DOUT.Bits.Pin0 = 0;
        __NOP();
//DrvGPIO_SetBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000E0C~0x00000E15 4条指令10个字节
//0x00000454~0x00000463        8条指令16个字节
        DrvGPIO_SetBit(E_GPB, GPB_0);
        __NOP();
//DrvGPIO_ClrBit()传递参数(E_GPB, GPB_0):(12条指令总共26个字节)
//0x00000E18~0x00000E21 4条指令10个字节
//0x00000428~0x00000437        8条指令16个字节
        DrvGPIO_ClrBit(E_GPB, GPB_0);
        __NOP();
//0x00000E24~0x00000E41        15条指令30个字节(不推荐语句)
        Px(E_GPB)->DOUT.Bits.Pin0 = 1;
        __NOP();
//0x00000E44~0x00000E59        11条指令22个字节(不推荐语句)
        Px(E_GPB)->DOUT.Bits.Pin0 = 0;
        __NOP();
//0x00000E5C~0x00000E6D        9条指令18个字节(不推荐语句)
        PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 1;
        __NOP();
//0x00000E70~0x00000E79        5条指令10个字节(不推荐语句)
        PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 0;
        __NOP();
//DrvGPIO_ClrBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000E7C~0x00000E85 4条指令10个字节
//0x00000428~0x00000437        8条指令16个字节
        DrvGPIO_ClrBit(E_GPB, GPB_0);
        __NOP();
//0x00000E88~0x00000E99        9条指令18个字节(推荐语句)
        PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 1;
        __NOP();
//0x00000E9C~0x00000EA5        5条指令10个字节(推荐语句)
        PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 0;
        __NOP();
//DrvGPIO_SetBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000E0C~0x00000E15 4条指令10个字节
//0x00000454~0x00000463        8条指令16个字节
        DrvGPIO_SetBit(E_GPB, GPB_0);
        __NOP();
//0x00000EB4~0x00000EC2        8条指令16个字节(推荐语句)
        PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 0;
        __NOP();
//0x00000EC6~0x00000ED0        6条指令12个字节(推荐语句)
        PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 1;
        __NOP();
//DrvGPIO_SetBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000ED4~0x00000EDD 4条指令10个字节
//0x00000454~0x00000463        8条指令16个字节
        DrvGPIO_SetBit(E_GPB, GPB_0);
        __NOP();
//0x00000EE0~0x00000EEF        8条指令16个字节(推荐语句)
        PORTs.PB.DOUT.Bits.Pin0 = 0;
        __NOP();
//0x00000EF2~0x00000EFD        6条指令12个字节(推荐语句)
        PORTs.PB.DOUT.Bits.Pin0 = 1;
        __NOP();

22:05:21
PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 0;
长否?

22:05:45
PORTs.PxB.DOUT.Bits.Pin0 = 0;

.COM 菜农弟子?<yuphone@qq.com>  22:05:47
不长 mdk是否可以自动识别结构体成员

22:06:28
实际在编译时是会直接找到的

22:06:56
CSS可以,如同VC助手那样

22:07:19
keil的编译太落后

22:08:11
实际敲"."时,应该成员自动显示,这样红杏菜农真的做到想错都难于上青天

22:08:11
实际敲"."时,应该成员自动显示,这样红杏菜农真的做到想错都难于上青天

22:08:38


过眼云烟(106821270助手啊

22:09:13
只要敲I2Cs.后再不用写一个字了


22:09:27
没有

22:09:56
入正题

李冬发(632653918)  22:10:07
老周的界面是自己写的

22:10:14
是的

22:10:35
界面没有技术含量

李冬发(632653918)  22:10:42
不能这样说呢

22:10:52
哈哈~~~相对的

22:11:49
而且Regs也可以

22:12:48
PORTs.PB.DOUT.Bits.Pin0 = 0;

22:13:29
typedef struct {
  union {
    __IO NU_GPIO_T Px[5];//GPIOs.Px[0].DOUT.Regs |= 1;GPIOs.Px[0].DOUT.Bits.Pin0 = 1;
        struct {
#ifdef __NUC1xx_H__//NUC1xx
            __IO NU_GPIO_T PA;//GPIOs.PA.DOUT.Regs |=1;GPIOs.PA.DOUT.Bits.Pin0=1;
            __IO NU_GPIO_T PB;//GPIOs.PB.DOUT.Regs |=2;GPIOs.PB.DOUT.Bits.Pin1=1;
            __IO NU_GPIO_T PC;//GPIOs.PC.DOUT.Regs |=4;GPIOs.PC.DOUT.Bits.Pin2=1;
            __IO NU_GPIO_T PD;//GPIOs.PD.DOUT.Regs |=8;GPIOs.PD.DOUT.Bits.Pin3=1;
            __IO NU_GPIO_T PE;//GPIOs.PE.DOUT.Regs |=16;GPIOs.PE.DOUT.Bits.Pin4=1;
#else//M05x
            __IO NU_GPIO_T P0;//GPIOs.P0.DOUT.Regs |=1;GPIOs.P0.DOUT.Bits.Pin0=1;
            __IO NU_GPIO_T P1;//GPIOs.P1.DOUT.Regs |=2;GPIOs.P1.DOUT.Bits.Pin1=1;
            __IO NU_GPIO_T P2;//GPIOs.P2.DOUT.Regs |=4;GPIOs.P2.DOUT.Bits.Pin2=1;
            __IO NU_GPIO_T P3;//GPIOs.P3.DOUT.Regs |=8;GPIOs.P3.DOUT.Bits.Pin3=1;
            __IO NU_GPIO_T P4;//GPIOs.P4.DOUT.Regs |=16;GPIOs.P4.DOUT.Bits.Pin4=1;
#endif
        };
  };
  __I  NU_REG             RESERVED1[16];
  __IO NU_GPIO_DBNCECON_T DBNCECON;//
#ifndef __NUC1xx_H__//M05x
  __I  NU_REG             RESERVED2[31];
  union {
    __IO NU_GPIO_BIT_DOUT_Pins PBitx[5];//P0~P4
        struct {
            __IO NU_GPIO_BIT_DOUT_Pins PBit0;
            __IO NU_GPIO_BIT_DOUT_Pins PBit1;
            __IO NU_GPIO_BIT_DOUT_Pins PBit2;
            __IO NU_GPIO_BIT_DOUT_Pins PBit3;
            __IO NU_GPIO_BIT_DOUT_Pins PBit4;
        };
  };
#endif
}NUS_GPIO, *NUPS_GPIO;

#ifdef __NUC1xx_H__
#define NU_BASE_GPIO  ((NUPS_GPIO) GPIOA_BASE)//定义硬件结构指针(硬件地址)
#define GPIOs (*NU_BASE_GPIO)//定位全局结构变量GPIOs
#define PORTs (*NU_BASE_GPIO)//定位全局结构变量PORTs
#else
#define NU_BASE_GPIO  ((NUPS_GPIO) PORT0_BASE)//定义硬件结构指针(硬件地址)
#define GPIOs (*NU_BASE_GPIO)//定位全局结构变量GPIOs
#define PORTs (*NU_BASE_GPIO)//定位全局结构变量PORTs
#endif
//-------------------------------------------------------------------------------------//

22:14:00
这就是真谛的所在

22:14:58
PORTs是将5个GPIOs包罗在一体

22:15:57
这样书写随长,但“文字池”只需存PORTs一个结构地址

22:16:32
即结构里面套结构

22:17:29
目的是减少“文字池”记录结构地址的个数
而结构内的全是其偏移了

使用特权

评论回复
板凳
火箭球迷| | 2010-12-15 21:14 | 只看该作者
ARM可以算单片机的升级版本

使用特权

评论回复
地板
fjhcpu| | 2010-12-15 21:54 | 只看该作者
这里也同步直播呀。。。

使用特权

评论回复
5
tear086|  楼主 | 2010-12-15 22:27 | 只看该作者
本帖最后由 tear086 于 2010-12-15 22:39 编辑

22:20:00
现在明白寄存器为何“不太好”了吧

22:21:44
假若keil优化不好,或连续访问一片文字池的结构被插入其他语句
那么必须刷新寄存器的地址,即需要再从文字池内取地址

22:22:33
PA.xxx
PA.yyy
PB.xxx
PB.yyy

22:23:52
首个PA.xxx不需从文字池中取出PA的地址,而PA.yyy就不需要了,只要偏移即可
同理PB.xxx也要取出

22:24:41
假若:
PA.xxx
PB.xxx
PA.yyy
PB.yyy
就要四次取出

22:24:54
明白否????

22:26:03
所以,包罗结构将减少访问文字池的次数,即压缩了代码的空间

22:26:18
这就是红杏的真谛所在

22:26:51
//DrvGPIO_SetBit()传递参数(E_PORT3, E_PIN6):(总共13条指令28个字节)
//0x00000CB4~0x00000CBB 3条指令8个字节
//0x00000420~0x00000433        10条指令20个字节
        DrvGPIO_SetBit(E_PORT3, E_PIN6);
        __NOP();
//DrvGPIO_ClrBit()传递参数(E_PORT3, E_PIN6):(总共15条指令32个字节)
//0x00000CBE~0x00000CC5 3条指令8个字节
//0x00000408~0x00000419        12条指令24个字节
        DrvGPIO_ClrBit(E_PORT3, E_PIN6);
        __NOP();
//0x00000CC8~0x00000CCD        3条指令6个字节(推荐语句)
        PBitx(E_PORT3, E_PIN6)->Regs = 0;
        __NOP();
//0x00000CD0~0x00000CD3        2条指令4个字节(推荐语句)
        PBitx(E_PORT3, E_PIN6)->Regs = 1;
        __NOP();
//0x00000CD6~0x00000CDF        5条指令10个字节(不推荐语句)
        PBitx(E_PORT3, E_PIN6)->Bits.DOUT = 0;
        __NOP();
//0x00000CE2~0x00000CED        6条指令12个字节(不推荐语句)
        PBitx(E_PORT3, E_PIN6)->Bits.DOUT = 1;
        __NOP();
//DrvGPIO_ClrBit()传递参数(E_PORT3, E_PIN6):(总共15条指令32个字节)
//0x00000CF0~0x00000CF7 3条指令8个字节
//0x00000408~0x00000419        12条指令24个字节
        DrvGPIO_ClrBit(E_PORT3, E_PIN6);
        __NOP();
//DrvGPIO_SetBit()传递参数(E_PORT3, E_PIN6):(总共13条指令28个字节)
//0x00000CFA~0x00000D01 3条指令8个字节
//0x00000420~0x00000433        10条指令20个字节
        DrvGPIO_SetBit(E_PORT3, E_PIN6);
        __NOP();
//0x00000D04~0x00000D0B        3条指令6个字节(推荐语句)
        PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Regs = 0;
        __NOP();
//0x00000D0E~0x00000D11        2条指令4个字节(推荐语句)
        PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Regs = 1;
        __NOP();
//0x00000D14~0x00000D1F        6条指令12个字节(不推荐语句)
        PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Bits.DOUT = 0;
        __NOP();
//0x00000D22~0x00000D2E        7条指令14个字节(不推荐语句)
        PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Bits.DOUT = 1;
        __NOP();
//0x00000D32~0x00000D35        2条指令4个字节(极力推荐语句)
        PORTs.PBit3.Pin6.Regs = 0;
        __NOP();
//0x00000D38~0x00000D3B        2条指令4个字节(极力推荐语句)
        PORTs.PBit3.Pin6.Regs = 1;
        __NOP();
*/
        while(1)
        {
                if (SystemTick.Timer.Bits.T500mS)//0.5S到
                {
//普通GPIO书写方式
//0x00000C8E~0x00000CAD        16条指令32个字节(M05x不推荐语句)
//                        P3s.DOUT.Bits.Pin6 ^= 1;//LED闪烁
//                        PORTs.P3.DOUT.Bits.Pin6 ^= 1;//LED闪烁
                        PORTs.P3.DOUT.Bits.Pin6 = 1;//LED闪烁
                        __NOP();
                        PORTs.P3.DOUT.Bits.Pin6 = 0;//LED闪烁
                        __NOP();
//快速GPIO书写方式
//0x00000CAE~0x00000CB9        6条指令12个字节(M05x极力推荐语句)
                        PORTs.PBit3.Pin6.Regs ^= 1;//LED闪烁
                        SystemTick.Timer.Bits.T500mS = 0;
//快速GPIO书写方式
//0x00000CC6~0x00000CD1        6条指令12个字节(M05x极力推荐语句)
                        PORTs.PBit3.Pin6.Regs ^= 1;//LED闪烁
//普通GPIO书写方式
//0x00000CD2~0x00000CF1        16条指令32个字节(M05x不推荐语句)
                        P3s.DOUT.Bits.Pin6 ^= 1;//LED闪烁

22:27:38
自己数数代码占用的字节数,俺这红杏不是吹气吹出来的~~~

22:28:50
将明白否???

22:28:50
将明白否???

宝宝(870336013)  22:30:52
请问学M051有什么书可以参考,我只会用51和AVR

缥缈九哥(14131338)  22:31:06
会了51就不用书了。

22:31:25
51和M051不是一回事

缥缈九哥(14131338)  22:31:45
基本是一回事。

22:31:49
学好了都是一回事

22:32:08
关键要知道真谛所在

22:34:08
红杏系列的宗旨就是简化**,控制到位,准确无误

22:34:57
俺晕!!!!!!!!!!!!

22:35:14
还讲否?抽烟去

22:38:40
晕,抽的家里乌烟瘴气

使用特权

评论回复
6
3B1105| | 2010-12-15 22:49 | 只看该作者
好长呀,慢慢看

使用特权

评论回复
7
X-Hawk| | 2010-12-15 23:32 | 只看该作者
首先感谢菜农大叔辛苦的付出!



其次直接写寄存器和函数PK, 俺强烈表示不公!嘿嘿。。


最后关于“包罗结构将减少访问文字池的次数,即压缩了代码的空间”。
非常认同这句话!
真正的精华所在啊。

使用特权

评论回复
8
X-Hawk| | 2010-12-15 23:52 | 只看该作者
其实算指令数并不精确,
俺测算的结果,
一次加法指令,占1个CPU cycle,
一次LDR指令,占3个CPU cycle,
一次PUSH/POP动作,占 2+寄存器个数的CPU cycle,

因此,减少指令数,特别是访问“文字池”的指令,真的非常必要。

使用特权

评论回复
9
hotpower| | 2010-12-16 01:40 | 只看该作者
哈哈~~~终于引鱼上钩了~~~


其次直接写寄存器和函数PK, 俺强烈表示不公!

这俺没PK,只把指令条数列不来,没发表言论,因为这无法PK,因为这肯定不战而胜,但胜之不武。


最后关于“包罗结构将减少访问文字池的次数,即压缩了代码的空间”。

这是ARM和单片机的一个重要区别。
当连续访问某一寄存器的许多不同位时,只需访问一次文字池即可。
当交叉访问某几个不同的寄存器时,由于它们的间距较大,可能超出了结构成员访问的偏移,故必须要多次的访问文字池。
这样文字池中的地址值较多,即增大了数据空间。再由于额外的访问也增大了代码的长度。
故空间和速度都是比较差的。


其实算指令数并不精确

准确来讲无法判断,主要的原因正如以上所述。
所以想精准测算程序的运行指令周期,难~~~

总之,红杏系列充分认识到了这些,力图做到:

简化**,控制到位,准确无误

使用特权

评论回复
10
hotpower| | 2010-12-16 07:40 | 只看该作者
在程序的优化方面实际有有三个目标:
1.优化代码实际运行的长度即提高执行速度。
2.优化代码实际占用的空间即提高代码压缩率。
3.前两者兼顾。

一般首先从宏定义和函数的编写入手。
前者实际就是相同代码的批量复制,不惜以浪费代码空间的代价换取代码执行的时间即提高了运行速度。
次者实际就是相同代码的浓缩汇集,不惜以分支调用额外产生时间的代价换取代码的空间即压缩了代码长度。

最后者是在兼顾前两者的基础上加以考虑的:
函数的传递也是需要时间和空间的,这主要消耗在参数的复制上面。
当函数的传递损耗 函数体长>宏体长度时,显然宏比函数优势巨大。
反之函数压缩空间优势。

(上班了)

使用特权

评论回复
11
mytempid| | 2010-12-16 08:39 | 只看该作者
本帖最后由 mytempid 于 2010-12-16 11:20 编辑

有没有“包罗结构...”对下列语句的优化示例?


假若:
PA.xxx
PB.xxx
PA.yyy
PB.yyy
就要四次取出


对这个优化如何实现不是很明白,没想出来

使用特权

评论回复
12
batsong| | 2010-12-16 08:41 | 只看该作者
昨天看直播了,哈哈,arm指令系统还不熟,但基本已经懂了

使用特权

评论回复
13
tjx727| | 2010-12-16 09:37 | 只看该作者
ARM本来就不是单片机,只是一种体系结构,只是其他公司拿ARM这种体系结构生产了许多单片机

使用特权

评论回复
14
jack_shine| | 2010-12-16 09:44 | 只看该作者
路过学习~~~

使用特权

评论回复
15
jack.king| | 2010-12-16 12:09 | 只看该作者
:)

使用特权

评论回复
16
linqing171| | 2010-12-16 12:27 | 只看该作者
大叔,文字池,确实实际上看是这样的,有没有英语的原文 或者 更详细的资料?

使用特权

评论回复
17
QQTony| | 2010-12-16 13:28 | 只看该作者
实际上都是编译器惹的祸! 好的编译器应该自动判断, 自动选取基址

使用特权

评论回复
18
areshan| | 2010-12-16 16:12 | 只看该作者
没有看明白!hot大叔能否说的明白点!是结构溢出吗?

使用特权

评论回复
19
hsbjb| | 2010-12-16 16:43 | 只看该作者
不太明白菜农标题的意思:lol

使用特权

评论回复
20
xiepengchenghn| | 2010-12-16 17:17 | 只看该作者
菜农是西安哪个学校的老师啊,早知道考你的研究生去:'(

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:個人博客:yuphone.cnblogs.com 聯絡方式:張亞峰 15013013265@qq.com

0

主题

120

帖子

3

粉丝