CC254x内部采用的是增强型8051内核,指令执行速度较标准的8051要快,主要基于:
l 增强型8051的单周期指令是1个时钟周期,而标准8051需要12个时钟周期;
l 没有了浪费的总线状态(wastedbus states);
由于一个指令周期能与存储中指令预取保持同步,使得大多数单周期指令能在一个时钟周期内完成,此外,增强型8051内核也包含一个“second data pointer”和一个扩展的18个中断单元。
8051有分离的程序存储空间和数据存储空间,可细分成4中不同的存储空间:
l CODE:只读程序存储,寻址空间64KB;
l DATA:可读写数据存储空间,可被直接或间接寻址,256 bytes,低128 byte 可被直接或间接寻址,高128 bytes只能间接寻址(SFR除外,SFR为直接寻址)
l XDATA:片外数据存储,寻址空间64K,
l SFR:寄存器区域,直接寻址;
CC254x内部时钟系统分两部分,系统时钟(system clock)和睡眠看门狗时钟。
· CPU运行主频,分频之后也为Timer1、Timer3、Timer4计数时钟;
· 支持2种时钟源,内部16MHz RC晶振或外部的32MHz晶振;
· 上电默认是IRC 16MHz;
· IRC 16MHz 启动时间比32MHz时间短,功耗低,但是精度差,不能用于射频相关的数据传输,射频相关操作必须要等32MHz时钟稳定之后才能进行;
· 为睡眠定时器和看门狗运行提供时钟;
· 支持2种时钟源,内部32KHz RC晶振或外部的32.768KHz晶振;
· 上电默认是内部32KHz;
· IRC 32KHz 启动时间比外部32.768KHz时间短,功耗低,但是精度差;
· 当开启IRC 32KHz校准功能(使用外部的32MHz分频,SLEEPCMD.OSC32K_CALDIS = 1;CLKCONCMD. OSC32K = 1),IRC 32KHz能以32.753KHz工作;
摘自TI-BLE-v1.2.1 HAL source code:
……
// start 16MHz RCOSC & 32MHz XOSC waitfor stable 32MHz XOSC
START_HSOSC_XOSC();
// switch to the 16MHz HSOSC and wait until it isstable
SET_OSC_TO_HSOSC();
// set 32kHz OSC and wait until it is stable
SET_32KHZ_OSC();
// switch to the 32MHz XOSC and wait until it isstable
SET_OSC_TO_XOSC();
//stop 16MHz RCOSC
STOP_HSOSC();
……
这段代码有对IRC 16MHz进行开关控制(SLEEPCMD.Bit2),实际根据手册,SLEEPCMD.Bit2始终为1,无需配置,个人猜测最初的CC254x或者CC253x可以对IRC16MHz进行开关控制,后来取消了这部分,改为上电默认IRC16MHz 打开,且可以默认它已经运行稳定(CLKCONCMD.OSC = 1; CLKCONSTA.OSC = 1; ),所以实际时钟初始化可以只是:
……
// set 32kHz OSC and wait until it is stable
SET_32KHZ_OSC();
// switch to the 32MHz XOSC and wait until it isstable
SET_OSC_TO_XOSC();
……
CC254x包含5种电源模式:Active ,idle,powermode1/2/3(PM1-PM3), 其中的PM1-PM3也称为睡眠模式。
CC254x的5种电源模式涉及晶振和片内1.8Vvoltage regulator digital部分的开关控制,高频率晶振包括X-OSC (32 MHz) 和IRC-OSC (16 MHz) ,低频率晶振包括X-OSC (32.768 KHz) 和IRC-OSC (32 KHz) 。
· Active 模式:为正常工作的全功能模式,片内1.8V 电压转换芯片、高频晶振(32MHz或16MHz)、低频晶振(32.768KHz或32KHz)都处于正常工作状态;
· IDLE模式:除了CPU内核处于“IDLE”外,其它等同于Active模式;
· PM1模式:适应于能快速唤醒,睡眠时间不超过3ms的应用场合;
· PM2模式:睡眠时间超过3ms,一般使用Sleeptimer定时唤醒;
· PM3模式:最低功耗状态,睡眠时间超过3ms,一般使用外部IO中断方式唤醒。
Power mode |
High-Frequency OSC |
Low-Frequency OSC |
voltage regulator |
Active |
X-OSC or IRC-OSC |
X -OSC or IRC-OSC |
ON |
IDLE |
X-OSC or IRC-OSC |
X -OSC or IRC-OSC |
ON |
PM1 |
None |
X-OSC or IRC-OSC |
ON |
PM2 |
None |
X -OSC or IRC-OSC |
OFF |
PM3 |
None |
None |
OFF |
CC254x睡眠模式和IDLE模式切换到Active 模式方法:
Power mode |
Wakeup to Active mode |
Active |
/ |
IDLE |
POR, BOD, External reset, External interrupt , Sleep timer expires |
PM1 |
POR, BOD, External reset, External interrupt , Sleep timer expires |
PM2 |
POR, External reset, CRC reset (CC2541 only), External interrupt , Sleep timer expires |
PM3 |
POR, External reset, CRC reset (CC2541 only), External interrupt, |
CC254x使用寄存器PCON.IDLE和SLEEP.MODE来控制,进入睡眠模式一般先设置要进入哪种非Active模式(IDLE、PM1-PM3):
SLEEP.MODE [1:0] |
Mode |
00 |
Active/Idle |
01 |
PM1 |
10 |
PM2 |
11 |
PM3 |
设置完成睡眠模式之后,使PCON.IDLE= 1,将立即使CC254x进入相应的非Active模式,在user’sguide里面特别有说明,在进入非Active模式,需要PCON.IDLE = 1指令必须4字节对齐地址,且之后的第一条指令必须是非4字节对齐存放。
对于PM3,由于其BOD已经不起作用,对于CC2541可以利用SRCRC.RESULT来判断电压是否Brownout。
设定SLEEP.MODE [1:0]之后,调用halSetSleepMode进入非Active模式,唤醒之后从PCON.IDLE= 1之后的指令开始执行,halSetSleepMode函数定义如下。
#pragma location ="SLEEP_CODE"
voidhalSetSleepMode(void);
……
void halSetSleepMode(void)
{
PCON =PCON_IDLE;
HAL_DISABLE_INTERRUPTS();
}
汇编之后:
halSetSleepMode:
CODE
MOV 0x87, #0x1
CLR 0xa8.7
这里面需要注意的是“PCON.IDLE =1”指令必须是4字节对齐地址,而接下来的指令(唤醒之后执行的第一条指令不能是4字节对齐地址)
打开xcl文件:
……
-D_CODE_START=0x0000
-D_CODE_END=0x7FFF // Last address for ROOT bank.
……
-D_SLEEP_CODE_SPACE_START=(_CODE_END-7)
-D_SLEEP_CODE_SPACE_END=(_CODE_END)
-Z(CODE)SLEEP_CODE=_SLEEP_CODE_SPACE_START-_SLEEP_CODE_SPACE_END
……
可以看出halSetSleepMode放置在0x7FF8的地址,满足4字节对齐要求,同时
“PCON = PCON_IDLE”占3个字节,即HAL_DISABLE_INTERRUPTS()地址在0x7FFB,不是4字节对齐,也满足要求。