phy_init.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <stddef.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <stdbool.h>
  18. #include <sys/lock.h>
  19. #include "rom/ets_sys.h"
  20. #include "rom/rtc.h"
  21. #include "soc/rtc.h"
  22. #include "soc/dport_reg.h"
  23. #include "esp_err.h"
  24. #include "esp_phy_init.h"
  25. #include "esp_system.h"
  26. #include "esp_log.h"
  27. #include "nvs.h"
  28. #include "nvs_flash.h"
  29. #include "sdkconfig.h"
  30. #include "freertos/FreeRTOS.h"
  31. #include "freertos/portmacro.h"
  32. #include "phy.h"
  33. #include "phy_init_data.h"
  34. #include "esp_coexist.h"
  35. #include "driver/periph_ctrl.h"
  36. static const char* TAG = "phy_init";
  37. /* Count value to indicate if there is peripheral that has initialized PHY and RF */
  38. static int s_phy_rf_init_count = 0;
  39. static _lock_t s_phy_rf_init_lock;
  40. uint32_t IRAM_ATTR phy_enter_critical(void)
  41. {
  42. return portENTER_CRITICAL_NESTED();
  43. }
  44. void IRAM_ATTR phy_exit_critical(uint32_t level)
  45. {
  46. portEXIT_CRITICAL_NESTED(level);
  47. }
  48. esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,
  49. esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data)
  50. {
  51. assert((s_phy_rf_init_count <= 1) && (s_phy_rf_init_count >= 0));
  52. _lock_acquire(&s_phy_rf_init_lock);
  53. if (s_phy_rf_init_count == 0) {
  54. // Enable WiFi/BT common peripheral clock
  55. periph_module_enable(PERIPH_WIFI_BT_COMMON_MODULE);
  56. ESP_LOGV(TAG, "register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d",
  57. init_data, calibration_data, mode);
  58. phy_set_wifi_mode_only(0);
  59. if (calibration_data != NULL) {
  60. uint8_t mac[6];
  61. esp_efuse_mac_get_default(mac);
  62. memcpy(&calibration_data->opaque[4], mac, 6);
  63. }
  64. register_chipv7_phy(init_data, calibration_data, mode);
  65. coex_bt_high_prio();
  66. } else {
  67. #if CONFIG_SW_COEXIST_ENABLE
  68. coex_init();
  69. #endif
  70. }
  71. s_phy_rf_init_count++;
  72. _lock_release(&s_phy_rf_init_lock);
  73. return ESP_OK;
  74. }
  75. esp_err_t esp_phy_rf_deinit(void)
  76. {
  77. assert((s_phy_rf_init_count <= 2) && (s_phy_rf_init_count >= 1));
  78. _lock_acquire(&s_phy_rf_init_lock);
  79. if (s_phy_rf_init_count == 1) {
  80. // Disable PHY and RF.
  81. phy_close_rf();
  82. // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware RNG
  83. periph_module_disable(PERIPH_WIFI_BT_COMMON_MODULE);
  84. } else {
  85. #if CONFIG_SW_COEXIST_ENABLE
  86. coex_deinit();
  87. #endif
  88. }
  89. s_phy_rf_init_count--;
  90. _lock_release(&s_phy_rf_init_lock);
  91. return ESP_OK;
  92. }
  93. // PHY init data handling functions
  94. #if CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
  95. #include "esp_partition.h"
  96. const esp_phy_init_data_t* esp_phy_get_init_data()
  97. {
  98. const esp_partition_t* partition = esp_partition_find_first(
  99. ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL);
  100. if (partition == NULL) {
  101. ESP_LOGE(TAG, "PHY data partition not found");
  102. return NULL;
  103. }
  104. ESP_LOGD(TAG, "loading PHY init data from partition at offset 0x%x", partition->address);
  105. size_t init_data_store_length = sizeof(phy_init_magic_pre) +
  106. sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
  107. uint8_t* init_data_store = (uint8_t*) malloc(init_data_store_length);
  108. if (init_data_store == NULL) {
  109. ESP_LOGE(TAG, "failed to allocate memory for PHY init data");
  110. return NULL;
  111. }
  112. esp_err_t err = esp_partition_read(partition, 0, init_data_store, init_data_store_length);
  113. if (err != ESP_OK) {
  114. ESP_LOGE(TAG, "failed to read PHY data partition (0x%x)", err);
  115. return NULL;
  116. }
  117. if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 ||
  118. memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post),
  119. PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) {
  120. ESP_LOGE(TAG, "failed to validate PHY data partition");
  121. return NULL;
  122. }
  123. ESP_LOGD(TAG, "PHY data partition validated");
  124. return (const esp_phy_init_data_t*) (init_data_store + sizeof(phy_init_magic_pre));
  125. }
  126. void esp_phy_release_init_data(const esp_phy_init_data_t* init_data)
  127. {
  128. free((uint8_t*) init_data - sizeof(phy_init_magic_pre));
  129. }
  130. #else // CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
  131. // phy_init_data.h will declare static 'phy_init_data' variable initialized with default init data
  132. const esp_phy_init_data_t* esp_phy_get_init_data()
  133. {
  134. ESP_LOGD(TAG, "loading PHY init data from application binary");
  135. return &phy_init_data;
  136. }
  137. void esp_phy_release_init_data(const esp_phy_init_data_t* init_data)
  138. {
  139. // no-op
  140. }
  141. #endif // CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
  142. // PHY calibration data handling functions
  143. static const char* PHY_NAMESPACE = "phy";
  144. static const char* PHY_CAL_VERSION_KEY = "cal_version";
  145. static const char* PHY_CAL_MAC_KEY = "cal_mac";
  146. static const char* PHY_CAL_DATA_KEY = "cal_data";
  147. static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle,
  148. esp_phy_calibration_data_t* out_cal_data);
  149. static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle,
  150. const esp_phy_calibration_data_t* cal_data);
  151. esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_data)
  152. {
  153. nvs_handle handle;
  154. esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle);
  155. if (err == ESP_ERR_NVS_NOT_INITIALIZED) {
  156. ESP_LOGE(TAG, "%s: NVS has not been initialized. "
  157. "Call nvs_flash_init before starting WiFi/BT.", __func__);
  158. } else if (err != ESP_OK) {
  159. ESP_LOGD(TAG, "%s: failed to open NVS namespace (0x%x)", __func__, err);
  160. return err;
  161. }
  162. err = load_cal_data_from_nvs_handle(handle, out_cal_data);
  163. nvs_close(handle);
  164. return err;
  165. }
  166. esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data)
  167. {
  168. nvs_handle handle;
  169. esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle);
  170. if (err != ESP_OK) {
  171. ESP_LOGD(TAG, "%s: failed to open NVS namespace (0x%x)", __func__, err);
  172. return err;
  173. }
  174. else {
  175. err = store_cal_data_to_nvs_handle(handle, cal_data);
  176. nvs_close(handle);
  177. return err;
  178. }
  179. }
  180. static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle,
  181. esp_phy_calibration_data_t* out_cal_data)
  182. {
  183. esp_err_t err;
  184. uint32_t cal_data_version;
  185. err = nvs_get_u32(handle, PHY_CAL_VERSION_KEY, &cal_data_version);
  186. if (err != ESP_OK) {
  187. ESP_LOGD(TAG, "%s: failed to get cal_version (0x%x)", __func__, err);
  188. return err;
  189. }
  190. uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
  191. ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
  192. if (cal_data_version != cal_format_version) {
  193. ESP_LOGD(TAG, "%s: expected calibration data format %d, found %d",
  194. __func__, cal_format_version, cal_data_version);
  195. return ESP_FAIL;
  196. }
  197. uint8_t cal_data_mac[6];
  198. size_t length = sizeof(cal_data_mac);
  199. err = nvs_get_blob(handle, PHY_CAL_MAC_KEY, cal_data_mac, &length);
  200. if (err != ESP_OK) {
  201. ESP_LOGD(TAG, "%s: failed to get cal_mac (0x%x)", __func__, err);
  202. return err;
  203. }
  204. if (length != sizeof(cal_data_mac)) {
  205. ESP_LOGD(TAG, "%s: invalid length of cal_mac (%d)", __func__, length);
  206. return ESP_ERR_INVALID_SIZE;
  207. }
  208. uint8_t sta_mac[6];
  209. esp_efuse_mac_get_default(sta_mac);
  210. if (memcmp(sta_mac, cal_data_mac, sizeof(sta_mac)) != 0) {
  211. ESP_LOGE(TAG, "%s: calibration data MAC check failed: expected " \
  212. MACSTR ", found " MACSTR,
  213. __func__, MAC2STR(sta_mac), MAC2STR(cal_data_mac));
  214. return ESP_FAIL;
  215. }
  216. length = sizeof(*out_cal_data);
  217. err = nvs_get_blob(handle, PHY_CAL_DATA_KEY, out_cal_data, &length);
  218. if (err != ESP_OK) {
  219. ESP_LOGE(TAG, "%s: failed to get cal_data(0x%x)", __func__, err);
  220. return err;
  221. }
  222. if (length != sizeof(*out_cal_data)) {
  223. ESP_LOGD(TAG, "%s: invalid length of cal_data (%d)", __func__, length);
  224. return ESP_ERR_INVALID_SIZE;
  225. }
  226. return ESP_OK;
  227. }
  228. static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle,
  229. const esp_phy_calibration_data_t* cal_data)
  230. {
  231. esp_err_t err;
  232. uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
  233. ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
  234. err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version);
  235. if (err != ESP_OK) {
  236. return err;
  237. }
  238. uint8_t sta_mac[6];
  239. esp_efuse_mac_get_default(sta_mac);
  240. err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac));
  241. if (err != ESP_OK) {
  242. return err;
  243. }
  244. err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data));
  245. return err;
  246. }
  247. void esp_phy_load_cal_and_init(void)
  248. {
  249. esp_phy_calibration_data_t* cal_data =
  250. (esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1);
  251. if (cal_data == NULL) {
  252. ESP_LOGE(TAG, "failed to allocate memory for RF calibration data");
  253. abort();
  254. }
  255. const esp_phy_init_data_t* init_data = esp_phy_get_init_data();
  256. if (init_data == NULL) {
  257. ESP_LOGE(TAG, "failed to obtain PHY init data");
  258. abort();
  259. }
  260. #ifdef CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE
  261. esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL;
  262. if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) {
  263. calibration_mode = PHY_RF_CAL_NONE;
  264. }
  265. esp_err_t err = esp_phy_load_cal_data_from_nvs(cal_data);
  266. if (err != ESP_OK) {
  267. ESP_LOGW(TAG, "failed to load RF calibration data (0x%x), falling back to full calibration", err);
  268. calibration_mode = PHY_RF_CAL_FULL;
  269. }
  270. esp_phy_rf_init(init_data, calibration_mode, cal_data);
  271. if (calibration_mode != PHY_RF_CAL_NONE && err != ESP_OK) {
  272. err = esp_phy_store_cal_data_to_nvs(cal_data);
  273. } else {
  274. err = ESP_OK;
  275. }
  276. #else
  277. esp_phy_rf_init(init_data, PHY_RF_CAL_FULL, cal_data);
  278. #endif
  279. esp_phy_release_init_data(init_data);
  280. free(cal_data); // PHY maintains a copy of calibration data, so we can free this
  281. }