lp_core.c 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "sdkconfig.h"
  7. #include "esp_log.h"
  8. #include "soc/pmu_reg.h"
  9. #include "soc/lp_aon_reg.h"
  10. #include "soc/lpperi_reg.h"
  11. #include "hal/misc.h"
  12. #include "ulp_common.h"
  13. #include "ulp_lp_core.h"
  14. #include "ulp_lp_core_memory_shared.h"
  15. #include "ulp_lp_core_lp_timer_shared.h"
  16. const static char* TAG = "ulp-lp-core";
  17. esp_err_t ulp_lp_core_run(ulp_lp_core_cfg_t* cfg)
  18. {
  19. if (!cfg->wakeup_source) {
  20. ESP_LOGE(TAG, "No valid wakeup source specified");
  21. return ESP_ERR_INVALID_ARG;
  22. }
  23. ulp_lp_core_memory_shared_cfg_t* shared_mem = ulp_lp_core_memory_shared_cfg_get();
  24. /* Enable LP-Core */
  25. REG_CLR_BIT(LP_AON_LPCORE_REG, LP_AON_LPCORE_DISABLE);
  26. /* Allow LP core to access LP memory during sleep */
  27. REG_CLR_BIT(LP_AON_LPBUS_REG, LP_AON_FAST_MEM_MUX_SEL);
  28. REG_SET_BIT(LP_AON_LPBUS_REG, LP_AON_FAST_MEM_MUX_SEL_UPDATE);
  29. /* Enable stall at sleep request*/
  30. REG_SET_FIELD(PMU_LP_CPU_PWR0_REG, PMU_LP_CPU_SLP_STALL_EN, 1);
  31. /* Enable reset after wake-up */
  32. REG_SET_BIT(PMU_LP_CPU_PWR0_REG, PMU_LP_CPU_SLP_RESET_EN);
  33. /* Set wake-up sources */
  34. REG_SET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_WAKEUP_EN, cfg->wakeup_source);
  35. /* Enable JTAG debugging */
  36. REG_CLR_BIT(LPPERI_CPU_REG, LPPERI_LPCORE_DBGM_UNAVALIABLE);
  37. if (cfg->wakeup_source & ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU) {
  38. REG_SET_FIELD(PMU_HP_LP_CPU_COMM_REG, PMU_HP_TRIGGER_LP, 1);
  39. }
  40. if (cfg->wakeup_source & ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER) {
  41. if (!cfg->lp_timer_sleep_duration_us) {
  42. ESP_LOGI(TAG, "LP timer specified as wakeup source, but no sleep duration set. ULP will only wake-up once unless it calls ulp_lp_core_lp_timer_set_wakeup_time()");
  43. }
  44. shared_mem->sleep_duration_us = cfg->lp_timer_sleep_duration_us;
  45. /* Set first wakeup alarm */
  46. ulp_lp_core_lp_timer_set_wakeup_time(cfg->lp_timer_sleep_duration_us);
  47. }
  48. if (cfg->wakeup_source & (ULP_LP_CORE_WAKEUP_SOURCE_LP_UART | ULP_LP_CORE_WAKEUP_SOURCE_LP_IO | ULP_LP_CORE_WAKEUP_SOURCE_ETM )) {
  49. ESP_LOGE(TAG, "Wake-up source not yet supported");
  50. return ESP_ERR_INVALID_ARG;
  51. }
  52. return ESP_OK;
  53. }
  54. esp_err_t ulp_lp_core_load_binary(const uint8_t* program_binary, size_t program_size_bytes)
  55. {
  56. if (program_binary == NULL) {
  57. return ESP_ERR_INVALID_ARG;
  58. }
  59. if (program_size_bytes > CONFIG_ULP_COPROC_RESERVE_MEM) {
  60. return ESP_ERR_INVALID_SIZE;
  61. }
  62. /* Turn off LP CPU before loading binary */
  63. ulp_lp_core_stop();
  64. uint8_t* base = (uint8_t*) RTC_SLOW_MEM;
  65. //Start by clearing memory reserved with zeros, this will also will initialize the bss:
  66. hal_memset(base, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
  67. hal_memcpy(base, program_binary, program_size_bytes);
  68. return ESP_OK;
  69. }
  70. void ulp_lp_core_stop(void)
  71. {
  72. /* Disable wake-up source and put lp core to sleep */
  73. REG_SET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_WAKEUP_EN, 0);
  74. REG_SET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_SLEEP_REQ, 1);
  75. }