parlio_common.c 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <sys/lock.h>
  7. #include "sdkconfig.h"
  8. #if CONFIG_PARLIO_ENABLE_DEBUG_LOG
  9. // The local log level must be defined before including esp_log.h
  10. // Set the maximum log level for this source file
  11. #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
  12. #endif
  13. #include "esp_log.h"
  14. #include "esp_check.h"
  15. #include "clk_ctrl_os.h"
  16. #include "soc/rtc.h"
  17. #include "soc/parlio_periph.h"
  18. #include "hal/parlio_ll.h"
  19. #include "esp_private/esp_clk.h"
  20. #include "parlio_private.h"
  21. static const char *TAG = "parlio";
  22. typedef struct parlio_platform_t {
  23. _lock_t mutex; // platform level mutex lock
  24. parlio_group_t *groups[SOC_PARLIO_GROUPS]; // array of parallel IO group instances
  25. int group_ref_counts[SOC_PARLIO_GROUPS]; // reference count used to protect group install/uninstall
  26. } parlio_platform_t;
  27. static parlio_platform_t s_platform; // singleton platform
  28. parlio_group_t *parlio_acquire_group_handle(int group_id)
  29. {
  30. bool new_group = false;
  31. parlio_group_t *group = NULL;
  32. // prevent install parlio group concurrently
  33. _lock_acquire(&s_platform.mutex);
  34. if (!s_platform.groups[group_id]) {
  35. group = heap_caps_calloc(1, sizeof(parlio_group_t), PARLIO_MEM_ALLOC_CAPS);
  36. if (group) {
  37. new_group = true;
  38. s_platform.groups[group_id] = group;
  39. group->group_id = group_id;
  40. group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
  41. PARLIO_RCC_ATOMIC() {
  42. parlio_ll_enable_bus_clock(group_id, true);
  43. parlio_ll_reset_register(group_id);
  44. }
  45. // hal layer initialize
  46. parlio_hal_init(&group->hal);
  47. }
  48. } else { // group already install
  49. group = s_platform.groups[group_id];
  50. }
  51. if (group) {
  52. // someone acquired the group handle means we have a new object that refer to this group
  53. s_platform.group_ref_counts[group_id]++;
  54. }
  55. _lock_release(&s_platform.mutex);
  56. if (new_group) {
  57. ESP_LOGD(TAG, "new group(%d) at %p", group_id, group);
  58. }
  59. return group;
  60. }
  61. void parlio_release_group_handle(parlio_group_t *group)
  62. {
  63. int group_id = group->group_id;
  64. bool do_deinitialize = false;
  65. _lock_acquire(&s_platform.mutex);
  66. s_platform.group_ref_counts[group_id]--;
  67. if (s_platform.group_ref_counts[group_id] == 0) {
  68. do_deinitialize = true;
  69. s_platform.groups[group_id] = NULL;
  70. // hal layer deinitialize
  71. parlio_hal_deinit(&group->hal);
  72. PARLIO_RCC_ATOMIC() {
  73. parlio_ll_enable_bus_clock(group_id, false);
  74. }
  75. free(group);
  76. }
  77. _lock_release(&s_platform.mutex);
  78. if (do_deinitialize) {
  79. ESP_LOGD(TAG, "del group(%d)", group_id);
  80. }
  81. }