Skip to content

Commit 88e3ea2

Browse files
committed
Merge branch 'bugfix/cache_invalidate_should_respect_size' into 'master'
bugfix(cache): cache invalidate operation should respect the cache line size See merge request espressif/esp-idf!36805
2 parents 44a27d3 + 5558028 commit 88e3ea2

File tree

5 files changed

+36
-45
lines changed

5 files changed

+36
-45
lines changed

components/esp_driver_bitscrambler/src/bitscrambler_loopback.c

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include "esp_check.h"
2121
#include "esp_heap_caps.h"
2222
#include "esp_cache.h"
23-
#include "esp_dma_utils.h"
2423
#include "esp_memory_utils.h"
2524

2625
const static char *TAG = "bs_loop";
@@ -209,18 +208,21 @@ esp_err_t bitscrambler_loopback_run(bitscrambler_handle_t bs, void *buffer_in, s
209208
return ESP_ERR_INVALID_SIZE;
210209
}
211210

212-
//Casual check to see if the buffer is aligned to cache requirements.
213-
esp_dma_mem_info_t dma_mem_info = {
214-
.dma_alignment_bytes = 4
215-
};
216-
//Note: we know the size of the data, but not of the buffer that contains it, so we set length=0.
217-
if (!esp_dma_is_buffer_alignment_satisfied(buffer_in, 0, dma_mem_info)) {
218-
ESP_LOGE(TAG, "buffer_in not aligned to DMA requirements");
219-
return ESP_ERR_INVALID_ARG;
211+
int int_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
212+
int ext_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA);
213+
214+
bool need_cache_sync = esp_ptr_internal(buffer_in) ? (int_mem_cache_line_size > 0) : (ext_mem_cache_line_size > 0);
215+
if (need_cache_sync) {
216+
//Note: we add the ESP_CACHE_MSYNC_FLAG_UNALIGNED flag for now as otherwise esp_cache_msync will complain about
217+
//the size not being aligned... we miss out on a check to see if the address is aligned this way. This needs to
218+
//be improved, but potentially needs a fix in esp_cache_msync not to check the size.
219+
ESP_RETURN_ON_ERROR(esp_cache_msync(buffer_in, length_bytes_in, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED),
220+
TAG, "failed in cache sync for input buffer");
220221
}
221-
if (!esp_dma_is_buffer_alignment_satisfied(buffer_out, 0, dma_mem_info)) {
222-
ESP_LOGE(TAG, "buffer_out not aligned to DMA requirements");
223-
return ESP_ERR_INVALID_ARG;
222+
need_cache_sync = esp_ptr_internal(buffer_out) ? (int_mem_cache_line_size > 0) : (ext_mem_cache_line_size > 0);
223+
if (need_cache_sync) {
224+
ESP_RETURN_ON_ERROR(esp_cache_msync(buffer_out, length_bytes_out, ESP_CACHE_MSYNC_FLAG_DIR_M2C),
225+
TAG, "failed in cache sync for output buffer");
224226
}
225227

226228
gdma_reset(bsl->rx_channel);
@@ -247,17 +249,6 @@ esp_err_t bitscrambler_loopback_run(bitscrambler_handle_t bs, void *buffer_in, s
247249
};
248250
gdma_link_mount_buffers(bsl->rx_link_list, 0, &out_buf_mount_config, 1, NULL);
249251

250-
int int_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
251-
int ext_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA);
252-
253-
bool need_cache_sync = esp_ptr_internal(buffer_in) ? (int_mem_cache_line_size > 0) : (ext_mem_cache_line_size > 0);
254-
if (need_cache_sync) {
255-
//Note: we add the ESP_CACHE_MSYNC_FLAG_UNALIGNED flag for now as otherwise esp_cache_msync will complain about
256-
//the size not being aligned... we miss out on a check to see if the address is aligned this way. This needs to
257-
//be improved, but potentially needs a fix in esp_cache_msync not to check the size.
258-
esp_cache_msync(buffer_in, length_bytes_in, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
259-
}
260-
261252
gdma_start(bsl->rx_channel, gdma_link_get_head_addr(bsl->rx_link_list));
262253
gdma_start(bsl->tx_channel, gdma_link_get_head_addr(bsl->tx_link_list));
263254
bitscrambler_start(bs);
@@ -272,11 +263,6 @@ esp_err_t bitscrambler_loopback_run(bitscrambler_handle_t bs, void *buffer_in, s
272263
ret = ESP_ERR_TIMEOUT;
273264
}
274265

275-
need_cache_sync = esp_ptr_internal(buffer_out) ? (int_mem_cache_line_size > 0) : (ext_mem_cache_line_size > 0);
276-
if (need_cache_sync) {
277-
esp_cache_msync(buffer_out, length_bytes_out, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
278-
}
279-
280266
if (bytes_written) {
281267
*bytes_written = gdma_link_count_buffer_size_till_eof(bsl->rx_link_list, 0);
282268
}

components/esp_driver_bitscrambler/test_apps/bitscrambler/main/test_bitscrambler.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ BITSCRAMBLER_PROGRAM(bitscrambler_program_timeout, "timeout");
1616

1717
TEST_CASE("Basic BitScrambler I/O", "[bs]")
1818
{
19-
int len = 0x4010;
19+
int len = 0x4000;
2020
uint8_t *data_in = heap_caps_aligned_calloc(8, 1, len, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
2121
uint8_t *data_out = heap_caps_aligned_calloc(8, 1, len, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
2222
TEST_ASSERT_NOT_NULL(data_in);

components/esp_hw_support/dma/esp_dma_utils.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,12 @@ esp_err_t esp_dma_split_rx_buffer_to_cache_aligned(void *rx_buffer, size_t buffe
101101
// invalidate the aligned buffer if necessary
102102
for (int i = 0; i < 3; i++) {
103103
if (need_cache_sync[i]) {
104-
esp_err_t res = esp_cache_msync(align_buf_array->aligned_buffer[i].aligned_buffer, align_buf_array->aligned_buffer[i].length, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
104+
size_t sync_size = align_buf_array->aligned_buffer[i].length;
105+
if (sync_size < split_line_size) {
106+
// If the buffer is smaller than the cache line size, we need to sync the whole buffer
107+
sync_size = split_line_size;
108+
}
109+
esp_err_t res = esp_cache_msync(align_buf_array->aligned_buffer[i].aligned_buffer, sync_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
105110
ESP_GOTO_ON_ERROR(res, err, TAG, "failed to do cache sync");
106111
}
107112
}

components/esp_mm/esp_cache.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ esp_err_t esp_cache_msync(void *addr, size_t size, int flags)
108108
}
109109
uint32_t cache_line_size = cache_hal_get_cache_line_size(cache_level, cache_type);
110110
if ((flags & ESP_CACHE_MSYNC_FLAG_UNALIGNED) == 0) {
111-
bool aligned_addr = (((uint32_t)addr % cache_line_size) == 0);
112-
ESP_RETURN_ON_FALSE_ISR(aligned_addr, ESP_ERR_INVALID_ARG, TAG, "start address: 0x%" PRIx32 " is not aligned with cache line size (0x%" PRIx32 ")B", (uint32_t)addr, cache_line_size);
111+
bool aligned_addr = (((uint32_t)addr % cache_line_size) == 0) && ((size % cache_line_size) == 0);
112+
ESP_RETURN_ON_FALSE_ISR(aligned_addr, ESP_ERR_INVALID_ARG, TAG, "start address: 0x%" PRIx32 ", or the size: 0x%" PRIx32 " is(are) not aligned with cache line size (0x%" PRIx32 ")B", (uint32_t)addr, (uint32_t)size, cache_line_size);
113113
}
114114

115115
s_acquire_mutex_from_task_context();

examples/peripherals/bitscrambler/main/bitscrambler_example_main.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,25 @@ void app_main(void)
3131
{
3232
ESP_LOGI(TAG, "BitScrambler example main");
3333

34-
uint8_t *data_in, *data_out;
35-
int len = sizeof(testdata);
34+
size_t test_data_len = sizeof(testdata);
35+
uint8_t* result_buf = heap_caps_calloc(test_data_len, 1, MALLOC_CAP_DMA);
36+
assert(result_buf);
3637

37-
data_in = heap_caps_calloc(len, 1, MALLOC_CAP_DMA);
38-
data_out = heap_caps_calloc(len, 1, MALLOC_CAP_DMA);
39-
assert(data_in);
40-
assert(data_out);
41-
memcpy(data_in, testdata, len);
38+
size_t result_buf_size = heap_caps_get_allocated_size(result_buf);
39+
assert(result_buf_size >= test_data_len);
4240

4341
bitscrambler_handle_t bs;
44-
ESP_ERROR_CHECK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_I2S0, len));
42+
ESP_ERROR_CHECK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_I2S0, result_buf_size));
4543
ESP_ERROR_CHECK(bitscrambler_load_program(bs, bitscrambler_program_example));
46-
size_t size;
47-
ESP_ERROR_CHECK(bitscrambler_loopback_run(bs, data_in, len, data_out, len, &size));
44+
45+
size_t result_len;
46+
// we can even use a const array as the input data because the DMA can read data from the Flash region
47+
ESP_ERROR_CHECK(bitscrambler_loopback_run(bs, (void*)testdata, test_data_len, result_buf, result_buf_size, &result_len));
4848
bitscrambler_free(bs);
4949

50-
printf("BitScrambler program complete. Input %d, output %d bytes:\n", len, size);
51-
for (int i = 0; i < size; i++) {
52-
printf("%02X ", data_out[i]);
50+
printf("BitScrambler program complete. Input %zu, output %zu bytes:\n", test_data_len, result_len);
51+
for (size_t i = 0; i < result_len; i++) {
52+
printf("%02X ", result_buf[i]);
5353
if ((i & 7) == 7) {
5454
printf("\n");
5555
}

0 commit comments

Comments
 (0)