esp_ieee802154_dev.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. /*
  2. * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <string.h>
  7. #include "freertos/portmacro.h"
  8. #include "soc/periph_defs.h"
  9. #include "soc/soc.h"
  10. #include "soc/ieee802154_periph.h"
  11. #include "esp_private/esp_modem_clock.h"
  12. #include "esp_check.h"
  13. #include "esp_coex_i154.h"
  14. #include "esp_err.h"
  15. #include "esp_log.h"
  16. #include "esp_timer.h"
  17. #include "esp_ieee802154_ack.h"
  18. #include "esp_ieee802154_dev.h"
  19. #include "esp_ieee802154_frame.h"
  20. #include "esp_ieee802154_pib.h"
  21. #include "esp_ieee802154_sec.h"
  22. #include "esp_ieee802154_util.h"
  23. #include "esp_ieee802154_timer.h"
  24. #include "hal/ieee802154_ll.h"
  25. #include "esp_attr.h"
  26. #include "esp_phy_init.h"
  27. #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
  28. #include "esp_pm.h"
  29. #include "esp_private/esp_clk.h"
  30. #include "esp_private/sleep_retention.h"
  31. static bool s_rf_closed = false;
  32. #if SOC_PM_RETENTION_HAS_CLOCK_BUG
  33. #define IEEE802154_LINK_OWNER ENTRY(3)
  34. #else
  35. #define IEEE802154_LINK_OWNER ENTRY(0) | ENTRY(2)
  36. #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG
  37. #endif
  38. #define CCA_DETECTION_TIME 8
  39. extern void bt_bb_set_zb_tx_on_delay(uint16_t time);
  40. IEEE802154_STATIC volatile ieee802154_state_t s_ieee802154_state;
  41. static uint8_t *s_tx_frame = NULL;
  42. static uint8_t s_rx_frame[CONFIG_IEEE802154_RX_BUFFER_SIZE][127 + 1 + 1]; // +1: len, +1: for dma test
  43. static esp_ieee802154_frame_info_t s_rx_frame_info[CONFIG_IEEE802154_RX_BUFFER_SIZE];
  44. static uint8_t s_rx_index = 0;
  45. static uint8_t s_enh_ack_frame[128];
  46. static uint8_t s_recent_rx_frame_info_index;
  47. static portMUX_TYPE s_ieee802154_spinlock = portMUX_INITIALIZER_UNLOCKED;
  48. static esp_err_t ieee802154_sleep_init(void);
  49. static void ieee802154_rf_enable(void);
  50. static IRAM_ATTR void event_end_process(void)
  51. {
  52. ieee802154_etm_channel_clear(IEEE802154_ETM_CHANNEL0);
  53. ieee802154_etm_channel_clear(IEEE802154_ETM_CHANNEL1);
  54. ieee802154_ll_set_transmit_security(false);
  55. ieee802154_timer0_stop();
  56. }
  57. #if !CONFIG_IEEE802154_TEST
  58. static IRAM_ATTR void receive_ack_timeout_timer_start(uint32_t duration)
  59. {
  60. ieee802154_ll_enable_events(IEEE802154_EVENT_TIMER0_OVERFLOW);
  61. ieee802154_timer0_set_threshold(duration);
  62. ieee802154_timer0_start();
  63. }
  64. #endif
  65. static void ieee802154_rx_frame_info_update(void)
  66. {
  67. uint8_t len = s_rx_frame[s_rx_index][0];
  68. int8_t rssi = s_rx_frame[s_rx_index][len - 1]; // crc is not written to rx buffer
  69. uint8_t lqi = s_rx_frame[s_rx_index][len];
  70. s_rx_frame_info[s_rx_index].channel = ieee802154_freq_to_channel(ieee802154_ll_get_freq());
  71. s_rx_frame_info[s_rx_index].rssi = rssi;
  72. s_rx_frame_info[s_rx_index].lqi = lqi;
  73. s_recent_rx_frame_info_index = s_rx_index;
  74. }
  75. int8_t ieee802154_get_recent_rssi(void)
  76. {
  77. return s_rx_frame_info[s_recent_rx_frame_info_index].rssi;
  78. }
  79. uint8_t ieee802154_get_recent_lqi(void)
  80. {
  81. return s_rx_frame_info[s_recent_rx_frame_info_index].lqi;
  82. }
  83. IEEE802154_STATIC void set_next_rx_buffer(void)
  84. {
  85. if (s_rx_frame[s_rx_index][0] != 0) {
  86. s_rx_index++;
  87. if (s_rx_index == CONFIG_IEEE802154_RX_BUFFER_SIZE) {
  88. s_rx_index = 0;
  89. }
  90. memset(s_rx_frame[s_rx_index], 0, sizeof(s_rx_frame[s_rx_index]));
  91. }
  92. ieee802154_ll_set_rx_addr((uint8_t *)&s_rx_frame[s_rx_index]);
  93. }
  94. static bool stop_rx(void)
  95. {
  96. ieee802154_ll_events events;
  97. ieee802154_set_cmd(IEEE802154_CMD_STOP);
  98. events = ieee802154_ll_get_events();
  99. if (events & IEEE802154_EVENT_RX_DONE) {
  100. esp_ieee802154_receive_done((uint8_t *)s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
  101. }
  102. ieee802154_ll_clear_events(IEEE802154_EVENT_RX_DONE | IEEE802154_EVENT_RX_ABORT | IEEE802154_EVENT_RX_SFD_DONE);
  103. return true;
  104. }
  105. static bool stop_tx_ack(void)
  106. {
  107. ieee802154_set_cmd(IEEE802154_CMD_STOP);
  108. esp_ieee802154_receive_done((uint8_t *)s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
  109. ieee802154_ll_clear_events(IEEE802154_EVENT_ACK_TX_DONE | IEEE802154_EVENT_RX_ABORT | IEEE802154_EVENT_TX_SFD_DONE); // ZB-81: clear TX_SFD_DONE event
  110. return true;
  111. }
  112. static bool stop_tx(void)
  113. {
  114. ieee802154_ll_events events;
  115. ieee802154_set_cmd(IEEE802154_CMD_STOP);
  116. events = ieee802154_ll_get_events();
  117. if (s_ieee802154_state == IEEE802154_STATE_TX_ENH_ACK) {
  118. // if current operation is sending 2015 Enh-ack, SW should create the receive-done event.
  119. esp_ieee802154_receive_done((uint8_t *)s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
  120. ieee802154_ll_clear_events(IEEE802154_EVENT_ACK_TX_DONE);
  121. } else if ((events & IEEE802154_EVENT_TX_DONE) && (!ieee802154_frame_is_ack_required(s_tx_frame) || !ieee802154_ll_get_rx_auto_ack())) {
  122. // if the tx is already done, and the frame is not ack request OR auto ack rx is disabled.
  123. esp_ieee802154_transmit_done(s_tx_frame, NULL, NULL);
  124. } else {
  125. esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_ABORT);
  126. }
  127. ieee802154_ll_clear_events(IEEE802154_EVENT_TX_DONE | IEEE802154_EVENT_TX_ABORT | IEEE802154_EVENT_TX_SFD_DONE);
  128. return true;
  129. }
  130. static bool stop_cca(void)
  131. {
  132. ieee802154_set_cmd(IEEE802154_CMD_STOP);
  133. ieee802154_ll_clear_events(IEEE802154_EVENT_ED_DONE | IEEE802154_EVENT_RX_ABORT);
  134. return true;
  135. }
  136. static bool stop_tx_cca(void)
  137. {
  138. stop_tx(); // in case the transmission already started
  139. ieee802154_ll_clear_events(IEEE802154_EVENT_TX_ABORT);
  140. return true;
  141. }
  142. static bool stop_rx_ack(void)
  143. {
  144. ieee802154_ll_events events;
  145. ieee802154_set_cmd(IEEE802154_CMD_STOP);
  146. events = ieee802154_ll_get_events();
  147. ieee802154_timer0_stop();
  148. ieee802154_ll_disable_events(IEEE802154_EVENT_TIMER0_OVERFLOW);
  149. if (events & IEEE802154_EVENT_ACK_RX_DONE) {
  150. esp_ieee802154_transmit_done(s_tx_frame, (uint8_t *)&s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
  151. } else {
  152. esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_NO_ACK);
  153. }
  154. ieee802154_ll_clear_events(IEEE802154_EVENT_ACK_RX_DONE | IEEE802154_EVENT_RX_SFD_DONE | IEEE802154_EVENT_TX_ABORT);
  155. return true;
  156. }
  157. static bool stop_ed(void)
  158. {
  159. ieee802154_set_cmd(IEEE802154_CMD_STOP);
  160. ieee802154_ll_clear_events(IEEE802154_EVENT_ED_DONE | IEEE802154_EVENT_RX_ABORT);
  161. return true;
  162. }
  163. IEEE802154_STATIC bool stop_current_operation(void)
  164. {
  165. event_end_process();
  166. switch (s_ieee802154_state) {
  167. case IEEE802154_STATE_DISABLE:
  168. break;
  169. case IEEE802154_STATE_IDLE:
  170. ieee802154_ll_set_cmd(IEEE802154_CMD_STOP);
  171. break;
  172. case IEEE802154_STATE_SLEEP:
  173. // Do nothing
  174. break;
  175. case IEEE802154_STATE_RX:
  176. stop_rx();
  177. break;
  178. case IEEE802154_STATE_TX_ACK:
  179. stop_tx_ack();
  180. break;
  181. case IEEE802154_STATE_TX_CCA:
  182. stop_tx_cca();
  183. break;
  184. case IEEE802154_STATE_CCA:
  185. stop_cca();
  186. break;
  187. case IEEE802154_STATE_TX:
  188. case IEEE802154_STATE_TX_ENH_ACK:
  189. stop_tx();
  190. break;
  191. case IEEE802154_STATE_RX_ACK:
  192. stop_rx_ack();
  193. break;
  194. case IEEE802154_STATE_ED:
  195. stop_ed();
  196. break;
  197. default:
  198. IEEE802154_ASSERT(false);
  199. break;
  200. }
  201. return true;
  202. }
  203. static void enable_rx(void)
  204. {
  205. set_next_rx_buffer();
  206. IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_RX);
  207. ieee802154_set_cmd(IEEE802154_CMD_RX_START);
  208. ieee802154_set_state(IEEE802154_STATE_RX);
  209. }
  210. static IRAM_ATTR void next_operation(void)
  211. {
  212. if (ieee802154_pib_get_rx_when_idle()) {
  213. enable_rx();
  214. } else {
  215. ieee802154_set_state(IEEE802154_STATE_IDLE);
  216. }
  217. }
  218. static void isr_handle_timer0_done(void)
  219. {
  220. #if !CONFIG_IEEE802154_TEST
  221. if (s_ieee802154_state == IEEE802154_STATE_RX_ACK) {
  222. esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_NO_ACK);
  223. next_operation();
  224. }
  225. #else
  226. esp_ieee802154_timer0_done();
  227. #endif
  228. }
  229. static void isr_handle_timer1_done(void)
  230. {
  231. // timer 1 is now unused.
  232. #if CONFIG_IEEE802154_TEST
  233. esp_ieee802154_timer1_done();
  234. #endif
  235. }
  236. static IRAM_ATTR void isr_handle_tx_done(void)
  237. {
  238. event_end_process();
  239. if (s_ieee802154_state == IEEE802154_STATE_TX_ENH_ACK) {
  240. esp_ieee802154_receive_done((uint8_t *)s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
  241. next_operation();
  242. } else {
  243. if (s_ieee802154_state == IEEE802154_STATE_TEST_TX) {
  244. esp_ieee802154_transmit_done(s_tx_frame, NULL, NULL);
  245. next_operation();
  246. } else if (s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA) {
  247. if (ieee802154_frame_is_ack_required(s_tx_frame) && ieee802154_ll_get_rx_auto_ack()) {
  248. ieee802154_set_state(IEEE802154_STATE_RX_ACK);
  249. #if !CONFIG_IEEE802154_TEST
  250. receive_ack_timeout_timer_start(200000); // 200ms for receive ack timeout
  251. #endif
  252. } else {
  253. esp_ieee802154_transmit_done(s_tx_frame, NULL, NULL);
  254. next_operation();
  255. }
  256. }
  257. }
  258. }
  259. static IRAM_ATTR void isr_handle_rx_done(void)
  260. {
  261. event_end_process();
  262. ieee802154_rx_frame_info_update();
  263. if (s_ieee802154_state == IEEE802154_STATE_RX) {
  264. if (ieee802154_frame_is_ack_required(s_rx_frame[s_rx_index]) && ieee802154_frame_get_version(s_rx_frame[s_rx_index]) <= IEEE802154_FRAME_VERSION_1
  265. && ieee802154_ll_get_tx_auto_ack()) {
  266. // auto tx ack only works for the frame with version 0b00 and 0b01
  267. s_rx_frame_info[s_rx_index].pending = ieee802154_ack_config_pending_bit(s_rx_frame[s_rx_index]);
  268. ieee802154_set_state(IEEE802154_STATE_TX_ACK);
  269. } else if (ieee802154_frame_is_ack_required(s_rx_frame[s_rx_index]) && ieee802154_frame_get_version(s_rx_frame[s_rx_index]) == IEEE802154_FRAME_VERSION_2
  270. && ieee802154_ll_get_tx_enhance_ack()) {
  271. s_rx_frame_info[s_rx_index].pending = ieee802154_ack_config_pending_bit(s_rx_frame[s_rx_index]);
  272. // For 2015 enh-ack, SW should generate an enh-ack then send it manually
  273. if (esp_ieee802154_enh_ack_generator(s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index], s_enh_ack_frame) == ESP_OK) {
  274. #if !CONFIG_IEEE802154_TEST
  275. // Send the Enh-Ack frame if generator succeeds.
  276. ieee802154_ll_set_tx_addr(s_enh_ack_frame);
  277. s_tx_frame = s_enh_ack_frame;
  278. ieee802154_sec_update();
  279. ieee802154_ll_enhack_generate_done_notify();
  280. ieee802154_set_state(IEEE802154_STATE_TX_ENH_ACK);
  281. #endif
  282. } else {
  283. // Stop current process if generator returns errors.
  284. ieee802154_set_cmd(IEEE802154_CMD_STOP);
  285. esp_ieee802154_receive_done((uint8_t *)s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
  286. next_operation();
  287. }
  288. } else {
  289. esp_ieee802154_receive_done((uint8_t *)s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
  290. next_operation();
  291. }
  292. }
  293. }
  294. static IRAM_ATTR void isr_handle_ack_tx_done(void)
  295. {
  296. esp_ieee802154_receive_done((uint8_t *)s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
  297. next_operation();
  298. }
  299. static IRAM_ATTR void isr_handle_ack_rx_done(void)
  300. {
  301. ieee802154_timer0_stop();
  302. ieee802154_ll_disable_events(IEEE802154_EVENT_TIMER0_OVERFLOW);
  303. ieee802154_rx_frame_info_update();
  304. esp_ieee802154_transmit_done(s_tx_frame, (uint8_t *)&s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
  305. next_operation();
  306. }
  307. static IRAM_ATTR void isr_handle_rx_abort(void)
  308. {
  309. event_end_process();
  310. uint32_t rx_status = ieee802154_ll_get_rx_status();
  311. ieee802154_ll_rx_abort_reason_t rx_abort_reason = ieee802154_ll_get_rx_abort_reason();
  312. switch (rx_abort_reason) {
  313. case IEEE802154_RX_ABORT_BY_RX_STOP:
  314. case IEEE802154_RX_ABORT_BY_TX_ACK_STOP:
  315. case IEEE802154_RX_ABORT_BY_ED_STOP:
  316. // do nothing
  317. break;
  318. case IEEE802154_RX_ABORT_BY_SFD_TIMEOUT:
  319. case IEEE802154_RX_ABORT_BY_CRC_ERROR:
  320. case IEEE802154_RX_ABORT_BY_INVALID_LEN:
  321. case IEEE802154_RX_ABORT_BY_FILTER_FAIL:
  322. case IEEE802154_RX_ABORT_BY_NO_RSS:
  323. case IEEE802154_RX_ABORT_BY_UNEXPECTED_ACK:
  324. case IEEE802154_RX_ABORT_BY_RX_RESTART:
  325. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX);
  326. #if CONFIG_IEEE802154_TEST
  327. esp_ieee802154_receive_failed(rx_status);
  328. next_operation();
  329. #endif
  330. break;
  331. case IEEE802154_RX_ABORT_BY_COEX_BREAK:
  332. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX);
  333. esp_ieee802154_receive_failed(rx_status);
  334. break;
  335. case IEEE802154_RX_ABORT_BY_ED_ABORT:
  336. case IEEE802154_RX_ABORT_BY_ED_COEX_REJECT:
  337. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_ED || s_ieee802154_state == IEEE802154_STATE_CCA);
  338. esp_ieee802154_ed_failed(rx_status);
  339. next_operation();
  340. break;
  341. case IEEE802154_RX_ABORT_BY_TX_ACK_TIMEOUT:
  342. case IEEE802154_RX_ABORT_BY_TX_ACK_COEX_BREAK:
  343. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX_ACK || s_ieee802154_state == IEEE802154_STATE_TX_ENH_ACK);
  344. #if !CONFIG_IEEE802154_TEST
  345. esp_ieee802154_receive_done((uint8_t *)s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
  346. next_operation();
  347. #else
  348. esp_ieee802154_receive_failed(rx_status);
  349. #endif
  350. break;
  351. case IEEE802154_RX_ABORT_BY_ENHACK_SECURITY_ERROR:
  352. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX_ENH_ACK);
  353. #if !CONFIG_IEEE802154_TEST
  354. esp_ieee802154_receive_done((uint8_t *)s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
  355. next_operation();
  356. #else
  357. esp_ieee802154_receive_failed(rx_status);
  358. #endif
  359. break;
  360. default:
  361. IEEE802154_ASSERT(false);
  362. }
  363. }
  364. static IRAM_ATTR void isr_handle_tx_abort(void)
  365. {
  366. event_end_process();
  367. ieee802154_ll_tx_abort_reason_t tx_abort_reason = ieee802154_ll_get_tx_abort_reason();
  368. switch (tx_abort_reason) {
  369. case IEEE802154_TX_ABORT_BY_RX_ACK_STOP:
  370. case IEEE802154_TX_ABORT_BY_TX_STOP:
  371. // do nothing
  372. break;
  373. case IEEE802154_TX_ABORT_BY_RX_ACK_SFD_TIMEOUT:
  374. case IEEE802154_TX_ABORT_BY_RX_ACK_CRC_ERROR:
  375. case IEEE802154_TX_ABORT_BY_RX_ACK_INVALID_LEN:
  376. case IEEE802154_TX_ABORT_BY_RX_ACK_FILTER_FAIL:
  377. case IEEE802154_TX_ABORT_BY_RX_ACK_NO_RSS:
  378. case IEEE802154_TX_ABORT_BY_RX_ACK_COEX_BREAK:
  379. case IEEE802154_TX_ABORT_BY_RX_ACK_TYPE_NOT_ACK:
  380. case IEEE802154_TX_ABORT_BY_RX_ACK_RESTART:
  381. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX_ACK);
  382. esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_INVALID_ACK);
  383. break;
  384. case IEEE802154_TX_ABORT_BY_RX_ACK_TIMEOUT:
  385. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX_ACK);
  386. ieee802154_ll_disable_events(IEEE802154_EVENT_TIMER0_OVERFLOW);
  387. esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_NO_ACK);
  388. next_operation();
  389. break;
  390. case IEEE802154_TX_ABORT_BY_TX_COEX_BREAK:
  391. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA);
  392. esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_COEXIST);
  393. next_operation();
  394. break;
  395. case IEEE802154_TX_ABORT_BY_TX_SECURITY_ERROR:
  396. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA);
  397. esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_SECURITY);
  398. next_operation();
  399. break;
  400. case IEEE802154_TX_ABORT_BY_CCA_FAILED:
  401. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX_CCA);
  402. esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_ABORT);
  403. next_operation();
  404. break;
  405. case IEEE802154_TX_ABORT_BY_CCA_BUSY:
  406. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX_CCA);
  407. esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_CCA_BUSY);
  408. next_operation();
  409. break;
  410. default:
  411. IEEE802154_ASSERT(false);
  412. break;
  413. }
  414. }
  415. static IRAM_ATTR void isr_handle_ed_done(void)
  416. {
  417. if (s_ieee802154_state == IEEE802154_STATE_CCA) {
  418. esp_ieee802154_cca_done(ieee802154_ll_is_cca_busy());
  419. } else if (s_ieee802154_state == IEEE802154_STATE_ED) {
  420. esp_ieee802154_energy_detect_done(ieee802154_ll_get_ed_rss());
  421. }
  422. next_operation();
  423. }
  424. static void ieee802154_isr(void *arg)
  425. {
  426. ieee802154_ll_events events = ieee802154_ll_get_events();
  427. IEEE802154_PROBE(events);
  428. ieee802154_ll_clear_events(events);
  429. if (events & IEEE802154_EVENT_RX_SFD_DONE) {
  430. // IEEE802154_STATE_TX && IEEE802154_STATE_TX_CCA && IEEE802154_STATE_TX_ENH_ACK for isr processing delay
  431. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX || s_ieee802154_state == IEEE802154_STATE_RX_ACK || s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA || s_ieee802154_state == IEEE802154_STATE_TX_ENH_ACK);
  432. s_rx_frame_info[s_rx_index].timestamp = esp_timer_get_time();
  433. esp_ieee802154_receive_sfd_done();
  434. events &= (uint16_t)(~IEEE802154_EVENT_RX_SFD_DONE);
  435. }
  436. if (events & IEEE802154_EVENT_TX_SFD_DONE) {
  437. // ZB-81: IEEE802154_STATE_TX_ACK is also a possible state
  438. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA || s_ieee802154_state == IEEE802154_STATE_TEST_TX || s_ieee802154_state == IEEE802154_STATE_TX_ENH_ACK || s_ieee802154_state == IEEE802154_STATE_TX_ACK);
  439. esp_ieee802154_transmit_sfd_done(s_tx_frame);
  440. events &= (uint16_t)(~IEEE802154_EVENT_TX_SFD_DONE);
  441. }
  442. if (events & IEEE802154_EVENT_TX_DONE) {
  443. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA || s_ieee802154_state == IEEE802154_STATE_TEST_TX || s_ieee802154_state == IEEE802154_STATE_TX_ENH_ACK);
  444. isr_handle_tx_done();
  445. events &= (uint16_t)(~IEEE802154_EVENT_TX_DONE);
  446. }
  447. if (events & IEEE802154_EVENT_RX_DONE) {
  448. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX);
  449. isr_handle_rx_done();
  450. events &= (uint16_t)(~IEEE802154_EVENT_RX_DONE);
  451. }
  452. if (events & IEEE802154_EVENT_ACK_TX_DONE) {
  453. // IEEE802154_STATE_RX for isr processing delay
  454. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX_ACK || s_ieee802154_state == IEEE802154_STATE_RX || s_ieee802154_state == IEEE802154_STATE_TX_ENH_ACK);
  455. isr_handle_ack_tx_done();
  456. events &= (uint16_t)(~IEEE802154_EVENT_ACK_TX_DONE);
  457. }
  458. if (events & IEEE802154_EVENT_ACK_RX_DONE) {
  459. // IEEE802154_STATE_TX && IEEE802154_STATE_TX_CCA && IEEE802154_STATE_TX_ENH_ACK for isr processing delay
  460. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX_ACK || s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA || s_ieee802154_state == IEEE802154_STATE_TX_ENH_ACK);
  461. isr_handle_ack_rx_done();
  462. events &= (uint16_t)(~IEEE802154_EVENT_ACK_RX_DONE);
  463. }
  464. if (events & IEEE802154_EVENT_RX_ABORT) {
  465. isr_handle_rx_abort();
  466. events &= (uint16_t)(~IEEE802154_EVENT_RX_ABORT);
  467. }
  468. if (events & IEEE802154_EVENT_TX_ABORT) {
  469. isr_handle_tx_abort();
  470. events &= (uint16_t)(~IEEE802154_EVENT_TX_ABORT);
  471. }
  472. if (events & IEEE802154_EVENT_ED_DONE) {
  473. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_ED || s_ieee802154_state == IEEE802154_STATE_CCA);
  474. isr_handle_ed_done();
  475. events &= (uint16_t)(~IEEE802154_EVENT_ED_DONE);
  476. }
  477. if (events & IEEE802154_EVENT_TIMER0_OVERFLOW) {
  478. #if !CONFIG_IEEE802154_TEST
  479. IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX_ACK);
  480. #else
  481. extern bool ieee802154_timer0_test;
  482. IEEE802154_ASSERT(ieee802154_timer0_test || s_ieee802154_state == IEEE802154_STATE_RX_ACK);
  483. #endif
  484. isr_handle_timer0_done();
  485. events &= (uint16_t)(~IEEE802154_EVENT_TIMER0_OVERFLOW);
  486. }
  487. if (events & IEEE802154_EVENT_TIMER1_OVERFLOW) {
  488. isr_handle_timer1_done();
  489. events &= (uint16_t)(~IEEE802154_EVENT_TIMER1_OVERFLOW);
  490. }
  491. // all events should be handled
  492. IEEE802154_ASSERT(events == 0);
  493. }
  494. IEEE802154_STATIC IRAM_ATTR void ieee802154_enter_critical(void)
  495. {
  496. portENTER_CRITICAL(&s_ieee802154_spinlock);
  497. }
  498. IEEE802154_STATIC IRAM_ATTR void ieee802154_exit_critical(void)
  499. {
  500. portEXIT_CRITICAL(&s_ieee802154_spinlock);
  501. }
  502. void ieee802154_enable(void)
  503. {
  504. modem_clock_module_enable(ieee802154_periph.module);
  505. s_ieee802154_state = IEEE802154_STATE_IDLE;
  506. }
  507. void ieee802154_disable(void)
  508. {
  509. modem_clock_module_disable(ieee802154_periph.module);
  510. ieee802154_set_state(IEEE802154_STATE_DISABLE);
  511. }
  512. esp_err_t ieee802154_mac_init(void)
  513. {
  514. esp_err_t ret = ESP_OK;
  515. modem_clock_module_mac_reset(PERIPH_IEEE802154_MODULE); // reset ieee802154 MAC
  516. ieee802154_pib_init();
  517. ieee802154_ll_enable_events(IEEE802154_EVENT_MASK);
  518. #if !CONFIG_IEEE802154_TEST
  519. ieee802154_ll_disable_events((IEEE802154_EVENT_TIMER0_OVERFLOW) | (IEEE802154_EVENT_TIMER1_OVERFLOW));
  520. #endif
  521. ieee802154_ll_enable_tx_abort_events(BIT(IEEE802154_TX_ABORT_BY_RX_ACK_TIMEOUT - 1) | BIT(IEEE802154_TX_ABORT_BY_TX_COEX_BREAK - 1) | BIT(IEEE802154_TX_ABORT_BY_TX_SECURITY_ERROR - 1) | BIT(IEEE802154_TX_ABORT_BY_CCA_FAILED - 1) | BIT(IEEE802154_TX_ABORT_BY_CCA_BUSY - 1));
  522. ieee802154_ll_enable_rx_abort_events(BIT(IEEE802154_RX_ABORT_BY_TX_ACK_TIMEOUT - 1) | BIT(IEEE802154_RX_ABORT_BY_TX_ACK_COEX_BREAK - 1));
  523. ieee802154_ll_set_ed_sample_mode(IEEE802154_ED_SAMPLE_AVG);
  524. #if !CONFIG_IEEE802154_TEST && CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
  525. esp_coex_ieee802154_ack_pti_set(IEEE802154_MIDDLE);
  526. IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_IDLE);
  527. #else
  528. ieee802154_ll_disable_coex();
  529. #endif
  530. #if CONFIG_IDF_ENV_FPGA
  531. bt_bb_set_zb_tx_on_delay(80);
  532. #else
  533. bt_bb_set_zb_tx_on_delay(50);
  534. REG_WRITE(IEEE802154_RXON_DELAY_REG, 50);
  535. #endif
  536. memset(s_rx_frame, 0, sizeof(s_rx_frame));
  537. ieee802154_set_state(IEEE802154_STATE_IDLE);
  538. // TODO: Add flags for IEEE802154 ISR allocating. TZ-102
  539. ret = esp_intr_alloc(ieee802154_periph.irq_id, 0, ieee802154_isr, NULL, NULL);
  540. ESP_RETURN_ON_FALSE(ret == ESP_OK, ESP_FAIL, IEEE802154_TAG, "IEEE802154 MAC init failed");
  541. ESP_RETURN_ON_FALSE(ieee802154_sleep_init() == ESP_OK, ESP_FAIL, IEEE802154_TAG, "IEEE802154 MAC sleep init failed");
  542. return ret;
  543. }
  544. IEEE802154_STATIC void start_ed(uint32_t duration)
  545. {
  546. ieee802154_ll_enable_events(IEEE802154_EVENT_ED_DONE);
  547. ieee802154_ll_set_ed_duration(duration);
  548. ieee802154_set_cmd(IEEE802154_CMD_ED_START);
  549. }
  550. IEEE802154_STATIC void tx_init(const uint8_t *frame)
  551. {
  552. s_tx_frame = (uint8_t *)frame;
  553. stop_current_operation();
  554. ieee802154_pib_update();
  555. ieee802154_sec_update();
  556. ieee802154_ll_set_tx_addr(s_tx_frame);
  557. if (ieee802154_frame_is_ack_required(frame)) {
  558. // set rx pointer for ack frame
  559. set_next_rx_buffer();
  560. }
  561. }
  562. esp_err_t ieee802154_transmit(const uint8_t *frame, bool cca)
  563. {
  564. ieee802154_rf_enable();
  565. ieee802154_enter_critical();
  566. tx_init(frame);
  567. IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_TX);
  568. if (cca) {
  569. ieee802154_set_cmd(IEEE802154_CMD_CCA_TX_START);
  570. ieee802154_set_state(IEEE802154_STATE_TX_CCA);
  571. } else {
  572. ieee802154_set_cmd(IEEE802154_CMD_TX_START);
  573. ieee802154_set_state(IEEE802154_STATE_TX);
  574. }
  575. ieee802154_exit_critical();
  576. return ESP_OK;
  577. }
  578. static inline bool is_target_time_expired(uint32_t target, uint32_t now)
  579. {
  580. return (((now - target) & (1 << 31)) == 0);
  581. }
  582. esp_err_t ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time)
  583. {
  584. uint32_t tx_target_time;
  585. uint32_t current_time;
  586. ieee802154_rf_enable();
  587. tx_init(frame);
  588. IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_TX_AT);
  589. if (cca) {
  590. tx_target_time = time - IEEE802154_ED_TRIG_TX_RAMPUP_TIME_US;
  591. ieee802154_set_state(IEEE802154_STATE_TX_CCA);
  592. ieee802154_enter_critical();
  593. ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL0, ETM_EVENT_TIMER0_OVERFLOW, ETM_TASK_ED_TRIG_TX);
  594. current_time = (uint32_t)esp_timer_get_time();
  595. ieee802154_timer0_set_threshold((is_target_time_expired(tx_target_time, current_time) ? 0 : (tx_target_time - current_time))); //uint: 1us
  596. ieee802154_timer0_start();
  597. ieee802154_exit_critical();
  598. } else {
  599. tx_target_time = time - IEEE802154_TX_RAMPUP_TIME_US;
  600. if (ieee802154_frame_get_type(frame) == IEEE802154_FRAME_TYPE_ACK && ieee802154_frame_get_version(frame) == IEEE802154_FRAME_VERSION_2) {
  601. ieee802154_set_state(IEEE802154_STATE_TX_ENH_ACK);
  602. } else {
  603. ieee802154_set_state(IEEE802154_STATE_TX);
  604. }
  605. ieee802154_enter_critical();
  606. ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL0, ETM_EVENT_TIMER0_OVERFLOW, ETM_TASK_TX_START);
  607. current_time = (uint32_t)esp_timer_get_time();
  608. ieee802154_timer0_set_threshold((is_target_time_expired(tx_target_time, current_time) ? 0 : (tx_target_time - current_time))); //uint: 1us
  609. ieee802154_timer0_start();
  610. ieee802154_exit_critical();
  611. }
  612. return ESP_OK;
  613. }
  614. IEEE802154_STATIC void rx_init(void)
  615. {
  616. stop_current_operation();
  617. ieee802154_pib_update();
  618. }
  619. esp_err_t ieee802154_receive(void)
  620. {
  621. if (((s_ieee802154_state == IEEE802154_STATE_RX) || (s_ieee802154_state == IEEE802154_STATE_TX_ACK)) && (!ieee802154_pib_is_pending())) {
  622. // already in rx state, don't abort current rx operation
  623. return ESP_OK;
  624. }
  625. ieee802154_rf_enable();
  626. ieee802154_enter_critical();
  627. rx_init();
  628. enable_rx();
  629. ieee802154_exit_critical();
  630. return ESP_OK;
  631. }
  632. esp_err_t ieee802154_receive_at(uint32_t time)
  633. {
  634. uint32_t rx_target_time = time - IEEE802154_RX_RAMPUP_TIME_US;
  635. uint32_t current_time;
  636. ieee802154_rf_enable();
  637. rx_init();
  638. IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_RX_AT);
  639. set_next_rx_buffer();
  640. ieee802154_set_state(IEEE802154_STATE_RX);
  641. ieee802154_enter_critical();
  642. ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL1, ETM_EVENT_TIMER0_OVERFLOW, ETM_TASK_RX_START);
  643. current_time = (uint32_t)esp_timer_get_time();
  644. ieee802154_timer0_set_threshold((is_target_time_expired(rx_target_time, current_time) ? 0 : (rx_target_time - current_time))); //uint: 1us
  645. ieee802154_timer0_start();
  646. ieee802154_exit_critical();
  647. return ESP_OK;
  648. }
  649. static esp_err_t ieee802154_sleep_init(void)
  650. {
  651. esp_err_t err = ESP_OK;
  652. #if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE
  653. #define N_REGS_IEEE802154() (((IEEE802154_MAC_DATE_REG - IEEE802154_REG_BASE) / 4) + 1)
  654. const static sleep_retention_entries_config_t ieee802154_mac_regs_retention[] = {
  655. [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_IEEE802154_LINK(0x00), IEEE802154_REG_BASE, IEEE802154_REG_BASE, N_REGS_IEEE802154(), 0, 0), .owner = IEEE802154_LINK_OWNER },
  656. };
  657. err = sleep_retention_entries_create(ieee802154_mac_regs_retention, ARRAY_SIZE(ieee802154_mac_regs_retention), REGDMA_LINK_PRI_7, SLEEP_RETENTION_MODULE_802154_MAC);
  658. ESP_RETURN_ON_ERROR(err, IEEE802154_TAG, "failed to allocate memory for ieee802154 mac retention");
  659. ESP_LOGI(IEEE802154_TAG, "ieee802154 mac sleep retention initialization");
  660. #endif
  661. return err;
  662. }
  663. IRAM_ATTR static void ieee802154_rf_disable(void)
  664. {
  665. #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
  666. if (s_rf_closed == false) {
  667. esp_phy_disable(PHY_MODEM_IEEE802154);
  668. s_rf_closed = true;
  669. }
  670. #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
  671. }
  672. IRAM_ATTR static void ieee802154_rf_enable(void)
  673. {
  674. #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
  675. if (s_rf_closed) {
  676. esp_phy_enable(PHY_MODEM_IEEE802154);
  677. s_rf_closed = false;
  678. }
  679. #endif //CONFIG_FREERTOS_USE_TICKLESS_IDLE
  680. }
  681. esp_err_t ieee802154_sleep(void)
  682. {
  683. if (ieee802154_get_state() != IEEE802154_STATE_SLEEP) {
  684. ieee802154_enter_critical();
  685. stop_current_operation();
  686. ieee802154_set_state(IEEE802154_STATE_SLEEP);
  687. ieee802154_exit_critical();
  688. ieee802154_rf_disable(); // colse rf
  689. }
  690. return ESP_OK;
  691. }
  692. esp_err_t ieee802154_energy_detect(uint32_t duration)
  693. {
  694. ieee802154_rf_enable();
  695. ieee802154_enter_critical();
  696. stop_current_operation();
  697. ieee802154_pib_update();
  698. start_ed(duration);
  699. ieee802154_set_state(IEEE802154_STATE_ED);
  700. ieee802154_exit_critical();
  701. return ESP_OK;
  702. }
  703. esp_err_t ieee802154_cca(void)
  704. {
  705. ieee802154_rf_enable();
  706. ieee802154_enter_critical();
  707. stop_current_operation();
  708. ieee802154_pib_update();
  709. start_ed(CCA_DETECTION_TIME);
  710. ieee802154_set_state(IEEE802154_STATE_CCA);
  711. ieee802154_exit_critical();
  712. return ESP_OK;
  713. }
  714. ieee802154_state_t ieee802154_get_state(void)
  715. {
  716. return s_ieee802154_state;
  717. }