mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
Merge branch 'fix/psram-ecc-mspi-dma-align' into 'master'
fix(mspi): handle PSRAM ECC DMA alignment across MSPI users Closes IDF-15850, IDF-15910, and IDF-15700 See merge request espressif/esp-idf!49987
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "hal/dma2d_types.h"
|
||||
|
||||
@@ -269,6 +271,47 @@ typedef struct {
|
||||
*/
|
||||
esp_err_t dma2d_set_transfer_ability(dma2d_channel_handle_t dma2d_chan, const dma2d_transfer_ability_t *ability);
|
||||
|
||||
/**
|
||||
* @brief Get DMA2D buffer alignment constraint for a specific buffer
|
||||
*
|
||||
* @note On invalid arguments, returns an impossible alignment (BIT(31)).
|
||||
*
|
||||
* @param[in] buffer Buffer address
|
||||
* @return Alignment requirement in bytes
|
||||
*/
|
||||
size_t dma2d_get_buffer_alignment_constraint(const void *buffer);
|
||||
|
||||
/**
|
||||
* @brief Get alignment required when allocating a buffer for DMA2D access
|
||||
*
|
||||
* Use this before the buffer exists (e.g. `heap_caps_aligned_calloc`).
|
||||
* Unlike `dma2d_get_buffer_alignment_constraint`, this returns the worst-case
|
||||
* DMA2D/MSPI alignment rather than treating a NULL pointer as invalid.
|
||||
*
|
||||
* @return Alignment requirement in bytes (1 if no strict alignment is needed)
|
||||
*/
|
||||
size_t dma2d_get_alloc_alignment(void);
|
||||
|
||||
/**
|
||||
* @brief Check whether a 2D DMA transaction window satisfies DMA2D/MSPI alignment
|
||||
*
|
||||
* Under Flash Encryption / PSRAM ECC, MSPI requires each AXI access to be aligned in both
|
||||
* address and size. For a 2D transfer that means:
|
||||
* - buffer base address aligned to N bytes
|
||||
* - bytes-per-line (`pic_width * bpp/8`) aligned, so every next line starts on an N-byte boundary
|
||||
* - transfer width (`blk_width * bpp/8`) aligned
|
||||
* - horizontal window offset (`offset_x * bpp/8`) aligned
|
||||
*
|
||||
* @param[in] buf Buffer base address
|
||||
* @param[in] pic_width Picture / stride width in pixels
|
||||
* @param[in] blk_width Transfer block width in pixels
|
||||
* @param[in] offset_x Horizontal offset of the block in pixels
|
||||
* @param[in] bit_depth Bits per pixel
|
||||
* @return true if the transaction satisfies the alignment constraints
|
||||
*/
|
||||
bool dma2d_check_transaction_alignment_constraint(const void *buf, uint32_t pic_width, uint32_t blk_width,
|
||||
uint32_t offset_x, uint32_t bit_depth);
|
||||
|
||||
/**
|
||||
* @brief A collection of color space conversion (CSC) items that each 2D-DMA channel could apply
|
||||
*/
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "esp_etm.h"
|
||||
#include "hal/gdma_types.h"
|
||||
#include "esp_err.h"
|
||||
@@ -221,23 +222,50 @@ typedef struct {
|
||||
esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transfer_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Get the alignment constraints for internal and external memory
|
||||
* @brief Alignment constraints of a configured GDMA channel
|
||||
*
|
||||
* @note You should call this function after `gdma_config_transfer`, the later one can
|
||||
* adjust the alignment constraints based on various conditions, e.g. burst size, memory encryption, etc.
|
||||
* @note You can use returned alignment value to validate if a DMA buffer provided by the upper layer meets the constraints.
|
||||
* @note The returned alignment doesn't take the cache line size into account, if you want to do aligned memory allocation,
|
||||
* you should align the buffer size to the cache line size by yourself if the DMA buffer is behind a cache.
|
||||
* @note Prefer this when allocating DMA buffers. Once a concrete buffer address is available,
|
||||
* use `gdma_get_buffer_alignment_constraint` for the effective runtime constraint of that region.
|
||||
* @note For allocation from external memory:
|
||||
* - Use `ext_enc_mem_alignment` as the safe default (worst-case MSPI encryption/ECC).
|
||||
* - Use `ext_no_enc_mem_alignment` when intentionally targeting no-encryption external memory (e.g. no-enc PSRAM).
|
||||
* @note The returned alignment doesn't take the cache line size into account. If the DMA buffer is behind a cache,
|
||||
* align the buffer size to the cache line size yourself when needed.
|
||||
*/
|
||||
typedef struct {
|
||||
size_t int_mem_alignment; /*!< Alignment for internal memory */
|
||||
size_t ext_enc_mem_alignment; /*!< Alignment for external memory including MSPI encryption/ECC constraints */
|
||||
size_t ext_no_enc_mem_alignment; /*!< Alignment for external memory without MSPI region-specific constraints */
|
||||
} gdma_channel_alignment_info_t;
|
||||
|
||||
/**
|
||||
* @brief Get the alignment constraints for a configured GDMA channel
|
||||
*
|
||||
* @note Call this function after `gdma_config_transfer`.
|
||||
*
|
||||
* @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel`
|
||||
* @param[out] int_mem_alignment Internal memory alignment
|
||||
* @param[out] ext_mem_alignment External memory alignment
|
||||
* @param[out] info Alignment constraints of the channel
|
||||
* @return
|
||||
* - ESP_OK: Get alignment constraints successfully
|
||||
* - ESP_ERR_INVALID_ARG: Get alignment constraints failed because of invalid argument
|
||||
* - ESP_FAIL: Get alignment constraints failed because of other error
|
||||
*/
|
||||
esp_err_t gdma_get_alignment_constraints(gdma_channel_handle_t dma_chan, size_t *int_mem_alignment, size_t *ext_mem_alignment);
|
||||
esp_err_t gdma_get_channel_alignment_constraints(gdma_channel_handle_t dma_chan, gdma_channel_alignment_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Get the effective alignment constraint for a specific DMA buffer
|
||||
*
|
||||
* @note Call this function after `gdma_config_transfer`.
|
||||
* @note Combines GDMA channel constraints with MSPI constraints of the actual buffer region.
|
||||
* External no-encryption PSRAM buffers can therefore use their real runtime constraint
|
||||
* instead of a generic worst-case MSPI alignment.
|
||||
* @note The returned alignment doesn't take the cache line size into account.
|
||||
* @note On invalid arguments, returns an impossible value (BIT(31)).
|
||||
*
|
||||
* @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel`
|
||||
* @param[in] buffer DMA buffer address
|
||||
* @return Effective buffer alignment in bytes
|
||||
*/
|
||||
size_t gdma_get_buffer_alignment_constraint(gdma_channel_handle_t dma_chan, const void *buffer);
|
||||
|
||||
/**
|
||||
* @brief Apply channel strategy for GDMA channel
|
||||
|
||||
@@ -82,7 +82,9 @@ typedef struct {
|
||||
gdma_final_node_link_type_t mark_final: 2; /*!< Specify the next item of the final item of this mount.
|
||||
For the other items that not the final one, it will be linked to the next item automatically and this field takes no effect.
|
||||
Note, the final item here does not mean the last item in the link list. It is `start_item_index + num_items - 1` */
|
||||
uint32_t bypass_buffer_align_check: 1; /*!< Whether to bypass the buffer alignment check.
|
||||
uint32_t bypass_buffer_addr_align_check: 1; /*!< Whether to bypass the buffer address alignment check.
|
||||
Only enable it when you know what you are doing. */
|
||||
uint32_t bypass_buffer_size_align_check: 1; /*!< Whether to bypass the buffer size alignment check.
|
||||
Only enable it when you know what you are doing. */
|
||||
} flags; //!< Flags for buffer mount configurations
|
||||
} gdma_buffer_mount_config_t;
|
||||
|
||||
Reference in New Issue
Block a user