通过以下四种方法可以优化 ESP8266 应用的内存使用,减少应用的内存占用空间。
1. 将字符串放到 Flash 中: (1) 有些字符串可以放在 Flash 中,特别是长字符串,例如 HTML 请求和响应模板。 比如,一个字符串原来是用 define 定义的: #define test_string "hello world” 现在可以定义成如下: static const char test_string[] ICACHE_RODATA_ATTR = "hello world"; (2) 当用 ICACHE_RODATA_ATTR 定义字符串常量时,需要对数据内容进行四字节对齐读取。由于 Flash 中的数据需要四字节对其读取,所以定义一个宏获取对齐后的字符串长度: #define GET_ALIGN_STRING_LEN(str) ((strlen(str) + 3) & ~3) 使用字符串时,动态分配一个新的数组对象,读写 Flash 中的数据。然后用 os_memcpy API 来复制数据内容: unsigned int str_len = GET_ALIGN_STRING_LEN(test_string); char *tmp_string = (char *)os_malloc(str_len); os_memcpy(tmp_string, test_string, str_len); (3) 在用户的应用代码里使用 tmp_string 进行操作,而不使用 test_string。此方法除了减少应用的 RAM 占用空间,也能解决由于对 Flash 中的数据进行非对齐读取时,在应用中引起的 exception。 …….
(4) 当用户代码中,无需再使用通过以上方法读取的数据,需要释放之前分配的内存空间 os_free(tmp_string); 注意:如果不释放之前分配的内存空间,重复分配内存将会减少核心功能所需的内存,导致 API 出现功能异常或失败。
2. 把 const 数据放到 Flash: (1) uint32 类型的数组可以直接放到 Flash,比如: const uint32 array[4] ICACHE_RODATA_ATTR = {0x11111111, 0x22222222, 0x33333333, 0x44444444}; 可以直接使用 array[0]。
(2) 对于 uint8 和 uint16 类型的数组,要注意读取数据的时候要四字节对齐, 比如: const uint8 array[7] ICACHE_RODATA_ATTR = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; (3) 如果需要按字节读取 char 数组当中的元素,可从软件上进行处理,先按四字节读取,然后再按偏移取当中的一个字节。如果直接读取 array[0],会导致 crash。
(4) 对于数据结构,通常做法是分配比用户需要读取的结构更大的内存,从 Flash 四字节读取数据到内存。如同方法 1,在代码中依然使用对象指针。修改代码操作内存中的数据结构,而不是读取数组。
3. 将调试字符串放到 Flash 中: 现在默认的 printf 打印的字符串都还是放在 RAM 区,占用部分内存。如果用户无需频繁打印日志文件,或者调试字符串太长,可以使用优化的 os_printf 把打印的字符串放到 Flash 而不是 RAM 中。
4. 避免使用全局数组变量: 全局数组变量会在应用的整个生存期中占用不必要的内存。为减少全局数组变量的使用,乐鑫提供了动态内存分配 API。在基于事件的编程中,请使用 os_malloc 和 os_free 来动态分配所需的内存空间。但注意,我们不建议过于频繁地分配和释放大小不等的内存空间。
QQ:2355573208
|