乐鑫技术交流
直播中

张虎豹

7年用户 1544经验值
私信 关注
[问答]

可以从一个利用c++标准库的项目的某处工作示例吗?

我上周收到了几块 ESP-01 板并开始摆弄它们。我安装了 esp-open-sdk 并编译了工具链。从那以后,我编译了一些纯 C 示例,并成功地自己编写了一些示例。
最近我决定升级我的游戏并尝试基于 C++ 启动和运行一些东西。我现在尝试编译的示例使用 std::string 和 std::function。每当我尝试将 libstdc++ 添加为附加库时,链接器都会抱怨

查看映射文件,所有 libstdc++ 对象确实似乎都在 iram1_0 段中结束。我对ESP8266的内存空间布局不是很了解,但是从我看这个论坛的内容来看,可以选择
将其代码放在iram1_0_seg或者irom0_0_seg中,然后按需加载并缓存到ram中。有没有办法将 libstdc++ 对象放在 irom0_0_seg 中?
我可以从一个利用 c++ 标准库的项目的某处工作示例吗?
为了完整性,我附上了我的 Makefile。
提前致谢。


回帖(1)

caosurround

2024-5-27 17:51:17
在 ESP8266 上使用 C++ 标准库需要注意内存的分配和使用。由于 ESP8266 的内存空间非常有限,因此需要特别谨慎地管理内存。以下是一个利用 C++ 标准库的示例,其中包括 std::string 和 std::function 的使用,并将代码放在 irom0_0_seg 中:

```c++
#include
#include
#include
#include

// 将代码放在 irom0_0_seg 中,以节省 iram 内存空间
extern "C" {
  volatile uint32_t _irom0_text_start;
  volatile uint32_t _irom0_text_end;
  volatile uint32_t _irom0_0_seg_start;
  volatile uint32_t _irom0_0_seg_end;
  volatile uint32_t _irom1_0_seg_start;
  volatile uint32_t _irom1_0_seg_end;

  ICACHE_RAM_ATTR const uint32_t *flash_ptr(uint32_t addr) {
    if (addr < _irom0_0_seg_start || addr >= _irom0_0_seg_end) {
      return NULL;
    }
    return (const uint32_t *)(addr - _irom0_text_start + _irom0_0_seg_start);
  }
}

ESP8266WebServer server(80);

void handleRoot() {
  std::string message = "Hello, world!";
  server.send(200, "text/plain", message.c_str());
}

void handleInline() {
  std::function f = [](int x) { return x * x; };
  server.send(200, "text/plain", "5 squared is " + std::to_string(f(5)));
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin("ssid", "password");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("WiFi connected");
  Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.on("/inline", handleInline);

  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
}
```

需要注意的是:

1. 代码需要放在 irom0_0_seg 中,需要通过 `ICACHE_RAM_ATTR` 来标记函数为在 iram 中运行。
2. 为了节省内存,可以使用 `std::string::c_str()` 来获取字符串的指针,然后将其传递给 `server.send()` 函数。
3. `std::function` 的使用可能会导致内存分配,因此在代码中需要注意内存使用情况。
4. 在编译时需要将 `-std=c++11` 添加到编译器选项中,以支持 C++11 标准。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分