这里会显示出您选择的修订版和当前版本之间的差别。
后一修订版 | 前一修订版 | ||
cc2640r2f:flash_map [2017/08/31 16:30] 127.0.0.1 外部编辑 |
cc2640r2f:flash_map [2021/06/22 23:14] (当前版本) |
||
---|---|---|---|
行 1: | 行 1: | ||
< | < | ||
+ | |||
# 存储架构 # | # 存储架构 # | ||
+ | |||
## Flash ## | ## Flash ## | ||
- | Flash以4KB为一个Page进行擦除/ | ||
- | 对于协议栈以库文件方式链接的工程(_lirary): | + | Flash 以 4KB 为一个 Page 进行擦除/ |
- | * **Application Image Code Space**(应用程序镜像代码区):应用程序和协议栈分为两个工程来管理,但是协议栈编译生成库文件供应用程序调用,应用程序会生成一个镜像文件,该镜像文件在应用程序的链接器配置文件中被配置:`cc26xx_app.icf`(IAR)和`cc26xx_app.cmd`(CCS)。 | + | |
- | 对于采用两个FLash镜像方式编译的工程(Split Image): | + | 对于协议栈以库文件方式链接的工程( _lirary ): |
- | * **Application Image Code Space**(应用程序镜像代码区):独立的应用程序Flash镜像,该镜像在应用程序的链接器配置文件中被配置:`cc26xx_app.icf`(IAR)和`cc26xx_app.cmd`(CCS)。 | + | |
+ | * ** Application Image Code Space **(应用程序镜像代码区):应用程序和协议栈分为两个工程来管理,协议栈编译生成库文件供应用程序调用。应用程序会生成一个镜像文件,该镜像文件在应用程序的链接器配置文件中被配置为 `cc26xx_app.icf`(IAR)和 `cc26xx_app.cmd`(CCS)。 | ||
- | * **Stack Image Code Space**(协议栈镜像代码区):独立的协议栈Flash镜像。该镜像在协议栈的链接器配置文件中被配置:`cc26xx_stack.icf`(IAR)和`cc26xx_ stack.cmd`(CCS)。 | + | 对于采用两个 FLash 镜像方式编译的工程( Split Image |
+ | * ** Application Image Code Space **(应用程序镜像代码区):独立的应用程序 Flash 镜像,该镜像在应用程序的链接器配置文件中被配置为 `cc26xx_app.icf`(IAR)和 `cc26xx_app.cmd`(CCS)。 | ||
- | * **Simple NV (SNV)Area**:非易失性存储器使用,可供应用程序和协议栈(GAP Bond Manager)使用。有关SNV的配置,请参阅本文后面的**使用Simple NV进行Flash存储**。配置时,SNV Flash存储区域是协议栈镜像的一部分。 | ||
+ | * ** Stack Image Code Space **(协议栈镜像代码区):独立的协议栈Flash镜像。该镜像在协议栈的链接器配置文件中被配置: `cc26xx_stack.icf`(IAR)和 `cc26xx_ stack.cmd`(CCS)。 | ||
- | * **Customer Configuration Area(CCA)**:Flash的最后一个Page用于存储客户特定芯片配置(CCFG)参数。CCA扇区未使用的空间被分配给应用程序项目。请参阅本文后面的**用户配置区**。 | ||
- | ### Flash内存映射 ### | + | * ** Simple NV (SNV)Area **:非易失性存储器使用,可供应用程序和协议栈(GAP Bond Manager)使用。有关 SNV 的配置请参阅本文后面的**使用 Simple NV 进行 Flash 存储**。配置时,SNV Flash 存储区域是协议栈镜像的一部分。 |
+ | |||
+ | |||
+ | * ** Customer Configuration Area(CCA)**:Flash 的最后一个 Page 用于存储客户特定芯片配置(CCFG)参数。CCA 扇区未使用的空间被分配给应用程序项目,详情请参阅本文后面的**用户配置区**。 | ||
+ | |||
+ | ### Flash 内存映射 ### | ||
+ | |||
+ | 本节介绍用于两个拆分镜像项目配置的 Flash 内存映射。如下图1所示,应用程序链接文件存储在用实线箭头指向的内存位置,协议栈链接文件存储在用虚线箭头指向的内存位置。 | ||
- | 本节在系统级别介绍用于两个拆分镜像项目配置的Flash内存映射。如下图1所示,应用程序链接文件存储在用实线箭头指向的内存位置和协议栈连接文件存储在用虚线箭头指向的内存位置。 | ||
![图1. 系统闪存映射](http:// | ![图1. 系统闪存映射](http:// | ||
- | > | + | > |
> | > | ||
- | 表1.总结了图29中的`Flash System Map`定义, 并提供了可在各个IDE链接器文件中找到的关联链接器的定义或符号。 | + | 下表总结了图 |
- | 表1. Flash系统映射定义 | + | |
+ | 表1. Flash 系统映射定义 | ||
|符号/ | |符号/ | ||
行 39: | 行 46: | ||
|CCFG region|位于CCA中,用来存储本地配置参数|App|CCA的最后88个字节|CCA的最后88个字节| | |CCFG region|位于CCA中,用来存储本地配置参数|App|CCA的最后88个字节|CCA的最后88个字节| | ||
- | ### 应用程序和协议栈的Flash边界 ### | + | ### 应用程序和协议栈的 Flash 边界 |
+ | |||
+ | 应用程序和协议栈代码镜像区域是基于预定义符号 ICALL_STACK0_ADDR 和 ICALL_STACK0_START 的,这些值定义协议栈镜像入口函数的硬编码 Flash 地址,它本质上是应用程序和协议栈项目边界字对齐的 Flash 地址。为了确保正确链接,应用程序和协议栈项目都必须使用相同的定义符号。默认情况下,链接器配置会将未使用的 Flash 分配给应用程序项目,但可以通过边界工具手动或自动修改。使用边界工具配置 Flash 边界地址的有关信息,请参阅本文后面的**边界工具操作**。 | ||
+ | |||
+ | ### 使用 Simple NV 进行 Flash 存储 | ||
- | 应用程序和协议栈代码镜像区域是基于预定义符号ICALL_STACK0_ADDR和ICALL_STACK0_START。这些值定义协议栈镜像的入口函数的硬编码Flash地址:为它本质上是应用程序和协议栈项目边界字对齐的Flash地址。了确保正确链接,应用程序和协议栈项目都必须使用相同的定义符号。默认情况下,链接器配置会将未使用的flash分配给应用程序项目,但可以通过边界工具手动或自动修改。使用边界工具配置Flash边界地址的有关信息,请参阅本文后面的**边界工具操作**。 | + | Flash 的 Simple NV (SNV)区域用于存储不易变动的数据,例如用于绑定的加密密钥或需要存储的自定义参数。协议栈可以配置成为 SNV 预留最多两个 4kB Flash page ,有效数据仅存储在一个可用的 Flash page 中。为了最小化 Flash 上的擦除周期数,当扇区具有 80% 的无效数据时,SNV 管理器对 |
- | ### 使用Simple NV进行Flash存储 ### | + | 表 2 列出了可配置的有效值以及相关描述。 |
- | 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 值 |
- | 表2. OSAL_SNV值 | + | |
|OSAL_SNV值|描述| | |OSAL_SNV值|描述| | ||
|: | |: | ||
- | |0|SNV未使能。不能在NV中存储绑定密钥。这时应用程序和协议栈工程代码的存储区域最大。这时GAP Bond Manager也不能使能。在协议栈工程中需要设置预处理符号NO_OSAL_SNV来关闭GAP Bond Manager功能。关于配置低功耗蓝牙协议栈特征可以查看**Stack Configurations**| | + | | 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| | + | | 1 (默认值)|分配一个 |
- | |2|分配两个flash扇区给SNV。绑定信息存储在NV区。在压缩期间功率损耗时SNV数据会受到保护| | + | | 2 |分配两个 |
- | 将OSAL_SNV设置成其他值是无效的。设置的值越低可以为应用程序或协议栈工程分配的代码空间越大。可以使用以下API读取或写入SNV。 | + | 将 OSAL_SNV 设置成其他值是无效的。设置的值越低,给应用程序或协议栈工程分配的代码空间就越大。可以使用以下 API 读取或写入 SNV 。 |
`uint8 osal_snv_read( osalSnvId_t id, osalSnvLen_t len, void *pBuf)` | `uint8 osal_snv_read( osalSnvId_t id, osalSnvLen_t len, void *pBuf)` | ||
- | ||从NV读取数据| | + | ||从 NV 读取数据| |
- | |形参|id-有效的NV条目< | + | |形参|id -有效的 NV 条目< |
- | |返回值|SUCCESS: | + | |返回值|SUCCESS: |
`uint8 osal_snv_write(osalSnvId_t id,osalSnvLen_t len,void * pBuf)` | `uint8 osal_snv_write(osalSnvId_t id,osalSnvLen_t len,void * pBuf)` | ||
- | ||写数据到NV| | + | ||写数据到 NV | |
- | |形参|id-有效的NV条目< | + | |形参|id -有效的 NV 条目< |
- | |返回值|SUCCESS: | + | |返回值|SUCCESS: |
- | 由于SNV与BLE5-Stack中的其他模块(如GAP Bond Manager)是共享的,所以必须小心管理NV条目ID。默认情况下,客户可用的ID在bcomdef.h中有定义,如下代码所示。 | + | 由于 SNV 与 BLE5-Stack 中的其他模块(如 GAP Bond Manager)是共享的,所以必须小心管理 NV 条目 ID。默认情况下,客户可用的 ID 在 bcomdef.h 中有定义,如下代码所示。 |
```C | ```C | ||
行 92: | 行 102: | ||
17 | 17 | ||
``` | ``` | ||
- | 如下代码显示了如何从SNV flash中读取和写入一个字节数组: | + | 如下代码显示了如何从 SNV flash 中读取和写入一个字节数组: |
```C | ```C | ||
行 135: | 行 145: | ||
``` | ``` | ||
- | NV条目ID不需要事先初始化; OSAL SNV管理器在首次调用osal_snv_write()成功访问SNV时会初始化NV ID。 | + | NV 条目 ID 不需要事先初始化,OSAL SNV 管理器在首次调用 osal_snv_write()成功访问 SNV 时会初始化 NV ID。 |
- | 当向SNV读取或写入大量数据时,TI建议将读/ | + | 当向 SNV 读取或写入大量数据时,TI 建议将读/ |
- | 默认情况下,`osalSnvId_t`和`osalSnvLen_t`被定义为`uint8`类型。要定义为`uint16`类型,需要在应用程序和协议栈项目中去修改预处理符号`OSAL_SNV_UINT16_ID`的定义。 | + | 默认情况下,`osalSnvId_t` 和 `osalSnvLen_t` 被定义为 `uint8` 类型。如果定义为 `uint16` 类型,需要在应用程序和协议栈项目中去修改预处理符号 `OSAL_SNV_UINT16_ID` 的定义。 |
- | `osal_snv_read`和`osal_snv_write`只允许在任务上下文中使用。在Swis或Hwis内无法调用此API。 | + | `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)占用 |
+ | |||
+ | CCA 区域由应用程序链接器文件中的 `FLASH_LAST_PAGE` 定义。在 IDE 中展示如下: | ||
+ | |||
+ | CCS 中: | ||
- | CCA区域由应用程序的链接器文件中的`FLASH_LAST_PAGE`定义。在IDE中展示如下: | ||
- | CCS中: | ||
```C | ```C | ||
MEMORY | MEMORY | ||
行 165: | 行 177: | ||
} | } | ||
``` | ``` | ||
- | IAR中: | + | |
+ | IAR 中: | ||
```C | ```C | ||
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||
行 179: | 行 193: | ||
keep { section .ccfg } | keep { section .ccfg } | ||
``` | ``` | ||
- | 有关CCFG区域和相关配置选项的详细信息,包括如何设置CCFG以禁止对内部flash内容的访问,请参阅[CC26XX技术参考手册](http:// | + | |
+ | 有关 CCFG 区域和相关配置选项的详细信息,以及如何设置 CCFG 来禁止对内部 | ||
## RAM ## | ## RAM ## | ||
- | 与Flash类似,RAM在应用程序和协议栈工程之间也是共享。RAM部分在其各自的链接器文件中被配置。 | ||
- | * 应用程序镜像:应用程序和共享堆的RAM空间。此镜像在应用程序的链接器配置文件中被配置:`cc26xx_app.icf`(IAR)和`cc26xx_app.cmd`(CCS)。 | + | 与 Flash 类似,RAM 在应用程序和协议栈工程之间也是共享。RAM 部分在其各自的链接器文件中被配置。 |
- | * 堆栈镜像:协议栈的`.bss`和`.data`部分的RAM空间。此镜像在协议栈的链接器配置文件中被配置:`cc26xx_stack.icf`(IAR)和`cc26xx_stack.cmd`(CCS)。 | + | |
- | ### 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 ** System Memory Map **展示了 simple_peripheral 工程默认的系统内存映射。这个图只是一个概要,你可以在 IAR 中的输出文件夹或 CCS 中的 FlashROM 文件夹中的 simple_peripheral_app.map 和 simple_peripheral_stack.map 文件中找到给定编译的确切内存位置。在利用 map 文件查看系统 flash 和 RAM 使用情况时,应用程序链接器文件包含实心箭头指向的符号,协议栈链接器文件包含虚线箭头指向的符号。 |
- | 系统内存映射 | ||
![图2. 系统内存映射](http:// | ![图2. 系统内存映射](http:// | ||
- | ### 应用程序和协议栈的RAM边界 ### | + | ### 应用程序和协议栈的 RAM 边界 ### |
- | 应用程序和协议栈的RAM内存映射基于通用的宏定义符号: | + | 应用程序和协议栈的 RAM 内存映射基于通用的宏定义符号: |
### 系统堆栈 ### | ### 系统堆栈 ### | ||
- | 除了RTOS和ICall堆,考虑一下内存的其他部分。如[TI-RTOS概述](http:// | + | 除了 RTOS 和 ICall 堆,考虑一下内存的其他部分。如[ TI-RTOS 概述](http:// |
+ | |||
+ | IAR 的 RTOS 系统堆栈由 `CSTACK` 符号定义: | ||
- | 对于IAR,此RTOS系统堆栈由`CSTACK`符号定义: | ||
```C | ```C | ||
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||
行 216: | 行 233: | ||
place at end of RAM { block CSTACK }; | place at end of RAM { block CSTACK }; | ||
``` | ``` | ||
- | 在IAR中,要更改`CSTACK`的大小,需要调整应用程序链接器文件中的`STACK_SIZE`的值。 | ||
- | 对于CCS,RTOS系统堆栈由RTOS配置文件appBLE.cfg中的Program.stack参数定义: | + | 在 IAR 中,更改 `CSTACK` 的大小需要调整应用程序链接器文件中的 `STACK_SIZE` 的值。 |
+ | |||
+ | CCS 的 RTOS 系统堆栈由 RTOS 配置文件 appBLE.cfg 中的 Program.stack 参数定义: | ||
```C | ```C | ||
/* main() and Hwi, Swi stack size */ | /* main() and Hwi, Swi stack size */ | ||
Program.stack = 1024; | Program.stack = 1024; | ||
``` | ``` | ||
- | 并由链接器放置在应用程序的RAM空间中: | + | |
+ | 并由链接器放置在应用程序的 RAM 空间中: | ||
```C | ```C | ||
/* Create global constant that points to top of stack */ | /* Create global constant that points to top of stack */ | ||
行 229: | 行 250: | ||
__STACK_TOP = __stack + __STACK_SIZE; | __STACK_TOP = __stack + __STACK_SIZE; | ||
``` | ``` | ||
+ | |||
### 动态内存分配 ### | ### 动态内存分配 ### | ||
系统使用两个堆进行动态内存分配。应用程序设计人员必须了解每个堆的使用情况,以便最大限度地利用可用内存。 | 系统使用两个堆进行动态内存分配。应用程序设计人员必须了解每个堆的使用情况,以便最大限度地利用可用内存。 | ||
- | 在RTOS配置文件app_ble.cfg中,RTOS配置了一个小堆: | + | 在 RTOS 配置文件 app_ble.cfg 中,RTOS 配置了一个小堆: |
```C | ```C | ||
var HeapMem = xdc.useModule(' | var HeapMem = xdc.useModule(' | ||
行 239: | 行 262: | ||
BIOS.heapSize = 1668; | 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堆分配内存。 | + | 该堆( HeapMem )用于初始化 RTOS 对象、分配低功耗蓝牙协议栈的任务运行时堆栈。TI 选择使用此大小的堆来满足系统初始化要求。由于此堆的体积本来就小,所以不建议从 RTOS 堆分配内存以供一般应用程序使用。有关 TI-RTOS 堆配置的更多信息,请参阅** TI-RTOS SYS/BIOS Kernel User’s Guide **中的** Heap Implementations **部分。 |
- | 要分析ICALL堆使用的情况,需要在应用程序工程的预处理器符号中定义`HEAPMGR_METRICS`。启用自动堆大小功能后要确定ICall堆的大小的有关信息,请参阅**Profiling the ICall Heap Manager (heapmgr.h)**。 | + | 应用程序必须使用单独的堆。ICall 模块使用应用程序 RAM 区域的一部分,这部分也可以由各种任务使用。ICALL 堆的大小由应用程序工程中的 `HEAPMGR_SIZE` |
- | > | + | 分析 ICALL 堆使用的情况需要在应用程序工程的预处理器符号中定义 `HEAPMGR_METRICS` 。启用自动堆大小功能后要确定 ICall 堆的大小的有关信息,请参阅** Profiling the ICall Heap Manager ( heapmgr.h )**。 |
+ | |||
+ | > | ||
+ | |||
+ | 以下是使用 ICALL 堆动态分配可变长度(n)数组的示例: | ||
- | 以下是使用ICALL堆动态分配可变长度(n)数组的示例: | ||
```C | ```C | ||
//define pointer | //define pointer | ||
行 261: | 行 286: | ||
} | } | ||
``` | ``` | ||
+ | |||
以下是释放上一个数组空间的示例: | 以下是释放上一个数组空间的示例: | ||
+ | |||
```C | ```C | ||
ICall_free(pMsg-> | ICall_free(pMsg-> | ||
``` | ``` | ||
- | ## 缓存(Cache)/ | ||
- | 缓存是为处理器在RAM上保留的一个8KB空间。缓存模块临时存储从Flash读取的数据,以便经常使用的数据不需要每次访问Flash来获取。这样可以减少CPU等待状态并节省电量。当不使用缓存时就不对它供电。当缓存没有工作时就让它处于待机和空闲的状态。 | ||
- | ### 把缓存作为RAM使用 ### | + | ## 缓存( Cache )/ GPRAM ## |
- | 如果应用程序需要更多内存,或者SRAM空间,则缓存可以当作RAM使用。这样链接器就可以将编译应用程序的一部分存储在这一部分的RAM中。这部分RAM将被称为通用RAM(GPRAM)。这样做会稍微降低程序的运行速度,并且会增加休眠状态下的设备功耗。这是因为与缓存相反的GPRAM即使是在设备休眠时也必须供电。CC2640R2F数据表中列出了具有和不具有缓存的待机模式下的当前消耗,您可以去查看验证。 | + | 缓存是为处理器在 RAM 上保留的一个 8KB 空间。缓存模块临时存储从 Flash 读取的数据,以便经常使用的数据不需要每次访问 Flash 来获取。这样可以减少 CPU 等待状态并节省电量,当不使用缓存时就不对它供电,当缓存没有工作时就让它处于待机和空闲的状态。 |
- | 上面我们已经提到,将缓存作为GPRAM使用会稍微降低运行速度以及增加功耗。对于如何影响设备的功耗将取决于应用。对于某些应用,增加的功耗会非常小,但是对于处理密集型应用,增加的功耗会略高一些。您可以使用[ Measuring Bluetooth Low Energy Power Consumption Application Report (SWRA478)](http:// | + | ### 把缓存作为 |
- | 把缓存作为RAM使用,需要做两件事情。首先,必须在使用这块内存的时候告诉程序是将它作为cache用还是GPRAM来用。其次,链接器必须被告知要将用作缓存的内存区域分配给GPRAM,以及哪一部分代码要存储在GPRAM中,这是在链接器的命令/ | + | 如果应用程序需要更多内存或者 SRAM 空间,则缓存可以当作 RAM 使用。这样链接器就可以将编译应用程序的一部分存储在这一部分的 RAM 中,这部分 RAM 将被称为通用 RAM( GPRAM )。但这样做会稍微降低程序的运行速度,并且会增加休眠状态下的设备功耗。主要是因为与缓存相反的 GPRAM 即使是在设备休眠时也必须供电。CC2640R2F 数据表中列出了具有和不具有缓存的待机模式下的当前消耗,您可以去查看验证。 |
- | 在BLE5-Stack中有一些示例项目会存在一个编译配置,允许将缓存用作RAM。对于多角色工程来说是很好的。在这种情况下,选择该编译配置就可以将缓存作为RAM使用了。在CCS中:`Project-> | + | 上面已经提到将缓存作为 GPRAM 使用会稍微降低运行速度以及增加功耗,如何影响设备的功耗还是取决于应用。对于某些应用增加的功耗会非常小,但是对于处理密集型应用增加的功耗会略高一些。您可以使用[ Measuring Bluetooth Low Energy Power Consumption Application Report (SWRA478)](http:// |
+ | |||
+ | 把缓存作为 RAM 使用需要做两件事情。首先,必须在使用这块内存的时候告诉程序是将它作为 Cache 还是 GPRAM 。其次,链接器必须被告知将要用作缓存的内存区域分配给 GPRAM ,以及哪一部分代码要存储在 GPRAM 中,这是在链接器的命令/ | ||
+ | |||
+ | BLE5-Stack中有一些示例项目会存在一个编译配置,允许将缓存用作 RAM 。对于多角色工程来说是很好的,在这种情况下,选择该编译配置就可以将缓存作为 RAM 使用了。 | ||
+ | 在 CCS 中:`Project -> Build Configurations -> Set Active -> FlashROM-CacheAsRAM `。 | ||
+ | 在 IAR 中:`Project -> Edit Configurations -> FlashROM - CacheAsRAM`。 | ||
> | > | ||
- | 如果要想在没有CacheAsRAM编译配置的工程中将缓存作为RAM使用,请按照下列步骤操作: | + | 如果要想在没有 CacheAsRAM 编译配置的工程中将缓存作为 RAM 使用,请按照下列步骤操作: |
- | > | + | > |
+ | |||
+ | 1. 在CCFG 文件(`app_ble_ccfg.c` 或 `ccfg.c` )中 `#include < | ||
- | 1. 在CCFG文件(`app_ble_ccfg.c`或`ccfg.c`)中,在`# | ||
```C | ```C | ||
#ifdef CACHE_AS_RAM | #ifdef CACHE_AS_RAM | ||
行 292: | 行 324: | ||
#include < | #include < | ||
``` | ``` | ||
- | 2. 在main()中,添加以下代码: | + | |
+ | 2. main() 中添加以下代码: | ||
清单1. 在休眠时作为缓存使用。 | 清单1. 在休眠时作为缓存使用。 | ||
+ | |||
```C | ```C | ||
#ifdef CACHE_AS_RAM | #ifdef CACHE_AS_RAM | ||
行 307: | 行 342: | ||
``` | ``` | ||
- | > | + | > |
+ | |||
+ | 在同一个文件中,包括以下文件:(Ble5stack 项目中这些文件已经包含在 main.c 中) | ||
- | 在同一个文件中,包括以下文件:(在ble5stack项目中,这些文件已经包含在main.c中) | ||
```C | ```C | ||
/* Power Driver */ | /* Power Driver */ | ||
行 318: | 行 354: | ||
#include < | #include < | ||
``` | ``` | ||
- | 3.去编译器预定义选项中添加`CACHE_AS_RAM`。对于来自ble5stack文件夹的示例项目,此定义将在以下文件中对执行的代码进行更改: | + | |
+ | 3.编译器预定义选项中添加 `CACHE_AS_RAM` 。对于来自 | ||
* ble_user_config.c | * ble_user_config.c | ||
* main.c | * main.c | ||
* ble_user_config.h | * ble_user_config.h | ||
- | 4.去链接器预定义选项中添加`CACHE_AS_RAM=1`。这个定义会对cc26xx_app.cmd/ | + | |
+ | 4.链接器预定义选项中添加 `CACHE_AS_RAM=1` 。这个定义会对 cc26xx_app.cmd/ | ||
> | > | ||
+ | |||
>CCS: | >CCS: | ||
- | > | + | > |
- | > | + | > |
>IAR: | >IAR: | ||
- | > | + | > |
- | > | + | > |
- | 5.如果您的工程是基于BLE5-Stack的工程,这将使.bss(ll.o除外)从SRAM移动到GPRAM。LL.o需要由RF驱动器放置在SRAM中。其他对象也可以根据需要移动到`.bss`中。您可以在本文后面的**使用AUX RAM作为RAM**中找到示例。重新编译并更新您的应用程序工程。查看`.map`文件确定设备内存的哪些部分被占用。(或者在CCS中可以通过:`View-> | + | 5.如果您的工程是基于 BLE5-Stack 的工程,这将使 .bss (ll.o 除外)从 SRAM 移动到 GPRAM ,LL.o 需要由 RF 驱动器放置在 SRAM 中。其他对象也可以根据需要移动到 `.bss` 中。您可以在本文后面的**使用 AUX RAM 作为 RAM **中找到示例。 |
+ | 重新编译并更新您的应用程序工程,查看 `.map` 文件确定设备内存的哪些部分被占用。(或者在 CCS 中可以通过:`View -> Memory Allocation `) | ||
- | 6.如果您的项目不是基于BLE5-Stack的项目,要将cache用作GPRAM还需要进行相关修改。如果您的项目正在使用无线电,在无线电覆盖中添加`0x00018063`。 | + | 6.如果您的项目不是基于 BLE5-Stack 的项目,要将 |
- | 7.GPRAM内存区域必须在链接器命令文件中定义。定义语法在CCS和IAR链接器中是不同的。下面分别说明一下: | + | 7.GPRAM 内存区域必须在链接器命令文件中定义。定义语法在 CCS 和 IA R链接器中是不同的。下面分别说明一下: |
- | 在CCS中,链接器命令文件的尾缀是`.cmd`(如:`CC2640R2_LAUNCHXL_TIRTOS.cmd`)。 | + | 在 CCS 中,链接器命令文件的尾缀是 `.cmd`(如:`CC2640R2_LAUNCHXL_TIRTOS.cmd` )。 |
+ | |||
+ | 清单2. 在 `Memory Sizes` 下,添加 GPRAM 开始地址和长度的定义。 | ||
- | 清单2. 在`Memory Sizes`下,添加GPRAM开始地址和长度的定义。 | ||
```C | ```C | ||
/ | / | ||
行 357: | 行 399: | ||
#endif /* CC26X0ROM */ | #endif /* CC26X0ROM */ | ||
``` | ``` | ||
- | 清单3. 在`Memory Definitions`下添加GPRAM | + | |
+ | 清单3. 在 `Memory Definitions` 下添加 GPRAM | ||
```C | ```C | ||
/ | / | ||
行 368: | 行 412: | ||
#endif /* CACHE_AS_RAM */ | #endif /* CACHE_AS_RAM */ | ||
``` | ``` | ||
- | 清单4. 在`MEMORY{}`中为GPRAM分配空间 | + | |
+ | 清单4. 在 `MEMORY{}` 中为 GPRAM 分配空间 | ||
```C | ```C | ||
#ifdef CACHE_AS_RAM | #ifdef CACHE_AS_RAM | ||
行 407: | 行 453: | ||
# | # | ||
``` | ``` | ||
- | 重新编译你的应用程序。会将`.bss`从SRAM移动到GPRAM,放在自动堆大小开始的后面。其他对象也可以移动。请参阅本文后面的**使用AUX RAM作为RAM**查看例程。 | ||
- | 8. 在IAR中,链接器配置文件的后缀是`.icf`(例如`CC2640R2_LAUNCHXL_TIRTOS.icf`)。 | + | 重新编译你的应用程序会将 `.bss` 从 SRAM 移动到 GPRAM ,放在自动堆大小开始的后面,其他对象也可以移动。请参阅本文后面的**使用 AUX RAM 作为 RAM **查看例程。 |
- | 清单6. 在`Memory Definitions`下面添加对GPRAM起始地址和长度的定义。 | + | |
+ | 8. 在 IAR 中,链接器配置文件的后缀是 `.icf`(例如 `CC2640R2_LAUNCHXL_TIRTOS.icf` )。 | ||
+ | |||
+ | 清单6. 在 `Memory Definitions` 下面添加对 GPRAM 起始地址和长度的定义。 | ||
```C | ```C | ||
////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////// | ||
行 422: | 行 471: | ||
} | } | ||
``` | ``` | ||
- | 清单7. 在`Memory Regions`下面,为GPRAM分配空间。 | + | |
+ | 清单7. 在 `Memory Regions`下面为 GPRAM 分配空间。 | ||
```C | ```C | ||
if ( isdefinedsymbol(CACHE_AS_RAM) ) | if ( isdefinedsymbol(CACHE_AS_RAM) ) | ||
行 429: | 行 480: | ||
} | } | ||
``` | ``` | ||
- | 清单8. 在`Memory Placement`下,将`.bss`从SRAM移动到GPRAM。 | + | |
+ | 清单8. 在 `Memory Placement` 下将 `.bss` 从 SRAM 移动到 GPRAM。 | ||
```C | ```C | ||
if ( isdefinedsymbol(CACHE_AS_RAM) ) | if ( isdefinedsymbol(CACHE_AS_RAM) ) | ||
行 438: | 行 491: | ||
} | } | ||
``` | ``` | ||
- | 重新编译应用程序。就会将`.bss`从SRAM移动到GPRAM。其他对象也可以移动。可以在本文后面的**使用AUX RAM作为RAM**查看例程。 | + | |
+ | 重新编译应用程序就会将 `.bss` 从 SRAM 移动到 GPRAM,其他对象也可以移动。可以在本文后面的**使用 AUX RAM 作为 RAM **查看例程。 | ||
## AUX RAM ## | ## AUX RAM ## | ||
- | AUX RAM是属于[传感器控制器](http:// | ||
- | ### 使用AUX RAM作为RAM ### | + | AUX RAM 是属于[传感器控制器](http:// |
+ | |||
+ | ### 使用 AUX RAM 作为 RAM ### | ||
+ | |||
+ | 要在应用程序中将 AUX RAM 作为 RAM 使用,请按照以下步骤操作(先描述 CCS,再描述 IAR)。 | ||
- | 要在应用程序中将AUX RAM作为RAM使用,请按照以下步骤操作(先描述CCS,再描述IAR)。 | + | 1.在链接器命令文件中添加一个新的定义: |
+ | 在 CCS 中:`Project -> Properties -> ARM Linker-> | ||
+ | 在 IAR 中: | ||
- | 1.在链接器命令文件中添加一个新的定义:在CCS中:`Project-> | + | 2.链接器命令/配置文件 CCS 和 IAR 有些不同。这里先介绍在 CCS 中更改链接器配置文件,再介绍 IAR。 |
- | 2.链接器命令/配置文件在CCS和IAR中有些不同。这里先介绍在CCS中更改链接器配置文件,再介绍IAR。 | + | * 在链接器命令文件 |
- | * 在链接器命令文件`cc26xx_app.cmd`中,定义AUX_RAM的内存区域: | ||
```C | ```C | ||
#ifdef AUX_AS_RAM | #ifdef AUX_AS_RAM | ||
行 459: | 行 517: | ||
``` | ``` | ||
- | * 在`MEMORY{}`中创建一个AUX_RAM内存区域 | + | * 在 `MEMORY{}` 中创建一个 AUX_RAM 内存区域 |
```C | ```C | ||
#ifdef AUX_AS_RAM | #ifdef AUX_AS_RAM | ||
行 466: | 行 525: | ||
``` | ``` | ||
- | * 在`SECTIONS{}`中将内存或代码的部分添加到AUX_RAM中 | + | * 在 `SECTIONS{}` 中将内存或代码的部分添加到 AUX_RAM 中 |
+ | |||
+ | 清单9. 将目标文件移动到 AUX_RAM 中。示例来自 simple_peripheral( `cc26xx_app.cmd` ) | ||
- | 清单9. 将目标文件移动到AUX_RAM中。示例来自simple_peripheral(`cc26xx_app.cmd`) | ||
```C | ```C | ||
#ifdef AUX_AS_RAM | #ifdef AUX_AS_RAM | ||
行 481: | 行 541: | ||
#endif/* AUX_AS_RAM */ | #endif/* AUX_AS_RAM */ | ||
``` | ``` | ||
- | .obj文件放在应用程序项目的FlashROM文件夹中。它们也在.map文件中列出了大小。链接器命令文件和内存部分的详细描述在维基文章[Linker Command File Primer](http:// | ||
- | 如果你想要更多地控制AUX_RAM中存储的内容,你可以使用命令`# | + | .obj 文件放在应用程序项目的 FlashROM 文件夹中,它们也在 .map 文件中列出了大小。链接器命令文件和内存部分的详细描述在 WiKi 文章[ Linker Command File Primer ](http:// |
+ | |||
+ | 如果你想要更多地控制 AUX_RAM 中存储的内容,你可以使用命令 `#pragma DATA_SECTION` 将指定的变量存储里面。但请注意,这仅适用于全局变量。 | ||
+ | |||
+ | 清单10.将全局显示句柄的变量移动到 AUX RAM 中一个叫做 `my_section` 的新区域。 | ||
- | 清单10.将全局显示句柄的变量移动到AUX RAM中一个叫做`my_section`的新区域。 | ||
```C | ```C | ||
// Display Interface | // Display Interface | ||
行 491: | 行 553: | ||
Display_Handle dispHandle = NULL; | Display_Handle dispHandle = NULL; | ||
``` | ``` | ||
- | 清单11. 在链接器命令文件(cc26xx_app.cmd)中,将这部分(`my_section`)添加到AUX_RAM。 | + | |
+ | 清单11. 在链接器命令文件( cc26xx_app.cmd )中,将这部分( `my_section` )添加到 AUX_RAM。 | ||
```C | ```C | ||
#ifdef AUX_AS_RAM | #ifdef AUX_AS_RAM | ||
行 501: | 行 565: | ||
``` | ``` | ||
- | > | + | > |
+ | |||
+ | 3. 对于 IAR ,打开链接器配置文件 `cc26xx_app.icf` ,在 `Memory Definitions` 下添加 | ||
- | 3. 对于IAR,打开链接器配置文件`cc26xx_app.icf`。在`Memory Definitions`下添加 | ||
```C | ```C | ||
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||
行 515: | 行 580: | ||
} | } | ||
``` | ``` | ||
- | * 在`Memory Regions`中,添加 | + | |
+ | * 在 `Memory Regions` 中添加 | ||
```C | ```C | ||
if ( isdefinedsymbol(AUX_AS_RAM) ) | if ( isdefinedsymbol(AUX_AS_RAM) ) | ||
行 522: | 行 589: | ||
} | } | ||
``` | ``` | ||
- | * 在`Memory Placement`下添加 | + | |
- | 清单12. 将目标文件移动到AUX_RAM中。来自simple_peripheral(`cc26xx_app.icf`)的示例 | + | * 在 `Memory Placement` 下添加 |
+ | |||
+ | 清单12. 将目标文件移动到 AUX_RAM 中。来自 simple_peripheral( `cc26xx_app.icf` )的示例 | ||
```C | ```C | ||
if ( isdefinedsymbol(AUX_AS_RAM) ) | if ( isdefinedsymbol(AUX_AS_RAM) ) | ||
行 536: | 行 606: | ||
} | } | ||
``` | ``` | ||
- | .o文件是在.map文件中列出的。有关链接器配置文件的更多信息,请参阅[IAR C/C++ Development Guide](http:// | ||
- | 如果你想要更多操控AUX_RAM中存储的内容,你可以使用命令`# | + | .o 文件是在 .map 文件中列出的。有关链接器配置文件的更多信息,请参阅[ IAR C/C++ Development Guide ](http:// |
+ | |||
+ | 如果你想要更多操控 AUX_RAM 中存储的内容,你可以使用命令 `#pragma DATA_SECTION` 将指定的变量存储在里面。但请注意,这仅适用于全局变量。 | ||
+ | |||
+ | 清单13.将全局显示句柄的变量移动到 AUX RAM 中一个叫做 `my_section` 的新区域 | ||
- | 清单13.将全局显示句柄的变量移动到AUX RAM中一个叫做`my_section`的新区域 | ||
```C | ```C | ||
// Display Interface | // Display Interface | ||
行 546: | 行 618: | ||
Display_Handle dispHandle = NULL; | Display_Handle dispHandle = NULL; | ||
``` | ``` | ||
- | 清单14. 在链接器配置文件(`cc26xx_app.cmd`)中,将下面这部分代码添加到AUX_RAM。 | + | |
+ | 清单14. 在链接器配置文件( `cc26xx_app.cmd` )中,将下面这部分代码添加到 AUX_RAM | ||
```C | ```C | ||
if ( isdefinedsymbol(AUX_AS_RAM) ) | if ( isdefinedsymbol(AUX_AS_RAM) ) | ||
行 556: | 行 630: | ||
``` | ``` | ||
## 边界工具 ## | ## 边界工具 ## | ||
- | 在将应用程序和协议栈工程编译为两个镜像文件时,边界工具用来自动调整两个镜像之间共享的各个RAM和Flash的边界地址符号。应用程序将协议栈作为库使用的工程不需要使用Frontier Tool。 | ||
- | 边界工具作为在协议栈工程编译后的一个步骤来运行,它基于对协议栈链接器和映射文件的分析来调整相应的RAM和Flash边界。边界工具不会修改任何项目文件和源代码,不运行任何编译器,也不执行链接器优化; | + | 在将应用程序和协议栈工程编译为两个镜像文件时,边界工具用来自动调整两个镜像之间共享的各个 RAM 和 Flash 的边界地址符号。应用程序将协议栈作为库使用的工程不需要使用 |
- | 边界工具安装到SDK中的以下路径:`< | + | 边界工具作为在协议栈工程编译后的一个步骤来运行,它基于对协议栈链接器和映射文件的分析来调整相应的 RAM 和 Flash 边界。边界工具不会修改任何项目文件和源代码,不运行任何编译器,也不执行链接器优化,只用于调整和更新位于编译器和链接器配置文件中的各个 Flash 和 RAM 的边界地址。应用程序以及协议栈工程都会使用这些配置文件。 |
- | 此工具的python源代码也包括在其中。 | + | 边界工具安装到 SDK 中的以下路径: |
+ | `< | ||
+ | |||
+ | 此工具的 python 源代码也包括在其中。 | ||
表3显示了边界工具更新的边界地址符号。 | 表3显示了边界工具更新的边界地址符号。 | ||
- | 表3. 边界地址符号 | + | 表3.边界地址和符号 |
|边界地址符号|描述| | |边界地址符号|描述| | ||
- | |ICALL_STACK0_START|应用程序和协议栈之间的flash边界地址。代表应用程序镜像的结束和协议栈镜像的开始| | + | |: |
- | |ICALL_STACK0_ADDR|协议栈实体的地址(flash)| | + | |ICALL_STACK0_START|应用程序和协议栈之间的 |
- | |ICALL_RAM0_START|应用程序和协议栈之间的RAM边界地址。代表应用程序RAM的结束以及协议栈RAM的开始| | + | |ICALL_STACK0_ADDR|协议栈实体的地址(Flash)| |
+ | |ICALL_RAM0_START|应用程序和协议栈之间的 RAM 边界地址。代表应用程序 RAM 的结束以及协议栈 RAM 的开始| | ||
- | 默认情况下,所有的示例应用程序项目都配置成使用边界工具; 因此,不需要进行边界工具的用户配置。当协议栈配置更改时,或者在协议栈工程中一些文件的更新导致协议栈镜像大小发生变化,边界文件可能会更新。因此在每次协议栈工程编译后都必须重新编译应用程序工程。 | + | 默认情况下所有的示例应用程序项目都配置成使用边界工具,不需要进行边界工具的用户配置。当协议栈配置更改时,或者在协议栈工程中一些文件的更新导致协议栈镜像大小发生变化,边界文件可能会更新。因此在每次协议栈工程编译后都必须重新编译应用程序工程。 |
> | > | ||
- | > | + | > frontier tool 替代了早期 SDK 中使用的边界工具。 |
### 边界工具操作 ### | ### 边界工具操作 ### | ||
- | 边界工具(frontier.exe)是协议栈工程在CCS或IAR集成开发环境中编译后的进行调用的。如果需要对RAM或Flash边界进行调整,则边界工具将更新以下列出的边界链接器配置和C定义文件。要并入更新后的配置值,请在应用程序工程上执行`Project -> Rebuild All`。在重新编译应用程序之前,协议栈工程必须正确编译和链接。 | + | 边界工具( frontier.exe )是协议栈工程在 CCS 或 IAR 集成开发环境中编译后进行调用的。如果需要对 RAM 或 Flash 边界进行调整,则边界工具将更新以下列出的边界链接器配置和 C 定义文件。要并入更新后的配置值,请在应用程序工程上执行`Project -> Rebuild All `。在重新编译应用程序之前,协议栈工程必须正确编译和链接。 |
+ | |||
+ | SDK 中的每个工程都有一组配置文件,IDE 的链接器和编译器利用它们设置或调整相应的 Flash 和 RAM 值。这些配置文件在应用程序和协议栈工作区之间共享,并存储在以下位置: | ||
- | SDK中的每个工程都有一组配置文件,IDE的链接器和编译器利用它们设置或调整相应的Flash和RAM值。这些配置文件在应用程序和协议栈工作区之间共享,并存储在以下位置: | ||
`< | `< | ||
- | 其中`< | + | 其中 `< |
+ | |||
+ | 例如,在 CC2640R2F LaunchPad 上运行的 `simple_peripheral` 示例应用程序,边界配置文件位于以下路径: | ||
- | 例如,在CC2640R2F LaunchPad上运行的`simple_peripheral`示例应用程序,边界配置文件位于以下路径: | ||
`CCS: < | `CCS: < | ||
行 593: | 行 672: | ||
以下是边界配置文件: | 以下是边界配置文件: | ||
- | * 边界链接器配置文件:`iar_boundary.xcl`[IAR]或`ccs_linker_defines.cmd`[CCS],为链接器定义边界地址。该文件位于TOOLS IDE文件夹中,并在需要进行调整时由边界工具进行更新。 | ||
- | * 边界C定义文件:`iar_boundary.bdef`[IAR]或`ccs_compiler_defines.bcfg`[CCS]。定义编译器的边界地址。该文件位于TOOLS IDE文件夹中,并在需要进行调整时由边界工具进行更新。 | ||
- | > | + | * 边界链接器配置文件:`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:// | 文章所有代码、工具、文档开源。加入我们[**QQ群 591679055**](http:// | ||
<div> | <div> | ||
行 607: | 行 688: | ||
</ | </ | ||
</ | </ | ||
- |