esp_dma_utils.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /*
  2. * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <sys/param.h>
  7. #include <inttypes.h>
  8. #include <string.h>
  9. #include "sdkconfig.h"
  10. #include "esp_check.h"
  11. #include "esp_log.h"
  12. #include "esp_heap_caps.h"
  13. #include "esp_memory_utils.h"
  14. #include "esp_dma_utils.h"
  15. #include "esp_private/esp_cache_private.h"
  16. #include "soc/soc_caps.h"
  17. static const char *TAG = "dma_utils";
  18. _Static_assert(ESP_DMA_MALLOC_FLAG_PSRAM == ESP_CACHE_MALLOC_FLAG_PSRAM);
  19. #define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
  20. esp_err_t esp_dma_malloc(size_t size, uint32_t flags, void **out_ptr, size_t *actual_size)
  21. {
  22. ESP_RETURN_ON_FALSE_ISR(out_ptr, ESP_ERR_INVALID_ARG, TAG, "null pointer");
  23. esp_err_t ret = ESP_OK;
  24. #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
  25. ret = esp_cache_aligned_malloc(size, flags | ESP_CACHE_MALLOC_FLAG_DMA, out_ptr, actual_size);
  26. #else
  27. if (flags & ESP_DMA_MALLOC_FLAG_PSRAM) {
  28. ret = esp_cache_aligned_malloc(size, flags | ESP_CACHE_MALLOC_FLAG_DMA, out_ptr, actual_size);
  29. } else {
  30. size = ALIGN_UP_BY(size, 4);
  31. void *ptr = heap_caps_aligned_alloc(4, size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
  32. ESP_RETURN_ON_FALSE_ISR(ptr, ESP_ERR_NO_MEM, TAG, "no enough heap memory");
  33. *out_ptr = ptr;
  34. if (actual_size) {
  35. *actual_size = size;
  36. }
  37. }
  38. #endif
  39. return ret;
  40. }
  41. esp_err_t esp_dma_calloc(size_t n, size_t size, uint32_t flags, void **out_ptr, size_t *actual_size)
  42. {
  43. ESP_RETURN_ON_FALSE_ISR(out_ptr, ESP_ERR_INVALID_ARG, TAG, "null pointer");
  44. esp_err_t ret = ESP_FAIL;
  45. size_t size_bytes = 0;
  46. bool ovf = false;
  47. ovf = __builtin_mul_overflow(n, size, &size_bytes);
  48. ESP_RETURN_ON_FALSE_ISR(!ovf, ESP_ERR_INVALID_ARG, TAG, "wrong size, total size overflow");
  49. void *ptr = NULL;
  50. ret = esp_dma_malloc(size_bytes, flags, &ptr, actual_size);
  51. if (ret == ESP_OK) {
  52. memset(ptr, 0, size_bytes);
  53. *out_ptr = ptr;
  54. }
  55. return ret;
  56. }
  57. bool esp_dma_is_buffer_aligned(const void *ptr, size_t size, esp_dma_buf_location_t location)
  58. {
  59. assert(ptr);
  60. uint32_t flags = ESP_CACHE_MALLOC_FLAG_DMA;
  61. if (location == ESP_DMA_BUF_LOCATION_INTERNAL) {
  62. if (!esp_ptr_dma_capable(ptr) || !esp_ptr_dma_capable(ptr + size - 1)) {
  63. return false;
  64. }
  65. } else {
  66. #if !SOC_PSRAM_DMA_CAPABLE
  67. return false;
  68. #endif
  69. if (!esp_ptr_external_ram(ptr) || !esp_ptr_external_ram(ptr + size - 1)) {
  70. return false;
  71. }
  72. flags |= ESP_DMA_MALLOC_FLAG_PSRAM;
  73. }
  74. bool is_aligned = false;
  75. #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
  76. size_t cache_alignment = 0;
  77. esp_err_t ret = esp_cache_get_alignment(flags, &cache_alignment);
  78. assert(ret == ESP_OK);
  79. if (((intptr_t)ptr % cache_alignment == 0) && (size % cache_alignment == 0)) {
  80. is_aligned = true;
  81. }
  82. #else
  83. (void)size;
  84. if ((intptr_t)ptr % 4 == 0) {
  85. is_aligned = true;
  86. }
  87. #endif
  88. return is_aligned;
  89. }