这里会显示出您选择的修订版和当前版本之间的差别。
cc2640r2f:flash_map [2017/09/02 10:41] long |
cc2640r2f:flash_map [2021/06/22 23:14] |
||
---|---|---|---|
行 1: | 行 1: | ||
- | < | ||
- | # 存储架构 # | ||
- | ## Flash ## | ||
- | Flash以4KB为一个Page进行擦除/ | ||
- | |||
- | 对于协议栈以库文件方式链接的工程(_lirary): | ||
- | * **Application Image Code Space**(应用程序镜像代码区):应用程序和协议栈分为两个工程来管理,但是协议栈编译生成库文件供应用程序调用,应用程序会生成一个镜像文件,该镜像文件在应用程序的链接器配置文件中被配置:`cc26xx_app.icf`(IAR)和`cc26xx_app.cmd`(CCS)。 | ||
- | |||
- | 对于采用两个FLash镜像方式编译的工程(Split Image): | ||
- | * **Application Image Code Space**(应用程序镜像代码区):独立的应用程序Flash镜像,该镜像在应用程序的链接器配置文件中被配置:`cc26xx_app.icf`(IAR)和`cc26xx_app.cmd`(CCS)。 | ||
- | |||
- | |||
- | * **Stack Image Code Space**(协议栈镜像代码区):独立的协议栈Flash镜像。该镜像在协议栈的链接器配置文件中被配置:`cc26xx_stack.icf`(IAR)和`cc26xx_ stack.cmd`(CCS)。 | ||
- | |||
- | |||
- | * **Simple NV (SNV)Area**:非易失性存储器使用,可供应用程序和协议栈(GAP Bond Manager)使用。有关SNV的配置,请参阅本文后面的**使用Simple NV进行Flash存储**。配置时,SNV Flash存储区域是协议栈镜像的一部分。 | ||
- | |||
- | |||
- | * **Customer Configuration Area(CCA)**:Flash的最后一个Page用于存储客户特定芯片配置(CCFG)参数。CCA扇区未使用的空间被分配给应用程序项目。请参阅本文后面的**用户配置区**。 | ||
- | |||
- | ### Flash内存映射 ### | ||
- | |||
- | 本节在系统级别介绍用于两个拆分镜像项目配置的Flash内存映射。如下图1所示,应用程序链接文件存储在用实线箭头指向的内存位置和协议栈连接文件存储在用虚线箭头指向的内存位置。 | ||
- | ![图1. 系统闪存映射](http:// | ||
- | |||
- | > | ||
- | > | ||
- | |||
- | 表1.总结了图29中的`Flash System Map`定义, 并提供了可在各个IDE链接器文件中找到的关联链接器的定义或符号。 | ||
- | 表1. Flash系统映射定义 | ||
- | |||
- | |符号/ | ||
- | |: | ||
- | |APP_FLASH_START|flash的起始位置/ | ||
- | |APP_FLASH_END|应用程序镜像的结束位置(ICALL_STACK0_ADDR)|App|ADJ_ICALL_STACK0_START_FLASH_APP_BASE|FLASH_END| | ||
- | |STACK_FLASH_START|协议栈镜像的起始位置(ICALL_STACK0_ADDR)|Stack|FLASH_START|FLASH_START| | ||
- | |STACK_FLASH_END|协议栈镜像的结束位置,包括SNV|Stack|FLASH_SIZE_RESERVED_SIZE|FLASH_END| | ||
- | |CCA sector|flash最后的扇区,包括CCFG|App|FLASH_LAST_PAGE|FLASH_LAST_PAGE| | ||
- | |CCFG region|位于CCA中,用来存储本地配置参数|App|CCA的最后88个字节|CCA的最后88个字节| | ||
- | |||
- | ### 应用程序和协议栈的Flash边界 ### | ||
- | |||
- | 应用程序和协议栈代码镜像区域是基于预定义符号ICALL_STACK0_ADDR和ICALL_STACK0_START。这些值定义协议栈镜像的入口函数的硬编码Flash地址:为它本质上是应用程序和协议栈项目边界字对齐的Flash地址。了确保正确链接,应用程序和协议栈项目都必须使用相同的定义符号。默认情况下,链接器配置会将未使用的flash分配给应用程序项目,但可以通过边界工具手动或自动修改。使用边界工具配置Flash边界地址的有关信息,请参阅本文后面的**边界工具操作**。 | ||
- | |||
- | ### 使用Simple NV进行Flash存储 ### | ||
- | |||
- | Flash的Simple NV (SNV)区域用于存储不易变动的数据,例如用于绑定的加密密钥或需要存储的自定义参数。协议栈可以配置成为SNV预留最多两个4kBFlash page,尽管有效数据仅存储在一个可用的Flash page中。为了最小化Flash上的擦除周期数,当扇区具有80%的无效数据时,SNV管理器对Flash扇区(可能是多个扇区)进行压缩。压缩是将有效数据复制到临时区域,然后擦除先前存储数据的扇区。再根据`OSAL_SNV Values`中描述的OSAL_SNV值,该有效数据接着会被放回新擦除的扇区中或着保存在新扇区中。可以通过在协议栈项目中设置OSAL_SNV预处理器符号的值来配置分配给SNV的Flash扇区数目。表2列出了可配置的有效值以及相关描述。 | ||
- | 表2. OSAL_SNV值 | ||
- | |||
- | |OSAL_SNV值|描述| | ||
- | |: | ||
- | |0|SNV未使能。不能在NV中存储绑定密钥。这时应用程序和协议栈工程代码的存储区域最大。这时GAP Bond Manager也不能使能。在协议栈工程中需要设置预处理符号NO_OSAL_SNV来关闭GAP Bond Manager功能。关于配置低功耗蓝牙协议栈特征可以查看**Stack Configurations**| | ||
- | |1(默认值)|分配一个flash扇区给SNV。绑定信息存储在NV中。flash压缩时使用cache RAM作为中间存储,因此压缩期间的功率损耗将导致SNV数据丢失。此外,由于临时禁用cache,在压缩期间可能会导致系统性能的降低。在协议栈工程中设置预处理符号OSAL_SNV=1| | ||
- | |2|分配两个flash扇区给SNV。绑定信息存储在NV区。在压缩期间功率损耗时SNV数据会受到保护| | ||
- | |||
- | 将OSAL_SNV设置成其他值是无效的。设置的值越低可以为应用程序或协议栈工程分配的代码空间越大。可以使用以下API读取或写入SNV。 | ||
- | |||
- | `uint8 osal_snv_read( osalSnvId_t id, osalSnvLen_t len, void *pBuf)` | ||
- | |||
- | ||从NV读取数据| | ||
- | |形参|id-有效的NV条目< | ||
- | |返回值|SUCCESS: | ||
- | |||
- | `uint8 osal_snv_write(osalSnvId_t id,osalSnvLen_t len,void * pBuf)` | ||
- | |||
- | ||写数据到NV| | ||
- | |形参|id-有效的NV条目< | ||
- | |返回值|SUCCESS: | ||
- | |||
- | 由于SNV与BLE5-Stack中的其他模块(如GAP Bond Manager)是共享的,所以必须小心管理NV条目ID。默认情况下,客户可用的ID在bcomdef.h中有定义,如下代码所示。 | ||
- | |||
- | ```C | ||
- | 1 // Device NV Items - Range 0 - 0x1F | ||
- | 2 #define BLE_NVID_IRK | ||
- | 3 #define BLE_NVID_CSRK | ||
- | 4 #define BLE_NVID_SIGNCOUNTER | ||
- | 5 #define BLE_LRU_BOND_LIST | ||
- | |||
- | 6 // Bonding NV Items - | ||
- | 7 #define BLE_NVID_GAP_BOND_START | ||
- | 8 #define BLE_NVID_GAP_BOND_END | ||
- | |||
- | 9 // GATT Configuration NV Items - Range 0x70 - 0x79 - This must match the number of Bonding entries | ||
- | 10 #define BLE_NVID_GATT_CFG_START | ||
- | 11 #define BLE_NVID_GATT_CFG_END | ||
- | |||
- | 12 // Customer NV Items - Range 0x80 - 0x8F - This must match the number of Bonding entries | ||
- | 13 #define BLE_NVID_CUST_START | ||
- | 14 #define BLE_NVID_CUST_END | ||
- | 15 | ||
- | 16 | ||
- | 17 | ||
- | ``` | ||
- | 如下代码显示了如何从SNV flash中读取和写入一个字节数组: | ||
- | |||
- | ```C | ||
- | / | ||
- | * GLOBAL VARIABLES | ||
- | */ | ||
- | #define BUF_LEN 4 | ||
- | #define SNV_ID_APP 0x80 | ||
- | uint8 buf[BUF_LEN] ={0,}; | ||
- | |||
- | static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1) | ||
- | { | ||
- | // Initialize application | ||
- | SimpleBLEPeripheral_init(); | ||
- | uint8 status = SUCCESS; | ||
- | |||
- | status = osal_snv_read(SNV_ID_APP, | ||
- | if(status != SUCCESS) | ||
- | { | ||
- | Display_print1(dispHandle, | ||
- | //Write first time to initialize SNV ID | ||
- | osal_snv_write(SNV_ID_APP, | ||
- | } | ||
- | |||
- | //Increment first element of array and write to SNV flash | ||
- | buf[0]++; | ||
- | status = osal_snv_write(SNV_ID_APP, | ||
- | if(status != SUCCESS) | ||
- | { | ||
- | Display_print1(dispHandle, | ||
- | } | ||
- | else | ||
- | { | ||
- | Display_print1(dispHandle, | ||
- | } | ||
- | |||
- | // Application main loop | ||
- | for (;;) | ||
- | { | ||
- | //... | ||
- | } | ||
- | ``` | ||
- | |||
- | NV条目ID不需要事先初始化; | ||
- | |||
- | 当向SNV读取或写入大量数据时,TI建议将读/ | ||
- | |||
- | 默认情况下,`osalSnvId_t`和`osalSnvLen_t`被定义为`uint8`类型。要定义为`uint16`类型,需要在应用程序和协议栈项目中去修改预处理符号`OSAL_SNV_UINT16_ID`的定义。 | ||
- | |||
- | `osal_snv_read`和`osal_snv_write`只允许在任务上下文中使用。在Swis或Hwis内无法调用此API。 | ||
- | |||
- | ### 用户配置区 ### | ||
- | |||
- | 用户配置区(CCA)占用flash的最后一页,用户可以在用户配置(CCFG)表中配置各种芯片和系统的参数。ccfg_app_ble.c中定义了CCFG表,你可以在应用程序项目的`Startup`文件夹中找到ccfg_app_ble.c文件。CCA扇区的最后88个(sizeof(ccfg_t))字节由系统为CCFG表保留。默认情况下,链接器将CCA扇区未使用的Flash分配给应用程序镜像来存储代码和数据。也可以修改链接器以保留整个扇区来存储用户参数(例如,板序列号和其他标识参数)。 | ||
- | |||
- | CCA区域由应用程序的链接器文件中的`FLASH_LAST_PAGE`定义。在IDE中展示如下: | ||
- | CCS中: | ||
- | ```C | ||
- | MEMORY | ||
- | { | ||
- | ... | ||
- | // CCFG Page, contains .ccfg code section and some application code. | ||
- | FLASH_LAST_PAGE (RX) : origin = FLASH_LAST_PAGE_START, | ||
- | ... | ||
- | } | ||
- | |||
- | SECTIONS | ||
- | { | ||
- | ... | ||
- | .ccfg : | ||
- | ... | ||
- | } | ||
- | ``` | ||
- | IAR中: | ||
- | ```C | ||
- | //////////////////////////////////////////////////////////////////////////////// | ||
- | // Memory Regions | ||
- | //////////////////////////////////////////////////////////////////////////////// | ||
- | ... | ||
- | define region FLASH_LAST_PAGE | ||
- | ... | ||
- | //////////////////////////////////////////////////////////////////////////////// | ||
- | ... | ||
- | // CCFG | ||
- | place at end of FLASH_LAST_PAGE { readonly section .ccfg }; | ||
- | keep { section .ccfg } | ||
- | ``` | ||
- | 有关CCFG区域和相关配置选项的详细信息,包括如何设置CCFG以禁止对内部flash内容的访问,请参阅[CC26XX技术参考手册](http:// | ||
- | |||
- | ## RAM ## | ||
- | 与Flash类似,RAM在应用程序和协议栈工程之间也是共享。RAM部分在其各自的链接器文件中被配置。 | ||
- | |||
- | * 应用程序镜像:应用程序和共享堆的RAM空间。此镜像在应用程序的链接器配置文件中被配置:`cc26xx_app.icf`(IAR)和`cc26xx_app.cmd`(CCS)。 | ||
- | * 堆栈镜像:协议栈的`.bss`和`.data`部分的RAM空间。此镜像在协议栈的链接器配置文件中被配置:`cc26xx_stack.icf`(IAR)和`cc26xx_stack.cmd`(CCS)。 | ||
- | ### RAM内存映射 ### | ||
- | |||
- | 下面的图2**System Memory Map**展示了simple_peripheral工程默认的系统内存映射。这个图表只是一个概要,你可以在IAR中的输出文件夹或CCS中的FlashROM文件夹中的simple_peripheral_app.map和simple_peripheral_stack.map文件中找到给定编译的确切内存位置。在利用map文件查看系统flash和RAM使用情况中,应用程序链接器文件包含实心箭头指向的符号,协议栈链接器文件包含虚线箭头指向的符号。 | ||
- | |||
- | 系统内存映射 | ||
- | ![图2. 系统内存映射](http:// | ||
- | |||
- | ### 应用程序和协议栈的RAM边界 ### | ||
- | |||
- | 应用程序和协议栈的RAM内存映射基于通用的宏定义符号: | ||
- | |||
- | ### 系统堆栈 ### | ||
- | |||
- | 除了RTOS和ICall堆,考虑一下内存的其他部分。如[TI-RTOS概述](http:// | ||
- | |||
- | 对于IAR,此RTOS系统堆栈由`CSTACK`符号定义: | ||
- | ```C | ||
- | //////////////////////////////////////////////////////////////////////////////// | ||
- | // Stack | ||
- | define symbol STACK_SIZE | ||
- | define symbol STACK_START | ||
- | define symbol STACK_END | ||
- | // | ||
- | define symbol STACK_TOP | ||
- | export symbol STACK_TOP; | ||
- | |||
- | // Runtime Stack | ||
- | define block CSTACK with alignment = 8, size = STACK_SIZE { section .stack }; | ||
- | place at end of RAM { block CSTACK }; | ||
- | ``` | ||
- | 在IAR中,要更改`CSTACK`的大小,需要调整应用程序链接器文件中的`STACK_SIZE`的值。 | ||
- | |||
- | 对于CCS,RTOS系统堆栈由RTOS配置文件appBLE.cfg中的Program.stack参数定义: | ||
- | ```C | ||
- | /* main() and Hwi, Swi stack size */ | ||
- | Program.stack = 1024; | ||
- | ``` | ||
- | 并由链接器放置在应用程序的RAM空间中: | ||
- | ```C | ||
- | /* Create global constant that points to top of stack */ | ||
- | /* CCS: Change stack size under Project Properties */ | ||
- | __STACK_TOP = __stack + __STACK_SIZE; | ||
- | ``` | ||
- | ### 动态内存分配 ### | ||
- | |||
- | 系统使用两个堆进行动态内存分配。应用程序设计人员必须了解每个堆的使用情况,以便最大限度地利用可用内存。 | ||
- | |||
- | 在RTOS配置文件app_ble.cfg中,RTOS配置了一个小堆: | ||
- | ```C | ||
- | var HeapMem = xdc.useModule(' | ||
- | |||
- | BIOS.heapSize = 1668; | ||
- | ``` | ||
- | 该堆(HeapMem)用于初始化RTOS对象以及分配低功耗蓝牙协议栈的任务运行时堆栈。TI选择使用此大小的堆来满足系统初始化要求。由于此堆的体积本来就小,所以不建议从RTOS堆分配内存以供一般应用程序使用。有关TI-RTOS堆配置的更多信息,请参阅**TI-RTOS SYS/BIOS Kernel User’s Guide**中的**Heap Implementations**部分。 | ||
- | |||
- | 应用程序必须使用单独的堆。ICall模块使用应用程序RAM区域的一部分,这部分也可以由各种任务使用。该ICALL堆的大小由应用程序工程中的`HEAPMGR_SIZE`预处理符号定义。可以用非零值将ICall堆设定为指定大小,如果`HEAPMGR_SIZE`值为0,系统会自动将堆的大小设置为链接器未分配而可用的空闲RAM的大小。默认情况下,如`simple_peripheral`项目使用的是自动大小分配功能。虽然ICall堆在应用程序工程中定义,但该堆由低功耗蓝牙协议栈使用。分配内存的API(如GATT_bm_alloc())是从ICall堆分配内存。 | ||
- | |||
- | 要分析ICALL堆使用的情况,需要在应用程序工程的预处理器符号中定义`HEAPMGR_METRICS`。启用自动堆大小功能后要确定ICall堆的大小的有关信息,请参阅**Profiling the ICall Heap Manager (heapmgr.h)**。 | ||
- | |||
- | > | ||
- | |||
- | 以下是使用ICALL堆动态分配可变长度(n)数组的示例: | ||
- | ```C | ||
- | //define pointer | ||
- | uint8_t *pArray; | ||
- | // Create dynamic pointer to array. | ||
- | if (pArray = (uint8_t*)ICall_malloc(n*sizeof(uint8_t))) | ||
- | { | ||
- | //fill up array | ||
- | } | ||
- | else | ||
- | { | ||
- | //not able to allocate | ||
- | } | ||
- | ``` | ||
- | 以下是释放上一个数组空间的示例: | ||
- | ```C | ||
- | ICall_free(pMsg-> | ||
- | ``` | ||
- | ## 缓存(Cache)/ | ||
- | 缓存是为处理器在RAM上保留的一个8KB空间。缓存模块临时存储从Flash读取的数据,以便经常使用的数据不需要每次访问Flash来获取。这样可以减少CPU等待状态并节省电量。当不使用缓存时就不对它供电。当缓存没有工作时就让它处于待机和空闲的状态。 | ||
- | |||
- | ### 把缓存作为RAM使用 ### | ||
- | |||
- | 如果应用程序需要更多内存,或者SRAM空间,则缓存可以当作RAM使用。这样链接器就可以将编译应用程序的一部分存储在这一部分的RAM中。这部分RAM将被称为通用RAM(GPRAM)。这样做会稍微降低程序的运行速度,并且会增加休眠状态下的设备功耗。这是因为与缓存相反的GPRAM即使是在设备休眠时也必须供电。CC2640R2F数据表中列出了具有和不具有缓存的待机模式下的当前消耗,您可以去查看验证。 | ||
- | |||
- | 上面我们已经提到,将缓存作为GPRAM使用会稍微降低运行速度以及增加功耗。对于如何影响设备的功耗将取决于应用。对于某些应用,增加的功耗会非常小,但是对于处理密集型应用,增加的功耗会略高一些。您可以使用[ Measuring Bluetooth Low Energy Power Consumption Application Report (SWRA478)](http:// | ||
- | |||
- | 把缓存作为RAM使用,需要做两件事情。首先,必须在使用这块内存的时候告诉程序是将它作为cache用还是GPRAM来用。其次,链接器必须被告知要将用作缓存的内存区域分配给GPRAM,以及哪一部分代码要存储在GPRAM中,这是在链接器的命令/ | ||
- | |||
- | 在BLE5-Stack中有一些示例项目会存在一个编译配置,允许将缓存用作RAM。对于多角色工程来说是很好的。在这种情况下,选择该编译配置就可以将缓存作为RAM使用了。在CCS中:`Project-> | ||
- | |||
- | > | ||
- | |||
- | 如果要想在没有CacheAsRAM编译配置的工程中将缓存作为RAM使用,请按照下列步骤操作: | ||
- | |||
- | > | ||
- | |||
- | 1. 在CCFG文件(`app_ble_ccfg.c`或`ccfg.c`)中,在`# | ||
- | ```C | ||
- | #ifdef CACHE_AS_RAM | ||
- | #define SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM | ||
- | #endif // | ||
- | |||
- | #include < | ||
- | ``` | ||
- | 2. 在main()中,添加以下代码: | ||
- | 清单1. 在休眠时作为缓存使用。 | ||
- | ```C | ||
- | #ifdef CACHE_AS_RAM | ||
- | // retain cache during standby | ||
- | Power_setConstraint(PowerCC26XX_SB_VIMS_CACHE_RETAIN); | ||
- | Power_setConstraint(PowerCC26XX_NEED_FLASH_IN_IDLE); | ||
- | #else | ||
- | // Enable iCache pre-fetching | ||
- | VIMSConfigure(VIMS_BASE, | ||
- | // Enable cache | ||
- | VIMSModeSet(VIMS_BASE, | ||
- | #endif // | ||
- | ``` | ||
- | |||
- | > | ||
- | |||
- | 在同一个文件中,包括以下文件:(在ble5stack项目中,这些文件已经包含在main.c中) | ||
- | ```C | ||
- | /* Power Driver */ | ||
- | #include < | ||
- | #include < | ||
- | /* Header files required to enable instruction fetch cache */ | ||
- | #include < | ||
- | #include < | ||
- | ``` | ||
- | 3.去编译器预定义选项中添加`CACHE_AS_RAM`。对于来自ble5stack文件夹的示例项目,此定义将在以下文件中对执行的代码进行更改: | ||
- | * ble_user_config.c | ||
- | * main.c | ||
- | * ble_user_config.h | ||
- | 4.去链接器预定义选项中添加`CACHE_AS_RAM=1`。这个定义会对cc26xx_app.cmd/ | ||
- | |||
- | > | ||
- | >CCS: | ||
- | > | ||
- | > | ||
- | >IAR: | ||
- | > | ||
- | > | ||
- | |||
- | 5.如果您的工程是基于BLE5-Stack的工程,这将使.bss(ll.o除外)从SRAM移动到GPRAM。LL.o需要由RF驱动器放置在SRAM中。其他对象也可以根据需要移动到`.bss`中。您可以在本文后面的**使用AUX RAM作为RAM**中找到示例。重新编译并更新您的应用程序工程。查看`.map`文件确定设备内存的哪些部分被占用。(或者在CCS中可以通过:`View-> | ||
- | |||
- | 6.如果您的项目不是基于BLE5-Stack的项目,要将cache用作GPRAM还需要进行相关修改。如果您的项目正在使用无线电,在无线电覆盖中添加`0x00018063`。 | ||
- | |||
- | 7.GPRAM内存区域必须在链接器命令文件中定义。定义语法在CCS和IAR链接器中是不同的。下面分别说明一下: | ||
- | |||
- | 在CCS中,链接器命令文件的尾缀是`.cmd`(如:`CC2640R2_LAUNCHXL_TIRTOS.cmd`)。 | ||
- | |||
- | 清单2. 在`Memory Sizes`下,添加GPRAM开始地址和长度的定义。 | ||
- | ```C | ||
- | / | ||
- | * Memory Sizes | ||
- | */ | ||
- | #define FLASH_BASE | ||
- | #define GPRAM_BASE | ||
- | #define RAM_BASE | ||
- | #define ROM_BASE | ||
- | |||
- | #ifdef CC26X0ROM | ||
- | #define FLASH_SIZE 0x00020000 | ||
- | #define GPRAM_SIZE 0x00002000 | ||
- | #define RAM_SIZE | ||
- | #define ROM_SIZE | ||
- | #endif /* CC26X0ROM */ | ||
- | ``` | ||
- | 清单3. 在`Memory Definitions`下添加GPRAM | ||
- | ```C | ||
- | / | ||
- | * GPRAM | ||
- | */ | ||
- | |||
- | #ifdef CACHE_AS_RAM | ||
- | #define GPRAM_START GPRAM_BASE | ||
- | #define GPRAM_END | ||
- | #endif /* CACHE_AS_RAM */ | ||
- | ``` | ||
- | 清单4. 在`MEMORY{}`中为GPRAM分配空间 | ||
- | ```C | ||
- | #ifdef CACHE_AS_RAM | ||
- | GPRAM(RWX) : origin = GPRAM_APP_BASE, | ||
- | #endif /* CACHE_AS_RAM */ | ||
- | ``` | ||
- | 清单5. 在`SECTIONS{}`中将`.bss`从SRAM移动到GPRAM。 | ||
- | ```C | ||
- | GROUP > SRAM | ||
- | { | ||
- | .data | ||
- | # | ||
- | .bss | ||
- | # | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | # | ||
- | } | ||
- | #else // !CACHE_AS_RAM | ||
- | } LOAD_END(heapStart) | ||
- | # | ||
- | |||
- | | ||
- | |||
- | # | ||
- | | ||
- | { | ||
- | | ||
- | | ||
- | |||
- | .bss : | ||
- | { | ||
- | | ||
- | } > GPRAM | ||
- | # | ||
- | ``` | ||
- | 重新编译你的应用程序。会将`.bss`从SRAM移动到GPRAM,放在自动堆大小开始的后面。其他对象也可以移动。请参阅本文后面的**使用AUX RAM作为RAM**查看例程。 | ||
- | |||
- | 8. 在IAR中,链接器配置文件的后缀是`.icf`(例如`CC2640R2_LAUNCHXL_TIRTOS.icf`)。 | ||
- | 清单6. 在`Memory Definitions`下面添加对GPRAM起始地址和长度的定义。 | ||
- | ```C | ||
- | ////////////////////////////////////////////////////////////////////////////// | ||
- | // GPRAM | ||
- | // | ||
- | if ( isdefinedsymbol(CACHE_AS_RAM) ) | ||
- | { | ||
- | define symbol GPRAM_START | ||
- | define symbol GPRAM_SIZE | ||
- | define symbol GPRAM_END | ||
- | } | ||
- | ``` | ||
- | 清单7. 在`Memory Regions`下面,为GPRAM分配空间。 | ||
- | ```C | ||
- | if ( isdefinedsymbol(CACHE_AS_RAM) ) | ||
- | { | ||
- | define region GPRAM = mem:[from GPRAM_START to GPRAM_END]; | ||
- | } | ||
- | ``` | ||
- | 清单8. 在`Memory Placement`下,将`.bss`从SRAM移动到GPRAM。 | ||
- | ```C | ||
- | if ( isdefinedsymbol(CACHE_AS_RAM) ) | ||
- | { | ||
- | // GPRAM | ||
- | define block GPDATA { section .bss }; | ||
- | place in GPRAM { block GPDATA } except { module ll.o }; | ||
- | } | ||
- | ``` | ||
- | 重新编译应用程序。就会将`.bss`从SRAM移动到GPRAM。其他对象也可以移动。可以在本文后面的**使用AUX RAM作为RAM**查看例程。 | ||
- | |||
- | ## AUX RAM ## | ||
- | AUX RAM是属于[传感器控制器](http:// | ||
- | |||
- | ### 使用AUX RAM作为RAM ### | ||
- | |||
- | 要在应用程序中将AUX RAM作为RAM使用,请按照以下步骤操作(先描述CCS,再描述IAR)。 | ||
- | |||
- | 1.在链接器命令文件中添加一个新的定义:在CCS中:`Project-> | ||
- | |||
- | 2.链接器命令/ | ||
- | |||
- | * 在链接器命令文件`cc26xx_app.cmd`中,定义AUX_RAM的内存区域: | ||
- | ```C | ||
- | #ifdef AUX_AS_RAM | ||
- | #define AUX_RAM_BASE | ||
- | #define AUX_RAM_SIZE | ||
- | #endif /* AUX_AS_RAM */ | ||
- | ``` | ||
- | |||
- | * 在`MEMORY{}`中创建一个AUX_RAM内存区域 | ||
- | ```C | ||
- | #ifdef AUX_AS_RAM | ||
- | AUX_RAM (RWX) : origin = AUX_RAM_BASE, | ||
- | #endif /* AUX_AS_RAM */ | ||
- | ``` | ||
- | |||
- | * 在`SECTIONS{}`中将内存或代码的部分添加到AUX_RAM中 | ||
- | |||
- | 清单9. 将目标文件移动到AUX_RAM中。示例来自simple_peripheral(`cc26xx_app.cmd`) | ||
- | ```C | ||
- | #ifdef AUX_AS_RAM | ||
- | reorganized_into_auxram | ||
- | { | ||
- | simple_peripheral.obj(.data) | ||
- | devinfoservice.obj(.data) | ||
- | simple_gatt_profile.obj(.data) | ||
- | icall.obj(.data) | ||
- | board.obj(.bss) | ||
- | } > AUX_RAM | ||
- | #endif/* AUX_AS_RAM */ | ||
- | ``` | ||
- | .obj文件放在应用程序项目的FlashROM文件夹中。它们也在.map文件中列出了大小。链接器命令文件和内存部分的详细描述在维基文章[Linker Command File Primer](http:// | ||
- | |||
- | 如果你想要更多地控制AUX_RAM中存储的内容,你可以使用命令`# | ||
- | |||
- | 清单10.将全局显示句柄的变量移动到AUX RAM中一个叫做`my_section`的新区域。 | ||
- | ```C | ||
- | // Display Interface | ||
- | #pragma DATA_SECTION(dispHandle, | ||
- | Display_Handle dispHandle = NULL; | ||
- | ``` | ||
- | 清单11. 在链接器命令文件(cc26xx_app.cmd)中,将这部分(`my_section`)添加到AUX_RAM。 | ||
- | ```C | ||
- | #ifdef AUX_AS_RAM | ||
- | reorganized_into_auxram | ||
- | { | ||
- | simple_peripheral.obj(my_section) | ||
- | } > AUX_RAM | ||
- | #endif /* AUX_AS_RAM */ | ||
- | ``` | ||
- | |||
- | > | ||
- | |||
- | 3. 对于IAR,打开链接器配置文件`cc26xx_app.icf`。在`Memory Definitions`下添加 | ||
- | ```C | ||
- | //////////////////////////////////////////////////////////////////////////////// | ||
- | // AUX_RAM | ||
- | // | ||
- | if ( isdefinedsymbol(AUX_AS_RAM) ) | ||
- | { | ||
- | define symbol AUX_RAM_START | ||
- | define symbol AUX_RAM_SIZE | ||
- | define symbol AUX_RAM_END | ||
- | } | ||
- | ``` | ||
- | * 在`Memory Regions`中,添加 | ||
- | ```C | ||
- | if ( isdefinedsymbol(AUX_AS_RAM) ) | ||
- | { | ||
- | define region AUX_RAM | ||
- | } | ||
- | ``` | ||
- | * 在`Memory Placement`下添加 | ||
- | 清单12. 将目标文件移动到AUX_RAM中。来自simple_peripheral(`cc26xx_app.icf`)的示例 | ||
- | ```C | ||
- | if ( isdefinedsymbol(AUX_AS_RAM) ) | ||
- | { | ||
- | // AUX_RAM | ||
- | define block AUXDATA { section .data object simple_peripheral.o, | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | place in AUX_RAM { block AUXDATA }; | ||
- | } | ||
- | ``` | ||
- | .o文件是在.map文件中列出的。有关链接器配置文件的更多信息,请参阅[IAR C/C++ Development Guide](http:// | ||
- | |||
- | 如果你想要更多操控AUX_RAM中存储的内容,你可以使用命令`# | ||
- | |||
- | 清单13.将全局显示句柄的变量移动到AUX RAM中一个叫做`my_section`的新区域 | ||
- | ```C | ||
- | // Display Interface | ||
- | #pragma location=" | ||
- | Display_Handle dispHandle = NULL; | ||
- | ``` | ||
- | 清单14. 在链接器配置文件(`cc26xx_app.cmd`)中,将下面这部分代码添加到AUX_RAM。 | ||
- | ```C | ||
- | if ( isdefinedsymbol(AUX_AS_RAM) ) | ||
- | { | ||
- | // AUX_RAM | ||
- | define block AUXDATA { section my_section object simple_peripheral.o }; | ||
- | place in AUX_RAM { block AUXDATA }; | ||
- | } | ||
- | ``` | ||
- | ## 边界工具 ## | ||
- | 在将应用程序和协议栈工程编译为两个镜像文件时,边界工具用来自动调整两个镜像之间共享的各个RAM和Flash的边界地址符号。应用程序将协议栈作为库使用的工程不需要使用Frontier Tool。 | ||
- | |||
- | 边界工具作为在协议栈工程编译后的一个步骤来运行,它基于对协议栈链接器和映射文件的分析来调整相应的RAM和Flash边界。边界工具不会修改任何项目文件和源代码,不运行任何编译器,也不执行链接器优化; | ||
- | |||
- | 边界工具安装到SDK中的以下路径:`< | ||
- | |||
- | 此工具的python源代码也包括在其中。 | ||
- | |||
- | 表3显示了边界工具更新的边界地址符号。 | ||
- | |||
- | 表3. 边界地址符号 | ||
- | |||
- | |边界地址符号|描述| | ||
- | |ICALL_STACK0_START|应用程序和协议栈之间的flash边界地址。代表应用程序镜像的结束和协议栈镜像的开始| | ||
- | |ICALL_STACK0_ADDR|协议栈实体的地址(flash)| | ||
- | |ICALL_RAM0_START|应用程序和协议栈之间的RAM边界地址。代表应用程序RAM的结束以及协议栈RAM的开始| | ||
- | |||
- | 默认情况下,所有的示例应用程序项目都配置成使用边界工具; | ||
- | |||
- | > | ||
- | > | ||
- | |||
- | ### 边界工具操作 ### | ||
- | |||
- | 边界工具(frontier.exe)是协议栈工程在CCS或IAR集成开发环境中编译后的进行调用的。如果需要对RAM或Flash边界进行调整,则边界工具将更新以下列出的边界链接器配置和C定义文件。要并入更新后的配置值,请在应用程序工程上执行`Project -> Rebuild All`。在重新编译应用程序之前,协议栈工程必须正确编译和链接。 | ||
- | |||
- | SDK中的每个工程都有一组配置文件,IDE的链接器和编译器利用它们设置或调整相应的Flash和RAM值。这些配置文件在应用程序和协议栈工作区之间共享,并存储在以下位置: | ||
- | `< | ||
- | |||
- | 其中`< | ||
- | |||
- | 例如,在CC2640R2F LaunchPad上运行的`simple_peripheral`示例应用程序,边界配置文件位于以下路径: | ||
- | `CCS: < | ||
- | |||
- | `IAR: < | ||
- | |||
- | 以下是边界配置文件: | ||
- | * 边界链接器配置文件:`iar_boundary.xcl`[IAR]或`ccs_linker_defines.cmd`[CCS],为链接器定义边界地址。该文件位于TOOLS IDE文件夹中,并在需要进行调整时由边界工具进行更新。 | ||
- | * 边界C定义文件:`iar_boundary.bdef`[IAR]或`ccs_compiler_defines.bcfg`[CCS]。定义编译器的边界地址。该文件位于TOOLS IDE文件夹中,并在需要进行调整时由边界工具进行更新。 | ||
- | |||
- | > | ||
- | |||
- | ## 加入我们 ## | ||
- | 文章所有代码、工具、文档开源。加入我们[**QQ群 591679055**](http:// | ||
- | <div> | ||
- | <p align=" | ||
- | <a target=" | ||
- | © Copyright 2017, 成都乐控畅联科技有限公司. | ||
- | </p> | ||
- | </ | ||
- | </ | ||