Customer Configuration (CCFG) parameters are stored 3.10.2 应用和栈Flash边界
应用和栈的代码镜像是基于共同的ICALL_STACKO_ADDR定义的。这个值定义了栈镜像的整个功能硬编码flash地址(4kB对齐):本质上就是应用-协议栈工程边界的Flash地址。为了确保适当的连接,应用和栈工程都必须使用同一个ICALL_STACK0_ADDR定义值。默认的ICALL_STACK0_ADDR被配置为调用没用的flash给应用工程,但是可以通过边界工具手动或自动修改。参考3.10.3节是关于手动修改flash边界地址的,3.12节是关于使用边界工具配置flash边界地址的。
3.10.3 手动修改flash地址
如上所诉,边界工具(Boundary Tool)是用来调整ICALL_STACK0_ADDR应用-栈flash边界的以便可以分配最大的flash内存空间给应用工程。尽管不是典型的要求,ICALL_STACK0_ADDR可以通过下面的步骤进行修改: IAR的步骤:
不翻译 CCS的步骤:
1. 调整在TOOLS/ccsLinkerDefines.cmd文件中的ICALL_STACK0_ADDR
--define=ICALL_STACK0_ADDR=0x0000B000
2. 调整应用工程中的预编译符号ICALL_STACK0_ADDR
ICALL_STACK0_ADDR=0xB000
3.重新编译应用和栈工程,验证是两个工程中是否有编译错误。
修改ICALL_STACK0_ADDR时需注意的几点:
1. ICALL_STACK0_ADDR的值必须是个4kB对齐的地址。分配给应用的flash内存空间
越大,分配给栈的空间就越小。
2. ICALL_STACK0_ADDR的值必须符合IAR-Boundary.xcl & IAR-Boundary.bdef文件,
或者要符合ccsLinkderDefines.cmd & preprocessor symbol for CCS。 3. 所有的应用和栈工程必须在ICALL_STACK0_ADDR修改后重新编译。 4. 如果在手动修改ICALL_STACK0_ADDR时发生了连接错误,验证每个工程是否有足
够的内存调用。
3.10.4 使用简单的NV(SNV)
flash中的SNV区域是用来保存稳定的数据以一种稳定的方式,诸如绑定的加密密匙或者存储用户参数。协议栈可以通过配置分配最高2个4kB的flash页给SNV。为了达到最少对flash的擦写,SNV管理者会在扇区存在80%以上的非法数据时会对扇区进行压缩。一次压缩就是将有效数据复制到紧跟着用来存储预先存储的数据的内存存储块的后面的区域。依据OSAL_SNV的值,作出如下的决定,有效数据是保存在新擦除的区域中还是继续保留在新的区域中。可以分配给SNV的flash内存块的数量可以通过配置栈工程中的OSAL_SNV预处理符的值来决定。下面的表列出了有效数值和相关的取舍问题: OSAL_SNV 值 0 描述 禁能SNV,在NV中保存绑定信息是不可能了。最大的应用和(或)栈工程的代码空间。GAP绑定管理必须禁能。在栈工程中,设置预处理符号NO_OSAL_SNV和禁能GAP绑定管理。参考10.4章中关于配置BLE协议栈 1 2 一个flash块调用给SNV。绑定信息存储在NV中。Flash 默认值。分配两个Flash扇区给SNV。绑定信息存储在NV中。SNV数据在压实阶段可以防止掉电丢失。 其他所有的值都是无效的。使用少于最大值的情况下对调用更多代码空间给应用或栈工程有用。
SNV可以通过下面的接口读写: Uint8 osal_snv_read(osalSnvld_t id, osalSnvLen_t len, void *pBuf 描述:从SNV中读取数据 参数: Id:有效的NV的主题 Len:要读取的数据长度 pBuf:存储读取到的数据的缓存指针 返回值: SUCCESS:NV 主题读取成功 NV_OPER_FAILED:读取失败 Uint8 osal_snv_write(osalSnvld_t id, osalSnvLen_t len, void *pBuf) 描述:往SNV中写数据 参数: Id:有效的NV的主题 Len:要写的数据长度 pBuf:要写的数据的缓存指针 返回值: SUCCESS:NV 主题写成功 NV_OPER_FAILED:写失败 由于SNV在BLE SDK中是与其他模块诸如GapBondMgr共享的,所以有必要仔细管理NV的主题ID。通常默认情况下,提供给用户的ID在bcomdef.h文件中定义:
// Customer NV Items - Range 0x80 - 0x8F - This must match the number of Bonding entries #define BLE_NVID_CUST_START 0x80 //!< Start of the Customer's NV IDs #define BLE_NVID_CUST_END 0x8F //!< End of the Customer's NV IDs
3.10.5 用户配置区域(CCA)
CCA占领了flash的最后一页,允许用户在用户配置表(CCFG)中配置不同的芯片和系统参数。CCFG在ccfg_appBLE.c文件中定义,可以在应用工程的设置文件夹中找到。CCA的最后86个字节被系统预留给CCFG表。通常默认情况下,连接器调用CCA扇区中没用到的flash给应用镜像作为代码或数据存储空间用,然而连接器可以修改为整个扇区都留给用户参数数据(举例说明,板子序列号和其他证明参数)。
CCA分配在应用的连接文件中定义,定义符号为FLASH_LAST_PAGE;位置与编译器有关:
CCS:
FLASH_LAST_PAGE (RX) : origin = FLASH_SIZE - 0x1000, length = 0x1000 …
.ccfg : > FLASH_LAST_PAGE (HIGH)
IAR:
define region FLASH_LAST_PAGE = mem:[from(FLASH_SIZE) - 0x1000 to FLASH_SIZE-1]; …
place at end of FLASH_LAST_PAGE { readonly section .ccfg };
参考TRM【2】获取CCFG区域和有关配置操作的更多信息。
3.11内存管理(RAM)
与flash相似,RAM也是在应用和栈工程间共享。RAM扇区在它们的相关连接文件中配置: 1. 应用镜像:应用和共享头的RAM空间。这个是在应用连接配置文件中配置:
cc26xx_ble_stack.icf(IAR)和cc2650f128_tirtos_ccs.cmd(CCS).
2. 栈镜像:栈的.bss和.data扇区的RAM。这个实在栈的连接配置文件中配置:
cc26xx_ble_stack.icf(IAR)和cc2650f128_tirtos_ccs_stack.cmd(CCS).
3.11.1 RAM内存映射
下图展示了默认程序SimpleBLEPeripheral工程的系统内存映射。注意这是概况的和精准的内存分配对于给定的编译来说,可以在SimpleBLEPerihperalApp.map和SimpleBLEPeripheralStack.map文件中找到,这些文件位于IAR的输出文件夹或者是CCS中的FlashROM文件夹中。阅读第9.11章获取这些文件的更多信息。在下面的图中,符号指向的实线队列可以在应用连接文件中找到,符号指向的虚线队列可以在栈的连接文件中找到。
3.11.2 应用和栈的RAM边界
应用和栈RAM内存映射是基于共同的ICALL_RAM0_ADDR宏。这个值定义了硬件编码的应用的RAM空间的尾部和栈镜像的.BSS和.DATA扇区的起始的RAM边界。注意与flash边界的不同知乎在于,栈工程的元素,诸如任务栈和头,是在应用工程中调用。为了确保合适的连接,应用
工程和栈工程都必须使用同一个ICALL_RAM0_ADDR值。默认情况下,ICALL_RAM0_ADDR用来配置为分配没有用到的RAM给应用工程但是可以通过边界工具修改位自动或手懂设置。扇区0是手动修改RAM边界地址,3.12张介绍使用边界工具来配置RAM的边界地址。
3.11.3 系统栈
另外像上面提到的RTOS和ICall头,有其他的内存可以考虑。就像在3.3.1中描述的一样,每个人物都有自己的运行时间栈以适应上下文切换。甚至于,这里有RTOS使用的另一个运行时间栈给main()函数,硬件中断和软件中断。这个系统栈在应用连接文件中调用用来替换应用尾部的应用RAM
对于IAR来说,这个RTOS系统栈是通过CSTACK符号定义的:
//////////////////////////////////////////////////////////////////////////////// // Stack //
define symbol STACK_SIZE = 0x400; define symbol STACK_START = RAM_END + 1;
define symbol STACK_END = STACK_START - STACK_SIZE;
define block CSTACK with alignment = 8, size = STACK_SIZE { section .stack }; //
define symbol STACK_TOP = RAM_END + 1; export symbol STACK_TOP; //
place at end of RAM { block CSTACK };
在IAR中,通过修改应用连接文件中的STACK_SIZE符号的值傀来改变CSTACK的大小
对于CCS来说,RTOS系统栈是appBLE.cfg中的Program.stack参数定义的RTOS配置文件:
/* main() and Hwi, Swi stack size */ Program.stack = 1024;
通过连接器在应用RAM空间中替换:
/* Create global constant that points to top of stack */ /* CCS: Change stack size under Project Properties */ __STACK_TOP = __stack + __STACK_SIZE;
3.11.4 手动修改RAM的边界
像上面提到的,边界工具用来调整ICALL_RAM0_ADDR应用栈的边界以便于给应用工程提供忒大的RAM。尽管不是要求的,ICALL_RAM0_ADDR可以通过下面的步骤手动修改。 IAR的做法:
1. 在栈工程中应用边界工具,阅读3.12配置边界工具 2. 在IAR_Boundary.xcl中调整ICALL_STACK0_ADDR
--config_def ICALL_RAM0_ADDR=0x200043AC
3. 重新编译应用和栈工程。验证两个工程是否有编译错误。 CCS的做法:
1. TOOL/ccsLinkerDefines.cmd 中调整ICALL_RAM0_ADDR:
--define=ICALL_RAM0_ADDR=0x200043AC
2. 重新编译应用栈工程,验证两个工程是否有编译错误。
当修改ICALL_RAM0_ADDR时需记住以下几点
1. ICALL_RAM0_ADDR的值必须是4字节对齐的地址。
2. 当ICALL_RAM0_ADDR被修改后,应用和栈工程都必须清除并重新编译。