main.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. #include "sdkconfig.h"
  2. #include <iostream>
  3. #include <string>
  4. #include <vector>
  5. #include <regex>
  6. #include "esp_psram.h"
  7. #include "esp_pm.h"
  8. #include "psram.h"
  9. #include "esp_chip_info.h"
  10. #include "esp_vfs_fat.h"
  11. #include "ffconf.h"
  12. #include "driver/sdmmc_host.h"
  13. #include "defines.h"
  14. #include "Helper.h"
  15. #include "read_network_config.h"
  16. #include "network_init.h"
  17. #include "server_ota.h"
  18. #include "MainFlowControl.h"
  19. #include "ClassLogFile.h"
  20. #include "time_sntp.h"
  21. #include "statusled.h"
  22. #include "sdcard_check.h"
  23. #ifdef DISABLE_BROWNOUT_DETECTOR
  24. #include "soc/soc.h"
  25. #include "soc/rtc_cntl_reg.h"
  26. #endif
  27. extern const char *GIT_TAG;
  28. extern const char *GIT_REV;
  29. extern const char *GIT_BRANCH;
  30. extern const char *BUILD_TIME;
  31. extern std::string getFwVersion(void);
  32. extern std::string getHTMLversion(void);
  33. extern std::string getHTMLcommit(void);
  34. bool setCpuFrequency(void);
  35. static const char *TAG = "MAIN";
  36. bool init_nvs_sd_card()
  37. {
  38. esp_err_t ret = nvs_flash_init();
  39. if (ret == ESP_ERR_NVS_NO_FREE_PAGES)
  40. {
  41. ESP_ERROR_CHECK(nvs_flash_erase());
  42. ret = nvs_flash_init();
  43. }
  44. ESP_LOGD(TAG, "Using SDMMC peripheral");
  45. sdmmc_host_t host = SDMMC_HOST_DEFAULT();
  46. host.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
  47. // For SoCs where the SD power can be supplied both via an internal or external (e.g. on-board LDO) power supply.
  48. // When using specific IO pins (which can be used for ultra high-speed SDMMC) to connect to the SD card
  49. // and the internal LDO power supply, we need to initialize the power supply first.
  50. #if SD_PWR_CTRL_LDO_INTERNAL_IO
  51. sd_pwr_ctrl_ldo_config_t ldo_config = {
  52. .ldo_chan_id = CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID,
  53. };
  54. sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
  55. ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
  56. if (ret != ESP_OK)
  57. {
  58. ESP_LOGE(TAG, "Failed to create a new on-chip LDO power control driver");
  59. return false;
  60. }
  61. host.pwr_ctrl_handle = pwr_ctrl_handle;
  62. #endif
  63. // This initializes the slot without card detect (CD) and write protect (WP) signals.
  64. // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
  65. #ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
  66. sdmmc_slot_config_t slot_config = {
  67. .cd = SDMMC_SLOT_NO_CD,
  68. .wp = SDMMC_SLOT_NO_WP,
  69. };
  70. #else
  71. sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
  72. #endif
  73. // Set bus width to use:
  74. #ifdef __SD_USE_ONE_LINE_MODE__
  75. slot_config.width = 1;
  76. #ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
  77. slot_config.clk = GPIO_SDCARD_CLK;
  78. slot_config.cmd = GPIO_SDCARD_CMD;
  79. slot_config.d0 = GPIO_SDCARD_D0;
  80. #endif // end CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
  81. #else // else __SD_USE_ONE_LINE_MODE__
  82. slot_config.width = 4;
  83. #ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
  84. slot_config.d1 = GPIO_SDCARD_D1;
  85. slot_config.d2 = GPIO_SDCARD_D2;
  86. slot_config.d3 = GPIO_SDCARD_D3;
  87. #endif // end CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
  88. #endif // end __SD_USE_ONE_LINE_MODE__
  89. // Enable internal pullups on enabled pins. The internal pullups
  90. // are insufficient however, please make sure 10k external pullups are
  91. // connected on the bus. This is for debug / example purpose only.
  92. slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
  93. // Der PullUp des GPIO13 wird durch slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
  94. // nicht gesetzt, da er eigentlich nicht benötigt wird,
  95. // dies führt jedoch bei schlechten Kopien des AI_THINKER Boards
  96. // zu Problemen mit der SD Initialisierung und eventuell sogar zur reboot-loops.
  97. // Um diese Probleme zu kompensieren, wird der PullUp manuel gesetzt.
  98. gpio_set_pull_mode(GPIO_SDCARD_D3, GPIO_PULLUP_ONLY); // HS2_D3
  99. // Options for mounting the filesystem.
  100. // If format_if_mount_failed is set to true, SD card will be partitioned and
  101. // formatted in case when mounting fails.
  102. esp_vfs_fat_sdmmc_mount_config_t mount_config = {
  103. .format_if_mount_failed = false,
  104. .max_files = 12, // previously -> 2022-09-21: 5, 2023-01-02: 7
  105. .allocation_unit_size = 0, // 0 = auto
  106. .disk_status_check_enable = 0,
  107. };
  108. sdmmc_card_t *card;
  109. const char mount_point[] = MOUNT_POINT;
  110. // Use settings defined above to initialize SD card and mount FAT filesystem.
  111. // Note: esp_vfs_fat_sdmmc_mount is an all-in-one convenience function.
  112. // Please check its source code and implement error recovery when developing production applications.
  113. ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);
  114. if (ret != ESP_OK)
  115. {
  116. if (ret == ESP_FAIL)
  117. {
  118. ESP_LOGE(TAG, "Failed to mount FAT filesystem on SD card. Check SD card filesystem (only FAT supported) or try another card");
  119. set_status_led(SDCARD_INIT, 1, true);
  120. }
  121. else if (ret == 263)
  122. {
  123. // Error code: 0x107 --> usually: SD not found
  124. ESP_LOGE(TAG, "SD card init failed. Check if SD card is properly inserted into SD card slot or try another card");
  125. set_status_led(SDCARD_INIT, 2, true);
  126. }
  127. else
  128. {
  129. ESP_LOGE(TAG, "SD card init failed. Check error code or try another card");
  130. set_status_led(SDCARD_INIT, 3, true);
  131. }
  132. return false;
  133. }
  134. // sdmmc_card_print_info(stdout, card); // With activated CONFIG_NEWLIB_NANO_FORMAT --> capacity not printed correctly anymore
  135. save_sd_card_info(card);
  136. return true;
  137. }
  138. esp_err_t init_psram(void)
  139. {
  140. // Init external PSRAM
  141. // ********************************************
  142. esp_err_t result = esp_psram_init();
  143. if (result == ESP_FAIL)
  144. {
  145. // ESP_FAIL -> Failed to init PSRAM
  146. ESP_LOGE(TAG, "PSRAM init failed (%s)! PSRAM not found or defective", std::to_string(result).c_str());
  147. set_system_statusflag(SYSTEM_STATUS_PSRAM_BAD);
  148. set_status_led(PSRAM_INIT, 1, true);
  149. return ESP_FAIL;
  150. }
  151. else
  152. {
  153. // ESP_OK -> PSRAM init OK --> continue to check PSRAM size
  154. size_t psram_size = esp_psram_get_size();
  155. ESP_LOGI(TAG, "PSRAM size: %s byte (%s MB / %s MBit)", std::to_string(psram_size).c_str(), std::to_string(psram_size / 1024 / 1024).c_str(), std::to_string(psram_size / 1024 / 1024 * 8).c_str());
  156. // Check PSRAM size
  157. // ********************************************
  158. if (psram_size < (4 * 1024 * 1024))
  159. {
  160. // PSRAM is below 4 MBytes (32Mbit)
  161. ESP_LOGE(TAG, "PSRAM size >= 4MB (32Mbit) is mandatory to run this application");
  162. set_system_statusflag(SYSTEM_STATUS_PSRAM_BAD);
  163. set_status_led(PSRAM_INIT, 2, true);
  164. return ESP_FAIL;
  165. }
  166. else
  167. {
  168. // PSRAM size OK --> continue to check heap size
  169. size_t _hsize = get_heapsize();
  170. ESP_LOGI(TAG, "Total heap: %s byte", std::to_string(_hsize).c_str());
  171. // Check heap memory
  172. // ********************************************
  173. if (_hsize < 4000000)
  174. {
  175. // Check available Heap memory for a bit less than 4 MB (a test on a good device showed 4187558 bytes to be available)
  176. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Total heap >= 4000000 byte is mandatory to run this application");
  177. set_system_statusflag(SYSTEM_STATUS_HEAP_TOO_SMALL);
  178. set_status_led(PSRAM_INIT, 3, true);
  179. return ESP_FAIL;
  180. }
  181. else
  182. {
  183. // HEAP size OK --> continue to reserve shared memory block and check camera init
  184. // Allocate static PSRAM memory regions
  185. if (reserve_psram_shared_region() == false)
  186. {
  187. ESP_LOGI(TAG, "Allocate static PSRAM memory regions failed, heap too small!");
  188. set_system_statusflag(SYSTEM_STATUS_HEAP_TOO_SMALL);
  189. set_status_led(PSRAM_INIT, 3, true);
  190. return ESP_FAIL;
  191. }
  192. else
  193. {
  194. ESP_LOGI(TAG, "Allocate static PSRAM memory regions ok");
  195. return ESP_OK;
  196. }
  197. }
  198. }
  199. }
  200. return ESP_OK;
  201. }
  202. esp_err_t init_camera(void)
  203. {
  204. Camera.set_flash_light_on_off(false);
  205. Camera.power_reset_camera();
  206. esp_err_t result = Camera.init_camera();
  207. // Check camera init
  208. // ********************************************
  209. if (result != ESP_OK)
  210. {
  211. // Camera init failed, retry to init
  212. char camStatusHex[33];
  213. sprintf(camStatusHex, "0x%02x", result);
  214. LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Camera init failed (" + std::string(camStatusHex) + "), retrying...");
  215. Camera.power_reset_camera();
  216. result = Camera.init_camera();
  217. Camera.set_flash_light_on_off(false);
  218. if (result != ESP_OK)
  219. {
  220. // Camera init failed again
  221. sprintf(camStatusHex, "0x%02x", result);
  222. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera init failed (" + std::string(camStatusHex) + ")! Check camera module and/or proper electrical connection");
  223. set_system_statusflag(SYSTEM_STATUS_CAM_BAD);
  224. Camera.set_flash_light_on_off(false); // make sure flashlight is off
  225. set_status_led(CAM_INIT, 1, true);
  226. return ESP_FAIL;
  227. }
  228. }
  229. Camera.set_flash_light_on_off(false); // make sure flashlight is off before start of flow
  230. // Print camera infos
  231. // ********************************************
  232. char caminfo[50];
  233. sensor_t *sensor = esp_camera_sensor_get();
  234. sprintf(caminfo, "PID: 0x%02x, VER: 0x%02x, MIDL: 0x%02x, MIDH: 0x%02x", sensor->id.PID, sensor->id.VER, sensor->id.MIDH, sensor->id.MIDL);
  235. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Camera info: " + std::string(caminfo));
  236. return ESP_OK;
  237. }
  238. extern "C" void app_main(void)
  239. {
  240. #ifdef DISABLE_BROWNOUT_DETECTOR
  241. WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector
  242. #endif
  243. #if (defined(BOARD_ESP32_S3_ETH_V1) || defined(BOARD_ESP32_S3_ETH_V2))
  244. // Configure IO Pad as General Purpose IO,
  245. // so that it can be connected to internal Matrix,
  246. // then combined with one or more peripheral signals.
  247. gpio_pad_select_gpio(PER_ENABLE);
  248. gpio_set_direction(PER_ENABLE, GPIO_MODE_OUTPUT);
  249. gpio_set_level(PER_ENABLE, 1);
  250. #endif
  251. // ********************************************
  252. // Highlight start of app_main
  253. // ********************************************
  254. ESP_LOGI(TAG, "\n\n\n\n================ Start app_main =================");
  255. // Init SD card
  256. // ********************************************
  257. if (!init_nvs_sd_card())
  258. {
  259. ESP_LOGE(TAG, "!!! Device init aborted at step: init_nvs_sd_card() !!!");
  260. set_system_statusflag(SYSTEM_STATUS_SDCARD_CHECK_BAD);
  261. vTaskDelay(2000 / portTICK_PERIOD_MS);
  262. return; // No way to continue without working SD card!
  263. }
  264. // Init external PSRAM
  265. // ********************************************
  266. if (init_psram() != ESP_OK)
  267. {
  268. ESP_LOGE(TAG, "!!! Device init aborted at step: init_psram() !!!");
  269. set_system_statusflag(SYSTEM_STATUS_PSRAM_BAD);
  270. vTaskDelay(2000 / portTICK_PERIOD_MS);
  271. return; // No way to continue without working PSRAM!
  272. }
  273. // SD card: basic R/W check
  274. // ********************************************
  275. int iSDCardStatus = SDCardCheckRW();
  276. if (iSDCardStatus < 0)
  277. {
  278. if (iSDCardStatus <= -1 && iSDCardStatus >= -2)
  279. {
  280. // write error
  281. set_status_led(SDCARD_CHECK, 1, true);
  282. }
  283. else if (iSDCardStatus <= -3 && iSDCardStatus >= -5)
  284. {
  285. // read error
  286. set_status_led(SDCARD_CHECK, 2, true);
  287. }
  288. else if (iSDCardStatus == -6)
  289. {
  290. // delete error
  291. set_status_led(SDCARD_CHECK, 3, true);
  292. }
  293. ESP_LOGE(TAG, "!!! Device init aborted at step: SDCardCheckRW() !!!");
  294. set_system_statusflag(SYSTEM_STATUS_SDCARD_CHECK_BAD);
  295. vTaskDelay(2000 / portTICK_PERIOD_MS);
  296. return; // No way to continue without working SD card!
  297. }
  298. // SD card: Create log directories (if not already existing)
  299. // ********************************************
  300. LogFile.CreateLogDirectories(); // mandatory for logging + image saving
  301. // SD card: Create further mandatory directories (if not already existing)
  302. // Correct creation of these folders will be checked with function "SDCardCheckFolderFilePresence"
  303. // ********************************************
  304. make_dir("/sdcard/firmware"); // mandatory for OTA firmware update
  305. make_dir("/sdcard/img_tmp"); // mandatory for setting up alignment marks
  306. make_dir("/sdcard/demo"); // mandatory for demo mode
  307. make_dir("/sdcard/config/certs"); // mandatory for mqtt certificates
  308. // SD card: Check presence of some mandatory folders / files
  309. // ********************************************
  310. if (!SDCardCheckFolderFilePresence())
  311. {
  312. set_status_led(SDCARD_CHECK, 4, true);
  313. set_system_statusflag(SYSTEM_STATUS_FOLDER_CHECK_BAD); // reduced web interface going to be loaded
  314. }
  315. // ********************************************
  316. // Highlight start of logfile logging
  317. // Default Log Level: INFO -> Everything which needs to be logged during boot should be have level INFO, WARN OR ERROR
  318. // ********************************************
  319. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
  320. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "==================== Start ======================");
  321. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
  322. // Check for updates
  323. // ********************************************
  324. ESP_LOGI(TAG, "check for updates");
  325. CheckOTAUpdateStatus();
  326. if (!CheckOTAUpdateAvailability())
  327. {
  328. // Check reboot reason
  329. // ********************************************
  330. ESP_LOGI(TAG, "check reboot reason");
  331. CheckIsPlannedReboot();
  332. if (!getIsPlannedReboot() && (esp_reset_reason() == ESP_RST_PANIC))
  333. {
  334. // If system reboot was not triggered by user and reboot was caused by execption
  335. LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Reset reason: " + get_reset_reason());
  336. LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Device was rebooted due to a software exception! Log level is set to DEBUG until the next reboot. "
  337. "Flow init is delayed by 5 minutes to check the logs or do an OTA update");
  338. LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Keep device running until crash occurs again and check logs after device is up again");
  339. LogFile.setLogLevel(ESP_LOG_DEBUG);
  340. }
  341. else
  342. {
  343. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reset reason: " + get_reset_reason());
  344. }
  345. // Set CPU Frequency
  346. // ********************************************
  347. ESP_LOGI(TAG, "set CPU Frequency");
  348. setCpuFrequency();
  349. #ifdef CONFIG_SOC_TEMP_SENSOR_SUPPORTED
  350. ESP_LOGI(TAG, "init Tempsensor");
  351. init_tempsensor();
  352. #endif
  353. // Init camera
  354. // ********************************************
  355. ESP_LOGI(TAG, "init camera");
  356. if (init_camera() != ESP_OK)
  357. {
  358. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "!!! Error at step: init_camera() !!!");
  359. }
  360. // Check version information
  361. // ********************************************
  362. ESP_LOGI(TAG, "check version information");
  363. std::string versionFormated = getFwVersion() + ", Date/Time: " + std::string(BUILD_TIME) + ", Web UI: " + getHTMLversion();
  364. if (std::string(GIT_TAG) != "")
  365. {
  366. // We are on a tag, add it as prefix
  367. versionFormated = "Tag: '" + std::string(GIT_TAG) + "', " + versionFormated;
  368. }
  369. LogFile.WriteToFile(ESP_LOG_INFO, TAG, versionFormated);
  370. if (getHTMLcommit().substr(0, 7) == "?")
  371. {
  372. LogFile.WriteToFile(ESP_LOG_WARN, TAG, std::string("Failed to read file html/version.txt to parse Web UI version"));
  373. }
  374. if (getHTMLcommit().substr(0, 7) != std::string(GIT_REV).substr(0, 7))
  375. {
  376. // Compare the first 7 characters of both hashes
  377. LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Web UI version (" + getHTMLcommit() + ") does not match firmware version (" + std::string(GIT_REV) + ")");
  378. LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Recommendation: Repeat installation using AI-on-the-edge-device__update__*.zip");
  379. }
  380. // Start webserver + register handler
  381. // ********************************************
  382. ESP_LOGI(TAG, "starting Webserver");
  383. if (init_network() != ESP_OK)
  384. {
  385. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Webserver init failed. Device init aborted!");
  386. set_status_led(WLAN_INIT, 3, true);
  387. return;
  388. }
  389. // Set log level for wifi component to WARN level (default: INFO; only relevant for serial console)
  390. // ********************************************
  391. esp_log_level_set("wifi", ESP_LOG_WARN);
  392. // Init time (as early as possible, but SD card needs to be initialized)
  393. // ********************************************
  394. if (network_config.connection_type != NETWORK_CONNECTION_DISCONNECT)
  395. {
  396. ESP_LOGI(TAG, "setup Time");
  397. setupTime(); // NTP time service: Status of time synchronization will be checked after every round (server_tflite.cpp)
  398. }
  399. TickType_t xDelay = 2000 / portTICK_PERIOD_MS;
  400. ESP_LOGD(TAG, "main: sleep for: %ldms", (long)xDelay * CONFIG_FREERTOS_HZ / portTICK_PERIOD_MS);
  401. vTaskDelay(xDelay);
  402. // manual reset the time
  403. // ********************************************
  404. if (network_config.connection_type != NETWORK_CONNECTION_DISCONNECT)
  405. {
  406. ESP_LOGI(TAG, "manual reset the time");
  407. if (!time_manual_reset_sync())
  408. {
  409. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Manual Time Sync failed during startup");
  410. }
  411. }
  412. // Print Device info
  413. // ********************************************
  414. ESP_LOGI(TAG, "print Device info");
  415. esp_chip_info_t chipInfo;
  416. esp_chip_info(&chipInfo);
  417. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Device info: CPU cores: " + std::to_string(chipInfo.cores) + ", Chip revision: " + std::to_string(chipInfo.revision));
  418. // Print SD-Card info
  419. // ********************************************
  420. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "SD card info: Name: " + get_sd_card_name() + ", Capacity: " + get_sd_card_capacity() + "MB, Free: " + get_sd_card_free_partition_space() + "MB");
  421. xDelay = 2000 / portTICK_PERIOD_MS;
  422. ESP_LOGD(TAG, "main: sleep for: %ldms", (long)xDelay * CONFIG_FREERTOS_HZ / portTICK_PERIOD_MS);
  423. vTaskDelay(xDelay);
  424. // Check main init + start TFlite task
  425. // ********************************************
  426. ESP_LOGI(TAG, "check main init");
  427. if (get_system_status() == 0)
  428. {
  429. // No error flag is set
  430. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Initialization completed successfully");
  431. InitializeFlowTask();
  432. }
  433. else if (is_set_system_statusflag(SYSTEM_STATUS_CAM_FB_BAD) || is_set_system_statusflag(SYSTEM_STATUS_NTP_BAD))
  434. {
  435. // Non critical errors occured, we try to continue...
  436. LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Initialization completed with non-critical errors!");
  437. InitializeFlowTask();
  438. }
  439. else
  440. {
  441. // Any other error is critical and makes running the flow impossible. Init is going to abort.
  442. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Flow task start aborted. Loading reduced web interface...");
  443. }
  444. }
  445. }
  446. bool setCpuFrequency(void)
  447. {
  448. FILE *pFile = fopen(CONFIG_FILE, "r");
  449. if (pFile == NULL)
  450. {
  451. LogFile.WriteToFile(ESP_LOG_WARN, TAG, "No ConfigFile defined - exit setCpuFrequency()!");
  452. return false;
  453. }
  454. ClassFlow classFlow;
  455. std::string aktparamgraph = "";
  456. while (classFlow.GetNextParagraph(pFile, aktparamgraph))
  457. {
  458. if ((to_upper(aktparamgraph).compare("[SYSTEM]") == 0) || (to_upper(aktparamgraph).compare(";[SYSTEM]") == 0))
  459. {
  460. break;
  461. }
  462. }
  463. if ((to_upper(aktparamgraph).compare("[SYSTEM]") != 0) && (to_upper(aktparamgraph).compare(";[SYSTEM]") != 0))
  464. {
  465. fclose(pFile);
  466. return false;
  467. }
  468. string cpuFrequency = "160";
  469. esp_pm_config_t pm_config;
  470. std::vector<std::string> splitted;
  471. while (classFlow.getNextLine(pFile, &aktparamgraph) && !classFlow.isNewParagraph(aktparamgraph))
  472. {
  473. splitted = split_line(aktparamgraph);
  474. if (splitted.size() > 1)
  475. {
  476. std::string _param = to_upper(splitted[0]);
  477. if (_param == "CPUFREQUENCY")
  478. {
  479. cpuFrequency = splitted[1];
  480. }
  481. }
  482. }
  483. fclose(pFile);
  484. if (esp_pm_get_configuration(&pm_config) != ESP_OK)
  485. {
  486. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read CPU Frequency!");
  487. return false;
  488. }
  489. if (cpuFrequency == "160")
  490. {
  491. // 160 is the default
  492. // No change needed
  493. }
  494. else if (cpuFrequency == "240")
  495. {
  496. pm_config.max_freq_mhz = 240;
  497. pm_config.min_freq_mhz = pm_config.max_freq_mhz;
  498. if (esp_pm_configure(&pm_config) != ESP_OK)
  499. {
  500. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to set new CPU frequency!");
  501. return false;
  502. }
  503. }
  504. else
  505. {
  506. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Unknown CPU frequency: " + cpuFrequency + "! It must be 160 or 240!");
  507. return false;
  508. }
  509. if (esp_pm_get_configuration(&pm_config) == ESP_OK)
  510. {
  511. LogFile.WriteToFile(ESP_LOG_INFO, TAG, string("CPU frequency: ") + to_string(pm_config.max_freq_mhz) + " MHz");
  512. }
  513. return true;
  514. }