feat(dma): added APIs for dma specific malloc

This commit is contained in:
Armando 2023-09-08 14:54:45 +08:00
parent e8813ddd1d
commit 900aebd158
4 changed files with 135 additions and 6 deletions

View File

@ -34,7 +34,8 @@ if(NOT BOOTLOADER_BUILD)
"sar_periph_ctrl_common.c"
"port/${target}/io_mux.c"
"port/${target}/esp_clk_tree.c"
"port/esp_clk_tree_common.c")
"port/esp_clk_tree_common.c"
"dma/esp_dma_utils.c")
if(CONFIG_SOC_ADC_SUPPORTED)
list(APPEND srcs "adc_share_hw_ctrl.c")
@ -51,6 +52,8 @@ if(NOT BOOTLOADER_BUILD)
# [refactor-todo]: requires "driver" for GPIO and RTC (by sleep_gpio and sleep_modes)
list(APPEND priv_requires driver esp_timer)
list(APPEND priv_requires esp_mm)
if(CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S2)
list(APPEND srcs "rtc_wdt.c")
endif()

View File

@ -0,0 +1,69 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <sys/param.h>
#include <inttypes.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_check.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "esp_dma_utils.h"
#include "esp_private/esp_cache_private.h"
#include "soc/soc_caps.h"
static const char *TAG = "dma_utils";
_Static_assert(ESP_DMA_MALLOC_FLAG_PSRAM == ESP_CACHE_MALLOC_FLAG_PSRAM);
#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
esp_err_t esp_dma_malloc(size_t size, uint32_t flags, void **out_ptr, size_t *actual_size)
{
ESP_RETURN_ON_FALSE_ISR(out_ptr, ESP_ERR_INVALID_ARG, TAG, "null pointer");
esp_err_t ret = ESP_OK;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
ret = esp_cache_aligned_malloc(size, flags | ESP_CACHE_MALLOC_FLAG_DMA, out_ptr, actual_size);
#else
if (flags & ESP_DMA_MALLOC_FLAG_PSRAM) {
ret = esp_cache_aligned_malloc(size, flags | ESP_CACHE_MALLOC_FLAG_DMA, out_ptr, actual_size);
} else {
size = ALIGN_UP_BY(size, 4);
void *ptr = heap_caps_aligned_alloc(4, size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
ESP_RETURN_ON_FALSE_ISR(ptr, ESP_ERR_NO_MEM, TAG, "no enough heap memory");
*out_ptr = ptr;
if (actual_size) {
*actual_size = size;
}
}
#endif
return ret;
}
esp_err_t esp_dma_calloc(size_t n, size_t size, uint32_t flags, void **out_ptr, size_t *actual_size)
{
ESP_RETURN_ON_FALSE_ISR(out_ptr, ESP_ERR_INVALID_ARG, TAG, "null pointer");
esp_err_t ret = ESP_FAIL;
size_t size_bytes = 0;
bool ovf = false;
ovf = __builtin_mul_overflow(n, size, &size_bytes);
ESP_RETURN_ON_FALSE_ISR(!ovf, ESP_ERR_INVALID_ARG, TAG, "wrong size, total size overflow");
void *ptr = NULL;
ret = esp_dma_malloc(size_bytes, flags, &ptr, actual_size);
if (ret == ESP_OK) {
memset(ptr, 0, size_bytes);
*out_ptr = ptr;
}
return ret;
}

View File

@ -0,0 +1,57 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdlib.h>
#include <stdint.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* DMA malloc flags
*/
/**
* @brief Memory is in PSRAM
*/
#define ESP_DMA_MALLOC_FLAG_PSRAM BIT(0)
/**
* @brief Helper function for malloc a DMA capable memory buffer
*
* @param[in] size Size in bytes, the amount of memory to allocate
* @param[in] flags Flags, see `ESP_DMA_MALLOC_FLAG_x`
* @param[out] out_ptr A pointer to the memory allocated successfully
* @param[out] actual_size Actual size for allocation in bytes, when the size you specified doesn't meet the DMA alignment requirements, this value might be bigger than the size you specified. Set null if you don't care this value.
*
* @return
* - ESP_OK:
* - ESP_ERR_INVALID_ARG: Invalid argument
* - ESP_ERR_NO_MEM: No enough memory for allocation
*/
esp_err_t esp_dma_malloc(size_t size, uint32_t flags, void **out_ptr, size_t *actual_size);
/**
* @brief Helper function for calloc a DMA capable memory buffer
*
* @param[in] n Number of continuing chunks of memory to allocate
* @param[in] size Size of one chunk, in bytes
* @param[in] flags Flags, see `ESP_DMA_MALLOC_FLAG_x`
* @param[out] out_ptr A pointer to the memory allocated successfully
* @param[out] actual_size Actual size for allocation in bytes, when the size you specified doesn't meet the cache alignment requirements, this value might be bigger than the size you specified. Set null if you don't care this value.
*
* @return
* - ESP_OK:
* - ESP_ERR_INVALID_ARG: Invalid argument
* - ESP_ERR_NO_MEM: No enough memory for allocation
*/
esp_err_t esp_dma_calloc(size_t n, size_t size, uint32_t flags, void **out_ptr, size_t *actual_size);
#ifdef __cplusplus
}
#endif

View File

@ -17,6 +17,7 @@
#include "driver/i2c.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_dma_utils.h"
#include "lvgl.h"
#if CONFIG_EXAMPLE_LCD_TOUCH_CONTROLLER_GT911
#include "esp_lcd_touch_gt911.h"
@ -406,13 +407,12 @@ void app_main(void)
// it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized
lv_color_t *buf1 = NULL;
lv_color_t *buf2 = NULL;
uint32_t malloc_flags = 0;
#if CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM
buf1 = heap_caps_aligned_alloc(EXAMPLE_PSRAM_DATA_ALIGNMENT, EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
buf2 = heap_caps_aligned_alloc(EXAMPLE_PSRAM_DATA_ALIGNMENT, EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
#else
buf1 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
buf2 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
malloc_flags |= ESP_DMA_MALLOC_FLAG_PSRAM;
#endif // CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM
ESP_ERROR_CHECK(esp_dma_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), malloc_flags, (void *)&buf1, NULL));
ESP_ERROR_CHECK(esp_dma_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), malloc_flags, (void *)&buf2, NULL));
assert(buf1);
assert(buf2);
ESP_LOGI(TAG, "buf1@%p, buf2@%p", buf1, buf2);